Earlier quoted context omitted.
"the extra syntax in this case is not adding any extra information (to the compiler)." This actually isn't true in C++, because there could be many classes in scope that could take a list initializer like this. In Haskell, no literal with [] can "turn into" something besides a list, but that can happen in C++: vector items = {1,2,3,4}; int[] items = {1,2,3,4}; These have different types, so how would C++ know which o…
Your example, void foo() { auto items = {1,2,3,4}; return; } is the case of poorly designed syntax, in a truly Hindley-Milner system there is no expression which doesn't have a type. Now, we could add some syntax that screws that up, say: let v = I-HAVE-AN-AMBIGUOUS-TYPE in 0 But that's rather silly, isn't it? If a value isn't used then I would, personally, like my language to optimize it away. So why not ditch such…
C++11 and Boost - Succinct like Python
151–160 of 172 posts
Re: C++11 and Boost - Succinct like Python
#152Earlier quoted context omitted.
Yes, to_string would have been better The C-style cast is shorter, but less safe, so you should not use it: http://stackoverflow.com/questions/1609163/what-is-the-diffe... Yeah, I couldn't quite decide if I should include const refs. On the one hand, it is idiomatic, but on the other hand I didn't want to clutter the code with something that is just an optimization on paper.
How can a C-style cast from char to unsigned possibly be "less safe", and how could a different style of cast be more safe?
Re: C++11 and Boost - Succinct like Python
#153Earlier quoted context omitted.
Your example, void foo() { auto items = {1,2,3,4}; return; } is the case of poorly designed syntax, in a truly Hindley-Milner system there is no expression which doesn't have a type. Now, we could add some syntax that screws that up, say: let v = I-HAVE-AN-AMBIGUOUS-TYPE in 0 But that's rather silly, isn't it? If a value isn't used then I would, personally, like my language to optimize it away. So why not ditch such…
Having programmed Haskell for the last seven years (and C++ for zero) I have a fairly decent handle on what HM is all about. If all you had said is that the foundations of C++ are too far gone, there wouldn't be anything to discuss. But the foundations of C++ being what they are, there's no point being offended when unfixable things go unfixed. I love HM, but you can't just throw it in any old language simply because…
I suggest using a HM language when you start a new project.
Re: C++11 and Boost - Succinct like Python
#154Earlier quoted context omitted.
In most programming languages the [] operator allows one to access elements in a container. In this case, we are accessing the position "two colons minus one". I refuse to believe this makes any sort of sense for someone that has no deep knowledge of Python.
Lots of languages use [] with colon separators for array slicing, e.g. F#, Perl, Ruby. The idea that this syntax involves "deep knowledge" is laughable. Your criticism is analogous to me looking at "int* foo = bar()" and saying, hey, we're multiplying a type by a name! How ridiculous!
Re: C++11 and Boost - Succinct like Python
#155Earlier quoted context omitted.
"the extra syntax in this case is not adding any extra information (to the compiler)." This actually isn't true in C++, because there could be many classes in scope that could take a list initializer like this. In Haskell, no literal with [] can "turn into" something besides a list, but that can happen in C++: vector items = {1,2,3,4}; int[] items = {1,2,3,4}; These have different types, so how would C++ know which o…
Integers and Strings aren't edge cases. Their literals are polymorphic and typed. C++ could also type its list initializers with some polymorphic type (similar to Haskell's Num) but didn't do so. This is not inherent.
There are no polymorphic literals in ML, just polymorphic math operators, which is enough of a blight on the standard that OCaml discarded it and forces you to use different operators for real and integer arithmetic. And there's only one kind of string in both MLs.
Haskell's Num hierarchy is troublesome. They traded usability for + with complexity for /. It's extremely unlikely that you could write a program in Haskell that does much arithmetic and have it build correctly on the first try without any manifest typing. This is one reason students of Haskell find things so confusing: type declarations are necessary at the top level simply because the extensions and complexity of modern Haskell break HM if you try using it everywhere. Also, the class system in there is not especially mathematically correct, which leads to the numerous replacement Preludes that try to do a better job but haven't caught on.
Strings are edge cases because they are not polymorphic unless you enable OverloadedStrings. Once you do, you will either replace the built-in string with something else (ByteString or Text) or find yourself in the same kind of trouble you'd be in with Num.
Let me be clear: I'm not saying that these problems are showstoppers. They're really minor annoyances once you're experienced, though they contribute to confusion for beginners. The point I'm trying to make is that you can't just drop HM into any old language and expect it to work. A greater point would perhaps be that all languages have warts simply because they're large, complex beasts (Haskell and C++ especially) and it's unproductive to point to a missing feature in one and demand some sort of perfected version of the other's.
Re: C++11 and Boost - Succinct like Python
#156Periodically throwing some new ingredients into old soup to freshen it up can only extend the life of leftovers so far. There comes a time when, even with a handful of fresh veggies, it's no longer good soup. You need to toss out the leftovers, scrub the kettle, and start a fresh batch. You will still need C++ for dealing with all the legacy C++ out there, but if you are starting a new project, you ought to be able t…
Re: C++11 and Boost - Succinct like Python
#157Earlier quoted context omitted.
Integers and Strings aren't edge cases. Their literals are polymorphic and typed. C++ could also type its list initializers with some polymorphic type (similar to Haskell's Num) but didn't do so. This is not inherent.
They're not worth discussing because they're a counterintuitive mess rather than a case study of the glory of HM. Maybe edge case isn't the right word, but they're definitely not something I would hail as a perfect resounding success. There are no polymorphic literals in ML, just polymorphic math operators, which is enough of a blight on the standard that OCaml discarded it and forces you to use different operators f…
Do you really believe Num overloading is a counterintuitive mess? I disagree completely.
> OCaml discarded it and forces you to use different operators for real and integer arithmetic
Which is pretty terrible.
> Haskell's Num hierarchy is troublesome.
Yes, but that's an orthogonal issue.
> This is one reason students of Haskell find things so confusing: type declarations are necessary at the top level simply because the extensions and complexity of modern Haskell break HM if you try using it everywhere
That sounds like FUD to me, a heavy Haskell user. Type declarations at the top-level are generally necessary to avoid the dreaded MR and for documentation purposes. Modern Haskell doesn't heavily use extensions that require type annotations on the top-level.
> Strings are edge cases because they are not polymorphic unless you enable OverloadedStrings. Once you do, you will either replace the built-in string with something else (ByteString or Text) or find yourself in the same kind of trouble you'd be in with Num.
It lets me use literals for Lazy Text, Strict Text, and String with the same syntax, which is nice.
My point is merely that giving a type to a polymorphic initializer is possible, and C++ chose not to.
Re: C++11 and Boost - Succinct like Python
#158Earlier quoted context omitted.
And this is where I decide the language is too far developed on the wrong foundation. I cannot put up with type systems that don't have complete or near-complete type inference. I don't know why one would start a new project in a language that didn't support Hindley-Milner.
Wrong foundation? No. Foundation you don't want? Sure. Try to remember that Hindley-Milner is very hard to do outside of functional languages like ML and Haskell.
Furthermore, I assert that this truly is the wrong foundation. For new projects that must have OO, Scala provides local type inference and object orientation. If you're really hurting for some manual memory management, look at Rust [3] or Habit [2].
If we can recover the features we love on a new foundation that provides new features like type inference or memory-safety, then we've found a better foundation, IMHO.
[1] http://www.cs.ucla.edu/~palsberg/typeflow.html
Re: C++11 and Boost - Succinct like Python
#159Earlier quoted context omitted.
Even in Hindley-Miller type systems it is considered good practice to add types as documentation to top-level constructs (see Haskell). In Python it is also considered good practice to add argument and return type info in the doc string. In a dynamic language you would also have to add a unit test or two for cases for some of the things that the compiler can catch for you. Looking at the complete picture makes a lang…
> it is considered good practice to add types as documentation to top-level constructs But with type inference your tools can do that for you (e.g. C-u C-c C-t in haskell-mode).
Re: C++11 and Boost - Succinct like Python
#160Earlier quoted context omitted.
Here's an example: A co-worker looked at a function I wrote that converts a table to a tree, and he said to me, "I thought Python was supposed to be readable, but I have no idea what this is doing." See for yourself: https://gist.github.com/3988350
Manually capturing free variables via: def __init__(self, x, y, ..): self.x = x self.y = y Is so tedious and DRY-violating.