That said, I desperately miss static-typing and Hindley-Milner type inference... I keep searching for the perfect language.
EDIT: apparently someone did not like your comment. Some downvotes confound me.
To your questions:
OcaML: seems like a hack-ish [S]ML. There's a nice comparison between SML and OcaML here : http://adam.chlipala.net/mlcomp/ . I like SML's syntax, but OcaML made it too easy to be imperative and seemed too hackish. Most of the OcaML I've seen looks like weird C, but written in OcaML because it's F4ST3R.
F# : I run Linux... next!
Scala* : I can't stand it. I use Python for everyday coding and I really don't like the philosophy behind str(), len(), and friends, but it's otherwise straightforward. There's pretty much only 1 [reasonable] way to do things in Python. Scala seems like the evile lovechild of Perl and SML. Classes and "case Classes"? WTF? Type inferencing, but not powerful type inference? If you're going to move to Java++ without going too far toward Haskell, then Gosu or Mirah seem like better compromises. That said, I'm only investigated Scala [not coded in it], so my griefing is likely due to a lack of familiarity.
SML/MLTon: the syntax is 95% good but they should have embraced significant-whitespace wholeheartedly. Do they really need an "end"? But, generally, I really like SML's thinking. In particular, I'm rooting for SML by following Yeti (https://github.com/mth/yeti; but "case" is closed with "esac", really?!) and Roy (http://roy.brianmckenna.org/). Oh and I hate header files. Sooooo 1995...
Clojure: static typing. I want to believe, but the lack of static typing (including Hindley-Mindler type systems) seems like a short-cut. I think the static/dynamic typing argument is a relic of pre-good-static-typing system and I don't think that big, server-side languages should be dynamically and/or weakly typed. That said, Stuart, and his hair, are great.
Felix: interesting, but I see no mention of type inference, so have concerns about the type system. Also, the wiki is broken and that makes me think "dead project".
But, unfortunately, I want mature toolchains, libraries, etc, so, though I wrote a mid-sized web framework in Haskell, I'm one of those who is waiting for a functional language to emerge as the winner. Until then, I'll work in Python and will support Yeti and Roy.
* I've forgotten where I saw it, but Scala also had some bizarre rules around interpreting variables in case statements [or something] involving the case of the argument. I closed the book at that point. Haskell has special notations for special features, not special assumptions for normal features.
I feel your pain. The other thing that bothers me is that Mono developer(s?) have been extremely bone headed about tail recursion. Hey guys if you are reading this, sorry about the tone, but that needed saying. John Harrop can be quite a troll but he is right in calling Mono out on this. Their incorporations of futures and promises is indeed an attraction though. But then we only have a non-binding promise from Microsoft that they wont go after other implementations. Thats not a threat I would like to be under.
I really would love a multicore enable runtime for OCaML. I dont even ask for threads, just the ability to run some of the concurrency exposed by the functional semantics be (optionally) run in parallel without forking processes.
Yeti...I dont know, unless JVM includes proper tail calls I will always have this nagging sensation in my brain.
Felix, BTW is far from dead, in fact it is quite the opposite, its too intensively developed. The wiki is very new, so there would be some breakage there. The original website is stable. Oh it uses Hindley-Milner type inferencing.
From your comment it seems you would like the white space thing http://people.csail.mit.edu/mikelin/ocaml+twt/ I have never used it though.
Wonder if there is anything akin to P4Caml for SML to give you significant white space. But I think you will get over the syntax :) I have to work with arrays a lot, there SML is a bit more verbose.
Microsoft's official FAQ on their Community Promise explicitly states that it irrevocable and legally binding [1]. I have previously read complaints that the promise doesn't cover enough of the .NET libraries among other issues [2], but I was not aware until now of anyone claiming that it is non-binding.
[1] http://www.microsoft.com/openspecifications/en/us/programs/c...
Clojure without dynamic-typing is bath-water without baby. What is the point of interactivity, homoiconicity and macros if the language is statically typed?
If the type system can handle it? MAGIC!
You achieve this by omitting the type annotation and reverting to normal Racket.
You can do macros in a statically typed language, but it would (and does) get ugly fast.
[Scala] Type inferencing, but not powerful type inference?
In Scala the Hindley–Milner type inferencing is not possible because Scala is OOP, compared to Haskell which isn't.Ocaml does have Hindley-Milner, but not for the OOP features and whenever I played with Ocaml it felt like 2 different type-systems shoved into the same language (much like Obj-C). Scala on the other hand is more consistent, elegant and simpler. That's why it has "case classes", because case classes are used for algebraic data-types, which have special properties that aren't necessarily shared by normal classes.
And because of implicits, the type-system is also more powerful than what's available in Ocaml and even Haskell. It's arguably too powerful, but the things that the collections library can do have no match in other languages. E.g. http://stackoverflow.com/a/1728140/3280
I also liked to bitch and moan about the lack of real type inferencing in Scala, however in Ocaml and Haskell just because the types are not specified, that doesn't mean you can ignore those types. Quite the contrary, you always have to be aware of those types, as opposed to working in a dynamic language. That's why it's standard practice in Haskell to add those types explicitly for public APIs, because otherwise it hurts readability a lot.
I don't think that's true. You do the same thing (e.g. collections that choose better representations) via type families/associated data types in Haskell. E.g. in [1] or [2]
That said, what is true is that Odersky has modified the Scala type system in quite interesting ways, specifically to support his collections library. [3]
[1]: http://hackage.haskell.org/package/adaptive-containers
I've got a quip for that in my quotefile:
> "Haskell mainly helps with my C++ template coding when I'm doing money oriented programming" -- fnord123
The question the programming community faces over the next, oh, ten years or so, is "Can we get the benefits of Haskell without the strict attention to the type system and without having to rigidly separate IO?" Or a bit more sarcastically/cynically, can we get the benefits without having to fundamentally change how we do business? My gut says no, but I'm open to being proved wrong. (Oh, and yeah that's not the only question, there's others like "What about OO? Can we keep it?", but I think that's really the core question; do we really have to rigidly control our side effects or can we keep our sloppy side-effect usage? Everything else is either incidental next to that, or flows from it.)
The real thing that would be cool would be a strict haskell with optional laziness.
Probably the most promising approach that might salvage conventional programming approaches is a process-based model like Erlang or Go, where each process is internally mutable (mostly unlike Erlang, though it does have the process dictionary), but strictly segmented such that one process can not mutate another's state. This hybrid approach might be viable, and while it's not exactly business-as-usual, it's not as far a trip as full-on IO isolation. (Still, that affords just slamming everything in one process, at which point you don't win much. Will be interesting to watch Go's ecosystem develop and see if goroutines manage to become something deeply and pervasively used in all libraries or a thing occasionally used when the situation is desparate.)
Yes and no, while Erlang structures are not mutable (aside from the process dictionary, and the process's message queue), each new iteration of the process loop mutates the process itself, as the process goes from one state to an other.
Which is of no relevance to Erlang in the first place, since it does not expose threads to the developer.
> I think that's basically what Go does, though I haven't quite studied it enough to be sure.
Go has mutable structures and mutable bindings.
It may not expose them to the developer in the sense that they are available for the developer to directly manipulate, but it is certainly exposed that multiple cores may be running Erlang simultaneously. To the extent that it isn't relevant to Erlang, it is because Erlang has made it not relevant to Erlang by a conscious choice of the developers, not some sort of accident.
"Go has mutable structures and mutable bindings."
Yes, I said that, but can a structure owned by one goroutine be directly modified by another such that a single goroutine can observe that a reference has changed values which the goroutine in question has not changed? Do structures even belong to goroutines? One of the things that turned me off when I looked at it a while ago was that the docs were giving me a hard time answering this question, but I consider it a rather fundamental one. (But this was a while ago, much closer to its beginning.)
Sure, but there is absolutely no way that values can change "under your feet" within a process since processes don't share memory. Even if objects were mutable within a given process that would make no difference.
> Yes, I said that, but can a structure owned by one goroutine be directly modified by another such that a single goroutine can observe that a reference has changed values which the goroutine in question has not changed?
Not sure what you mean by "a single goroutine can observe that a reference has changed value". If a structure is not local to a goroutine A (because it was carried through a pipe or was created in a lexical scope other routines can see), then other goroutines will be able to alter it yes, as to whether A will be able to see that, well unless A memoized the old value (by deep-cloning the structure) A will see new values and not old ones.
> Do structures even belong to goroutines?
Go has no built-in concept of ownership, so that question is a bit tricky. Structures are only exclusive to a given goroutine if they are not visible by or shared with other routines. So if the structure in question has been created in a scope making it visible by multiple goroutines, or it has been carried across a channel to an other goroutine, then other goroutines will be able to modify it from "under your feet".
Having side effects in a transaction occur more than once because you didn't pay attention is a real pain to debug, mostly because the transaction won't be retried until the program is exposed to heavy load leading to serious memory contention.
At that point, debugging concurrent designs turns into a nightmare, not being any better than having to deal with deadlocks etc, the very thing STM is supposed to magically make go away. In some cases I even had to resort to locks because it was easier to handle IO that way.
Now, Haskell's type system would just not allow having any sort of IO side effects inside a STM transaction. Yes, having to explicitly handle IO may sound as a lot of work, but in my experience it makes everything easier.
http://www.xent.com/pipermail/fork/Week-of-Mon-20070219/0441...
(Edit: After further research if you were on Hacker news mid january last year this would in fact be old news, sorry for the unwitting repost)