Hacker News new | ask | show | jobs
by nyellin 5347 days ago
Parenthesis for method invocations are optional, if the method does not take any arguments.

obj.compute instead of obj.compute()

That seems silly. The optional semicolons also irritate me.

----------------- (Added)

I imagine a committee of Java developers, in a penthouse boardroom at Oracle, meeting with management to discuss Java's descent into disuse.

"Lets make Java more concise," suggests a senior developer.

"Yes! Lets get rid of the parenthesis like Ruby!"

"And the semicolons like Javascript."

All falls silent. Everyone stares at the programmer.

"But... But..." stammers an important board member. "I thought we needed those."

"We could make them optional."

"Yeah, we'll be multi-paradimatic like Perl!"

And so Extend was born. A cargo cult at its best.

8 comments

That's what Scala already does: if a method does not take any args then the parentheses aren't necessary.

To quote Odersky: "This convention supports the uniform access principle which says that client code should not be affected by a decision to implement an attribute as a field or method."

It makes sense if you want to implement something that may be a field but needs to be computed.

How do you differentiate between referencing a method, and calling the method? I.e., foo.Sort(x.compare)?

I think the idea of computed fields implemented via methods is better represented via C#-style properties, although I'd prefer to be able to access their methods directly, when suitable.

You'd use an underscore to form a partially applied function:

    foo.Sort(x.compare _)
And Scala's getters and setters are essentially equivalent to C#'s properties:

    class A {
        private var _x = 0
        def x = _x
        def x_=(value: Int) { _x = value }
    }

    val a = new A
    a.x = 5
    println(a.x)
So instead of a simple, uniform rule that () invokes a function, and no-() references the function, you add yet a third syntax?

This is not an improvement, it is an unnecessary complication.

That's not the same thing. You obviously use partial application only if the function takes params. And I just can't see why you'd like to pass a reference on a parameter-less function.
Closures don't need to take parameters to be useful, but you're missing the point.

There is a simple, unambiguous rule -- () calls, no-() references. In order to... what? save two keystrokes? -- you have added a strange corner case, and then tacked on a new bit of punctuation for partial application. Though now it seems you're adding the rule that functions without parameters can't be referenced.

This takes a simple yes-or-no rule and adds edge cases for no reason. Two keystrokes on the occasional parameterless function call is not a real savings, and you've just made it harder for someone reading the code to spot all the function calls.

This fundamentally makes no sense. Why would this be a good idea?

This feature, which Delphi has, can be problematic - if you're assigning a method to a method reference variable, it's not always clear if you intend to assign the method itself, or the return value of the method (which may itself be a method reference).

Of course, Java doesn't have method reference types. But it's an ambiguity worth bearing in mind.

There is nothing wrong with optional semi-colons. In most cases, the parser doesn't need them, and the programmer doesn't want to type them. But they're useful in some cases for disambiguation, especially in a language like Xtend that doesn't use an explicit return. E.g.

    foo("bar") ;
    (a + b)
The semicolon is necessary for disambiguation in a case like this, but there is no reason to require the programmer to put in semicolons everywhere. I think the operator precedence hierarchy and optional parens to override it is way more complicated, but people seem to deal with it fine.
"The semicolon is necessary for disambiguation in a case like this..."

This is why semicolons should be mandatory or illegal. The whole "optional semicolon" thing is a mis-feature designed by language committees that can't make a decision. One's codebase becomes a mismash of lines with and lines without semicolons, sprinkled in as magic to make the compiler happy.

There are plenty of interesting language features which are useful -- support for "optional semicolons" isn't one of them. The feature needs to die, and people should just choose to use a language that suits their need to type -- or not type -- a ';'.

We should also use a fully-parenthesized prefix syntax so we don't get a mishmash of lines with and without parentheses used to override operator precedence!

I agree Javascript's "automatic semicolon insertion" is a terrible feature, but largely because the description is so hard to understand that programmers don't know when the semicolon is required.

In an expression-oriented language, like Xtend seems to be, the rule for when you need a semicolon is simple. The parser makes the longest legal expression it can, if that's not what you mean, then add a semicolon. It's no harder to understand than the lexer equivalent (the lexer makes the longest token you can, if you want to resolve the ambiguity insert a space), or the operator precedence rule (the parser will interpret infix operations using this precedence table, if that isn't what you mean use parentheses).

Matlab, for example, doesn't require commas to separate list elements, and doesn't require but allows semicolons at the end of lines, and nobody complains.

Sorry for not understanding, but can you explain what the ambiguity is here?
A C-like parser will keep parsing an expression as long as it's legal. Take:

    foo("bar") * a
It will parse the call to 'foo', then see the '*' which is an infix operator and parse the whole thing as a multiplication expression. In most C-like languages, '(' is both a prefix operator (for grouping) and an infix operator (for function calls). So:

    foo("bar") (a + b)
Is ambiguous if you don't require semicolons to separate expressions. The parser will parse the call to foo, then see the '(' and parse that as a call to the value returned by 'foo'. To stop that, you use the semicolon to stop parsing one expression, so the next '(' is treated as a prefix operator.
Wow, yes of course. For some reason I thought Xtend was whitespace sensitive, so just having a newline was enough.
Talking about cargo cult, they added "def" to function definitions making it more verbose actually.
That's probably to make it easier to parse with type inference, since right now it's the type name that start's a method definition
Seriously, I was thinking, WTF? Increased verbosity and then it isn't even a full word like "define", it's verbose and then abbreviated. Are they just trying to make Javathon at any price?
Ruby does not get rid of semicolons or brackets. Heck, you can write Java/C++ style curly brace code in Ruby if you wanted.
Of course, if you did write Java/C++ style curly brace code in Ruby, those of us who like Ruby would bring out the pitchforks.
At least then vim would understand it and you wouldn't have to deindent every 'end' yourself. It would be nice to be able to use % and some other stuff that you get with most other languages.

The fact is that the visual style of a language is trivial to get used to. Breaking my text editor is a real issue though.

vim does understand Ruby. As soon as I type end, it automatically de-indents the line 2 spaces. Put this in your ~/.vimrc:

    filetype plugin indent on
also matchit.vim to do %-bouncing between keyword/end pairs
Making the parenthesis optional makes it harder to differentiate between taking a method reference and the return value.
It's pandering to hipsters. Parenthesis are just to obvious.
Optional parenthesis if no argument is given was already a feature of at least pascal in the seventies.

All those new "cool and innovative" languages are just rediscovering it after almost a decade of everything with C syntax.

Not that it's bad or anything, it's just my OCD tingling.

Well, Ruby does go beyond this: optional parenthesis with or without arguments. Of course, no public instance variables, like Smalltalk and Scala, makes this possible.
IMHO, it's less readable, and more ambiguous. Is it a variable or a function? Who knows!
This is actually half of the value of it. It allows you to easily change the implementation without breaking the public semantics. Generally speaking, the first-pass practice in Scala is to use public fields and to make them vals (final/C# readonly). Where you need to provide mutability, you use a var. But due to C#-esque properties, you can go from

  var x = 1
to (not great code, but illustrative of the point)

  private var _x: Int = 1
  def x: Int =  _x
  def x_= (value: Int) = {
      if (value > 1337)
          throw new ArgumentOutOfRangeException() 
 
      _x = value
  }
The convention is to use empty parents after zero-argument functions that have side effects, much like the ! in Scheme.
Cargo cult is actually your argument, i.e thinking you need the parenthesis and the semicolons, just because Java always had them...
The point is removing them accomplishes little and adds ambiguity. There's something to be said about not changing things that adds no value; momentum and familiarity are valuable features, even if technically they're not needed.

This trend of trying to strip programming languages down to their "essence" is a fools errand and the pendulum will swing back eventually (not fast enough in my opinion).