News for hackers. Stuff that matters.
Re:Syntax Matters...? by barrkel on Monday April 16, 2012 @11:35AM (#3847803)
It is important, however, to distinguish between syntax and expressiveness. I don’t care (too much) whether you write function(x) { ... }, \x -> ... or { |x| ... } to denote a closure, but there had better be a way to write a closure somehow! (Java, I’m looking at you here)

Java is the refutation, IMO: it does have a way to express a closure, it's just that the syntax (anonymous class) is laborious. You need to wrap up any mutable variables to be captured in final single-element arrays, and your closure type will be a single-method interface, but the expressiveness is there. The syntax just sucks.

The laborious syntax is what stops you from writing what may be expressed in C# as 'foo.Where(x => x.Name.Length > 10).OrderBy(x => x.Name)' in Java. The equivalent, even using the smaller Javascript syntax of 'function(x) { return x.name.length > 10; }', is tedious. The (current) Java syntax is just silly.

The syntax "weight" of a feature matters. Syntax that's light and unobtrusive invites use. Syntax that's large and clumsy dissuades use, to the point that whole libraries may not come into existence, not because of a lack of expressiveness in the language, but because of aesthetic ugliness.

Lisp has an out here because of macros; almost everything is equally ugly. Many people appear to consider this base level of ugliness unacceptable; others may see it as a flaw of Lisp, because the very malleability of the syntax makes it harder to encode implementation costs in the form of the program.

Re:Syntax Matters...? by scott_s on Monday April 16, 2012 @11:47AM (#3847841)
I think you're abusing the word "syntax." I think there is a difference between being able to implement the same functionality of an abstraction, and having direct language support for that abstraction.

I don't think it's accurate to say that Java has clunky syntax for closures. Rather, I think it's more accurate to say that Java has no concept of closures. If you want that functionality, you need to roll your own support using existing concepts. C++ before C++11 is the same.

Re:Syntax Matters...? by ajross on Monday April 16, 2012 @11:55AM (#3847868)
But isn't that abuse of the word "concept"? The same logic would argue that C has no concept of a string, or that lisp has no concept of an object (despite lots of text handling and OO code being written in both languages). Not every "closure" works the same, even between languages that support things called "closures" and use them in roughtly the same way. Anonymous Java classes are clearly a related concept, and in fact as the grandparent points out there's a straightforward mapping between them.
Re:Syntax Matters...? by scott_s on Monday April 16, 2012 @12:03PM (#3847900)
I would argue that C has no concept of a string: there is no direct support in C (or C++, for that matter) for concepts related to strings. They are just arrays that happen to contain characters. All of the strigyness of those arrays exists solely in the mind of the programmer. C itself does not help you any. That is, I think, the hallmark of a language level abstraction: does the language allow you to think of the entity only as its abstraction, or do you need to handle that yourself? This fact is also, I think, a major reason why there are so many string-related bugs in C code.

Having never used Common Lisp, I can't say if that's also accurate for your other example.

Edit: ARGH. I forgot string literals in C. So C clearly does have the concept of strings. The problem is that's the only support in the language for that concept. Aside from being able to define string literals, C does not help you with strings at all.

Re:Syntax Matters...? by ajross on Monday April 16, 2012 @12:22PM (#3847996)
Fair enough. Then I suspect we'll just have to agree to disagree here. To me, that's a near-meaningless semantic distinction. Language concepts are squishier in my mind.
Re:Syntax Matters...? by kibwen on Monday April 16, 2012 @12:30PM (#3848041)
I'm not sure we can make a distinction here; since it's possible to use any Turing-complete language to augment itself (if necessary, in the worst case, by writing a new virtual machine for itself in itself), every language, technically, includes every concept. We have to draw the line somewhere, don't we? :)
Re:Syntax Matters...? by barrkel on Monday April 16, 2012 @12:21PM (#3847991)
Anonymous classes use lexical closure to capture names in the outer environment. The feature that Java lacks is not so much closures, as first class functions (which you can have without closures). Defining a method which binds to lexically enclosing symbols, and when evaluated has access to an environment mapping these symbols to values, seems to me to be possible in Java. It's just that the method needs to be contained in a class.
Re:Syntax Matters...? by tqs on Monday April 16, 2012 @01:37PM (#3848405)
I think you're spot on with your comment on syntactic weight.

Coffeescript vs Javascript forms a good case study because they largely have the same semantics but with different syntax for key features.

To my mind, the big difference with Coffeescript is the syntax for functions, e.g.

(x) -> x * x

vs.

function (x) { return x * x; }

Coffeescript's syntax eliminates "function" and "return", which significantly lightens the syntactic weight for functions.

I would assume on average that Coffeescripters write significantly more functions than Javascripters (say, for normalization, per bytes of minified JS). This assumption is based on reinforcing selective pressures: Coffeescript encourages programmers to write more functions, and programmers who want to write more functions choose Coffeescript.

Re:Syntax Matters...? by kibwen on Monday April 16, 2012 @11:53AM (#3847862)
You make a very good point. However, I think he addresses your concern over "syntactic weight" in this line:

Basically, there are some languages whose syntax is so distinctive that it makes a qualitative difference to the experience of programming.

I believe his argument then is that of the following three syntaxes (syntaxen?) to describe closures:

  function(x) { ... }
  \x -> ...
  { |x| ... }
The differences are so slight as to not be worth quibbling over. Perhaps his point, as yours, is that Java's closure-equivalents are so onerous to employ that they might as well not exist at all. :)
Re:Syntax Matters...? by barrkel on Monday April 16, 2012 @12:14PM (#3847949)
Part of my comment is arguing that there is actually a significant difference in aesthetics between "\x -> y" and "function(x) { return y; }"; and that query library like LINQ is natural to use with the former syntax, but so awkward to use with the latter that it's unlikely to be written in that way because of how ugly it would be in use.
Re:Syntax Matters...? by vorg on Tuesday April 17, 2012 @07:48AM (#3852146)
The first | in the third example, i.e. {|x| ...}, is redundant. This is the first thing I noticed when I first read up about Ruby over 10 years ago, and it put me off what I now know is a fairly good language. The same thing happened with the leading __ and trailing __ for certain names in Python. Syntax matters as newcomers notice it.
Re:Syntax Matters...? by kibwen on Tuesday April 17, 2012 @08:31AM (#3852248)
I don't know about Ruby, but it's not redundant in Rust; you can enclose arbitrary expressions in braces, and | is the bitwise OR operator, and Rust allows implicit returns such that the following is the identity closure:

  {|x| x}
Trying to rewrite this in your syntax as:

  {x| x}
could cause ambiguity if you had defined a variable x somewhere up-scope: is that a bitwise OR or is it a closure? True, the correct behavior could probably (maybe?) be inferred from context, but that might require Rust to switch from a simple LR(1) parser to an arbitrary-lookahead parser, which would inflate compilation times.

In any case, Ruby's hamburger-notation for closures is well-known by this point, and I'd hardly call it novel anymore. In the case of Python's __special__ methods, the whole point was to discourage people from heavily using them in the first place. Making ugly operations ugly, as it were.

Your point that newcomers might be turned off by a language's syntax remains valid, but you've also demonstrated that newcomers lack the context necessary to be aware of the tradeoffs necessary in language design. But hey, tough shit for language developers, huh? Yes, tough shit indeed. Languages must be familiar enough to attract people, but they must also be sufficiently expressive enough to retain the interest of the people in the community who really matter (the elite hackers and the devoted evangelists), while at the same time seeming novel enough to justify switching away from whatever language you were previously using in that domain.

TL;DR: It's a thorny issue, and simply saying "syntax matters" is an unjust simplification. :)

Re:Syntax Matters...? by CodeMage on Monday April 16, 2012 @06:35PM (#3849850)
While I agree with your ideas about the "syntax weight", I think that you're wrong about Java.

Java definitely has no syntax for closures, because it has no semantics for function types. It has interfaces and anonymous classes, which you can use to accomplish the same requirement, but the semantics of interfaces are not 100% the same as that of function types. A small example: there's only one function type for a function that takes one int and returns one int, whereas there are infinitely many interfaces you can define to represent that function type and none of them are necessarily interchangeable among themselves.

I think this distinction is important and that this is what the author is talking about when he says "there had better be a way to write a closure somehow!" In Java, there isn't.

Re:Syntax Matters...? by barrkel on Wednesday April 18, 2012 @03:27AM (#3856911)
You're confusing structural / nominal typing with first class functions. What Java lacks is the latter, while closures do not depend on the former, which is what you're talking about.

For example, C# supports function types, but it can have hundreds of function types (it calls them delegate types) for a function that takes one int and returns one int:

  delegate int Func1(int x);
  delegate int Func2(int x);
  delegate int Func3(int x);
and so on; all these function types are incompatible with one another.

I believe the distinctive feature of closures is closing over (hence the name) the outer lexical environment and binding to variables in the outer environment, in such a way that those variables are available during evaluation. Which is exactly what an anonymous class lets you have (so long as locals in the outer scope are declared final).

Re:Syntax Matters...? by beothorn on Monday April 16, 2012 @12:01PM (#3847885)
I agree with all you said, except that writing the equivalent of "function(x) { return x.name.length > 10; }" on java is a syntax problem. There is a lot implicit when you declare this function on javascript, for example, it's visibility. There's also the typing which is resolved on runtime. So maybe I don't have the concept very clear but, is this really a syntax difference or a language features difference?
Re:Syntax Matters...? by starwed on Monday April 16, 2012 @04:23PM (#3849218)
You realize you're making exactly the same point that the blog post was trying to make...