>Mmm... I wouldn't really say that JS is a good example of idiomatic HOF - just look at the standard library. I would say that JS has specific idiomatic patterns (such as callbacks) that are a subset of HOF, but most JS code you see around is not like ML or Haskell with regard to HOF in general.
Lodash/Underscore is tremendously popular. Yes, most JS libs HOF merely for callbacks, but the IDEA of, "foo takes a function and returns a function," is a fairly widespread idea in the JS community: The same is true of ruby, and a few other mainstream languages.
>And scoping. And magic semicolons.
Scoping is semantics, not syntax. And yeah, scoping semantics suck. But hey, IIRC at least they were never as bad as python's used to be :-).
However, this is no excuse for how awful the semantics are. Variable Hoisting is the devil. However, ES6 seems to improve this somewhat.
As for the 'magic semicolons,' JS doesn't do ASI when the syntax is ambiguous. So I fail to see what's so magical about them.
Unless you mean the semicolon/lack of semicolon on the end of a function definition. And that's for the same reason as C struct semicolons, and about as easy to remember.
>Can you clarify? So far as I can see, all you need for lambdas are first-class functions (function-typed values), function literals, and closure semantics for the latter. Most mainstream languages offer that these days. C# would be a good example - what do you find limiting about its lambdas that JS does better?
<rant>
First of all, people talk closures like they're some magical entity: They're not. They are a natural consequence of lexical scoping and every lexically scoped language you have ever used has them. Yes, even whatever one you're thinking of right now. They may not support inner functions, but all a closure is is a lexically closed environment, so semantically, EVERY function is a closure.
</rant>
My pedantic nature over that aside, yes, I will gladly clarify. I am not familiar with C# or Perl, and am not super familiar with the Java lambda semantics, so let's talk scripting languages: Ruby, Python, JS. And since this IS JS's domain, and Perl is Perl, the comparison should be useful.
Let's start with Python:
def apply(f, arglis):
f(*arglis)
It seems simple enough, but as you no doubt know, Python's lambdas can only have one statement: So while this works:
>>>apply((lambda x, y: x+y), 1, 2)
=>3
This doesn't:
>>>apply((lambda x: \
... if x:
... print("oh noes")), 2)
=>syntax error
Next, ruby. Off the bat, Ruby looks better: blocks, procs, and lambdas are everywhere!
And thus begins our first problem: Blocks, Procs, and Lambdas are all SUBTLEY DIFFERENT. Bad, okay, but not awful.
However, Ruby is, unlike Python, fully Object Oriented. Thus, procs and lambdas are instances of their respective classes. What ruby should have done is introduce python style call methods, allowing any object to act like a function. Instead, much like Smalltalk before it, it added a call method to each object, which you call to invoke the code. This means that you can't just pass in a kernel method (What most of us call functions) instead of a block or proc when a function is expecting one: you have to wrap it. Thus, functions defined with def aren't the same as the anonymous procs you create: they're different entities. The Schemer in me is shouting that making functions and lambdas different entities should be a compiler optimization, not something transparent to the programmer.
Finally, Java: I said I wouldn't cover this, I lied. Java actually handles lambdas surprisingly well. The only problem is that a lambda can only touch 'final' variables. So a lambda can read the args of the function that created it, but it can't change them, and thus you cannot get the greatness of lambdas with mutable lexically closed environments. Joe Armstrong would disagree with me, but I'm not trying to build a 5 nines system with thousands of servers and billions of concurrent threads. Immutability is great, but a bit of mutable state every now and then is nice.
Basically, I like JS's lambda implementation because lambdas in JS are indistinguishable from functions created any other way.
Pretty much, these lambda semantics remind me of Scheme. The language I wish I was writing in. I mean, JS is nice enough, but if Spock ever becomes production ready...
>QuakeC was basically just C with only primitive data types (no pointers or arrays!), and a single reference type that referenced a single struct type with an extensible definition. So yeah, not very impressive; but it mostly did what it needed to do in its niche.
Besides, it was fun fighting with the language limitations sometimes (e.g. you could simulate a global array by writing a function with a giant conditional inside - or, better yet, writing a code generator to do it for you). Again, not something you really want in a "production" language - but as far as writing game mods went, fun was usually the primary goal for most who did it.
Oh it's fun, sure. And then you see Xonotic. And you see OO hacked into a system that only kinda sorta supports it. Which is kinda cool, until you realize that that system is backing one of the biggest Open Source AFPS out there. And then you a bit ill...