For those interested in compiling down to Javascript with a strongly and statically typed language, there's a brilliant proper subset of Haskell that compiles down to Javascript called "Fay": https://github.com/faylang/fay/wiki
Also Roy, which is statically typed (with type inference) and is designed for JS interop. It's also written in JS and can be installed with just npm install roy http://roy.brianmckenna.org/
I would like it, but why oh why does it have Algol-like syntax? It started with ML-like one IIRC, so whyyyy? (it's just an expression of disappointment, not actual question)
I haven't written any Elm but having written some Haskell I can say it's surprising how often you _don't_ need a debugger in a functional language. I doubt Elm not having a debugger is as difficult as, for instance, Javascript or Coffeescript not having a debugger would be.
Clojure is a great language, but there really is a difference between functional and "pretty" functional; e.g. as in, I know 100% sure that this function has no side-effects.
Static typing can do a lot of good, but the stricter semantics of Haskell also goes a long way into writing code with fewer bugs.
Nobody can agree on the definition of a functional language. AFAIK, so-called "functional" languages like F# or O-Camel allow arbitrary side effects, unlike Haskell.
Any function changes the state of your machine, and you have to pretend your computer doesn't have memory or registers in order for this pure function side effect free stuff to make sense. When you said "know 100%" my ability to accept abstractions like that turned off.
Haskell has support for side-effects. It's just able to state the property that something is a 100% pure function, and also makes it very easy to write such code a lot of the time.
Unfortunately, I don't have the opportunity to be paid to write Haskell. Which means I haven't had the opportunity to use it for anything else than side projects.
However, there is one thing you want a debugger for in Haskell: checking when thunks have been forced.
Also, the type system can catch much more issues than "normal" compiled languages, not to mention the safety of immutable values. But there still numerous classes of issues which will not be caught by the type system. And of course, you have exceptions. Even if your code catches them, figuring out what triggered the exception can be tricky.
Paraphrasing a great programmer: "The best debugger is your brain". I have no issue with people using a debugger, but it is not a must in order to debug, imho.
I have found that this advice doesn't work too well when dealing with large, preferably legacy, codebases along with a pile of third-party libraries. Sometimes, the best debugger is a debugger.
A-men. Right now, I'm waist-deep in over 80k lines of JavaScript neither I nor anyone remaining on our team wrote, and just being able to set breakpoints on event listeners in Chrome and step into the functions that are fired probably saved me weeks off a more plodding read-through-the-whole-codebase approach.
I'm not sure how you'd create a language that would solve that problem, though I guess since the bug I was chasing down was a classic state problem, maybe it would have been caught by a compiler in Fay/Haskell.
The bigger problem I encountered trying it out yesterday was that it (at the moment) is fairly happy to generate an empty page and not give any compiler errors.
I assume that will change, but it made it pretty hard for me to get started with the language.
That said, I hope it changes, because Elm looks really neat!
Do source maps also support tracing values in variables, or do they only map line numbers in source to line numbers in output? Because the former (mapping values) is the hard part of implementing a debugger.
That's an interesting question. Debuggers are very different when they target functional languages and the mote you express with fewer lines of code make for somewhat surprising.
OTOH, the way one codes in functional languages is also different. Lack of a debugger may not he a problem as big as it would be with, say, Java.
No, its plain old lazyness. All these "compiled to JS" language makers would rather add more fancy syntactic sugar or extend the standard library than getting their goddamn bases covered.
I have no problem with that, but please don't go on about how you are much more productive in this language than in JS, and how much cheaper the code will be to maintain.
I think it's ridiculous to call people "lazy" who wrote an entirely new language from scratch and released it for free, because it's lacking one feature.
Per my sibling post, I do not believe you are technically correct. Debuggers must support the ability to debug compiled languages before anyone can usefully implement support for debugging. I'm curious what exactly you think the developers of languages that compile to JS are not doing out of "lazyness"?
I was taught in early rhetoric and composition classes that it is poor style to include "In my opinion" and other qualifiers in pieces that are clearly rhetorical or opinion based. The repetition is unneeded. In engineering discussions it is very common to differentiate between opinions and knowns. When discussions happen between people who don't agree on these things, someone gets annoyed. The engineers get annoyed when people state opinions as fact and think the other person is making unjustified assumptions. The non-engineers get annoyed and think that the other person is being pedantic.
This is not a statement about the skills of other developers. This is a statement about the applicability of JavaScript to the sorts of problems people are trying to solve with it. There are a lot of nice things about JavaScript that people didn't quite understand or appreciate in the early days, but that doesn't change the fact that the HTML5 stack is deeply flawed in many ways for the needs of application developers. That shouldn't be surprising or controversial: All of these technologies were developed in a simpler time for a simpler set of problems.... and in a rush.
It's fairly crazy, but then again there are ~700 programming languages listed on Wikipedia, so really, there are just a lot of programming languages in general.
In terms of Foo->JS there seem to be two main camps, at least that I've noticed: writing a "better" JS (CoffeeScript / Dart et al), and writing something that converts your language to JS so you don't have to learn JS (ClojureScript, Scala.js etc) at all.
The latter can have ~700 of those before you've even started to duplicate yourself, so there is still a ways to go :P
Arguably there are only half a dozen or so "real" contenders in the former category (in the same way when you decide you want to learn a new programming language you don't pick from all ~700).
I recently attended a coding dojo where we wrote code in elm and tests in coffeescript. I was new to both languages but I was surprised how easier elm felt compared to coffeescript (note: I have some haskell background ;]).
Here are the results: https://github.com/dzsodzso63/PreziCodingDojo/tree/master/fr...
Great news that Evan can dedicate fully to Elm as his main job. I'm very curious about the language and its departure/simplification over traditional DOM manipulation with JS. I hope the best for the project and would love to see some effort for the compiler targeting asm.js :D
The world seems to be intent on writing mountains of code to avoid writing javascript, and usually ending up with a system that compiles to more javascript than if they just wrote javascript. Saying javascript is broken is a nonsense, they mean they feel they should be above writing javascript due to its quirks and inconsistencies. Whatever they write the end result is still the "broken" language they wanted to avoid. It all seems like a huge waste of resources and smart people's time to me, but then I've been writing javascript for getting on for 15 years so perhaps im past it and don't "get it" anymore.
> and usually ending up with a system that compiles to more javascript than if they just wrote javascript
That's not really a useful or sufficient argument against languages that target JavaScript, since you won't be reading or maintaining the JavaScript code itself. You could say the same thing about assembly code ("languages which target assembly languages usually end up outputting more assembly code than if the programmer had just written the assembly code manually"). If you're really concerned about lines of code (which is itself somewhat troublesome), a more valid comparison would be the lines of Elm code versus the lines of human-written JavaScript code to implement the same thing.
> The world seems to be intent on writing mountains of code to avoid writing javascript, and usually ending up with a system that compiles to more javascript than if they just wrote javascript.
Does it really matter how much javascript gets created? That statement could be made for any higher level language where X lines of the higher level language compiles into 5X lines of the target language. Maybe you could hand write your program in the target language using only 4X lines, but the point of the higher level language is to make it easier for the programmer to avoid mistakes as well as reduce source code size, not necessarily compiled code size.
Except that when JavaScript is the target code size does matter because it has to come up over the wire no? That's why something like Dart advertises the fact that it does tree shaking. (Elm may aim for the same efficiency who knows?)
You can do tree shaking in JavaScript with tools like Google Closure Compiler and uglifyjs (a bit more limited). Any language which compiles to JavaScript aught to be able to make use of these tools.
I think that may not be the case - it may be more that Haskell is a fabulous language to write compilers and parsers in, and so lots of compilers and parsers are written in it :)
It's a bit of both. I will say that it's very frustrating to use other languages after adjusting to Haskell. The way it feels when it feels when you're out on your own without a helpful compiler to guide you? It's like losing your sense of balance!
because JS is flexible, the VMs are really good recently and the web platform is tempting but haskell coders miss safety, succinct syntax and efficiency.
Yes - I think once you start being productive with Haskell you prefer to work in languages with strong type systems that are purely functional (Haskell and subsets of it). When I work in Haskell it feels like a burden has been lifted from my shoulders - for real! Coming back to JS is simply painful.
I think more programmers would experience this if it weren't for Haskell's insane learning curve. It took me a ~year of casual learning and skimming before I could do anything useful. Very casual, though ;)
I think i also got confused the first time i saw that syntax (being used to C-like languages hehe). It started making lots of sense once i got familiar with the concept of currying and functions as first-class values.
Suppose you have a function f with type Int -> Int -> Int (you can read it as "it takes two integers and returns an integer" or "it takes one integer and returns a function that takes an integer and returns an integer"), then:
f
is the function itself, and it is a usable value.
f 42
is a function of type Int -> Int, and a perfectly valid value too. And
f 42 33
is just and Int.
It's like with each application you take one arrow from the function type; until you get something that's not a function any more :)
It's just new and you're not used to it. There's nothing wrong with finding new and different syntax confusing, as long as you're willing to keep an open mind.
If you use it for a while, you'll get used to it. After a while, I've found it makes the most sense. I think it's better because it reduces the amount of syntactic noise in the code.
It's a simple design decision. Function application is the most important part of the language. So it gets the best syntax: none.
is how you would write your example. In Elm, you could also use the function application operator to avoid writing the parentheses:
f a b <| g x y -- EDIT: flipped the operator around
In Haskell, this would be done with $, which used to exist in Elm as well:
f a b $ g x y
Once you get used to mentally parsing the $ as grouping the rest of the expression together--admittedly, it does take a little while--the last version is probably the most readable. At least that's what I've found.
A lot of modern mathematics also drops the parens, especially in areas related to modern algebra. It really makes the most sense and is less ambiguous, with parens not being overloaded between grouping and application.
I was really impressed by elm, but I strongly prefer working with a library that provides some of the features without transpiling. If anyone else is interested, I'm looking for some help with my project: https://github.com/jlatt/frp.js
Do you have time to explain why bacon is better than Reactive Extensions, and thus the only frp library for JavaScript that you chose to link to? I don't have too much experience with frp in general (primarily just the Reactive Extensions for .NET), and even less with JavaScript implementations, so I'm not really in a position to begin making the comparison.
> Elm is the future as much as Java is dead in the software development industry.
Correct me if I'm wrong, but it seems like what you've done here is just take one narrow interpretation of Nekorosu's comment and used that as the basis for a dismissive reply that offered no value.
---
Dateline 1995:
Nekorosu: "Java is the future"
Cuttooth: "Java is the future as much as C is dead in the software development industry"
---
It's a big industry, cut. There's room for everybody.
The point was that JavaScript is king and this "Elm is the future" suggests that it'll be a major player. Right now it's a niche toy language. There's room for plenty of those, sure, but it takes years of work and development for a language to become worth its salt. Java had its fair share of issues for a while, and arguably still does.
I think the idea here is that you aren't /forced/ into inversion of control. That is, if it is clearer to write things side by side, instead of separated into another callback function, you can keep them together.