• Post Reply Bookmark Topic Watch Topic
  • New Topic

Operator Precedences?? ->

 
Campbell Ritchie
Marshal
Posts: 52549
119
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What is the precedence of the -> operator? Does it associate to the right? In Maurice Naftalin's book (page 31) there is code like
(Supplier) () -> "hi";
and
Callable<Runnable> c = () -> () -> System.out.println("hi");
That suggests to me that -> has a higher precedence than casts and associates to the right. Anybody know that for sure? Anybody got a JLS page for that? I think this JLS page may explain it. It says that a lambda expression is lambda parameters -> lambda body and lambda body can be expression or block and expression can be assignment expression or lambda expression.

Or have I got it wrong?
 
Rob Spoor
Sheriff
Posts: 20819
68
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Since that compiles, you're not wrong

I knew that lambdas had precedence over casting, but never tried a lambda in a lambda. I am actually surprised that https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html still does not include the lambda operator, even after 18 months of Java 8.
 
Hauke Ingmar Schmidt
Rancher
Posts: 436
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:Since that compiles, you're not wrong

I knew that lambdas had precedence over casting, but never tried a lambda in a lambda. I am actually surprised that https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html still does not include the lambda operator, even after 18 months of Java 8.


JLS does ( http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.12 ) but omits instanceof which exists ... a little longer.
 
Campbell Ritchie
Marshal
Posts: 52549
119
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you, both of you. I am not sure I am right after all. I presume the cast compiles; I copied it from Maurice Naftaline's book.
If a λexpression can be arguments -> something which λexpression is a subtype of, then -> associates to the right.
But does that mean higher precedence or lower than anything in the λbody? Do we then have to regard the λexpression as being implicitly wrapped in invisible ()? You usually wrap a λ in visible ().

But that JLS link isn't a precedence table.
 
Campbell Ritchie
Marshal
Posts: 52549
119
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That code will compile and run. I even mistaken applied the Supplier cast to c and got a class cast exception as MN says in the book:-
 
Campbell Ritchie
Marshal
Posts: 52549
119
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I see I could have got an output from line 6 had I thought a bit; the call method returns a Runnable whose run method needs to be invoked.
 
Campbell Ritchie
Marshal
Posts: 52549
119
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Does -> have a precedence at all?

Usually when you write a grammar like
Exp1 op Exp2
… it means that op has a lower precedence than any operator permitted in an Exp1 or an Exp2. In the case of -> the left operand is a comma&#s2011;separated argument list. But that list must be wrapped in () if it does not contain exactly one element, so any operators on the left do not help us. Let us have a look at the right. It would appear so far that
(i, j) -> i + j
… is a valid λ which suggests that -> has a lower precedence than +. But we have seen that the casts I found in MN's book are permissible, in which case -> has a higher precedence than +.

I now feel I am the same place as the ancient Greek philosophers who found that √2 is not a rational number because they could prove n is not an even number nor is it an odd number when √2 = n ÷ m where n and m are integral numbers.

The precedence of -> is higher than that of (cast) and the precedence of -> is lower than + and the precedence of + is lower than the precedence of (cast). I am now in a position where I can prove something by contradiction: -> does not have a non‑null precedence.
 
Campbell Ritchie
Marshal
Posts: 52549
119
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So -> is not a precedence operator at all; it must be a context operator. There is a context where -> can be used, in the middle of a λ expression. The left half must be a unit. You can tell that, as I said earlier, by reading it. If the left half is not a single argument, it is a comma‑separated list [possibly empty] which is enveloped in () converting it to a unit at this stage of parsing. At later stages of parsing the left part of the λ may cease to be a unit but that is after the -> operator has been evaluated. The -> operator sees its right operand as a single expression or as a block. A block is bracketed into a unit by its {}. One must therefore regard a λ expression as being in this form:-
((argument list) | single argument -> block | (expression))
… where the coloured () [underlined] are implied and imputed by the context, rather than by any precedences. You might not write those () but the context implies and imputes them to the code.
 
Stephan van Hulst
Bartender
Posts: 6583
84
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm glad I had some experience with Miranda (Haskell predecessor) before Java 8 came out.

You declare functions like so:

compareFoo :: Foo -> Foo -> num

You can read this in two ways:

1) The compareFoo function takes two Foos and returns a number.
2) The compareFoo function takes a Foo and returns a function that takes a Foo and returns a number.

Because of currying, the two are identical. You can envision the second one more clearly like this:

compareFoo :: Foo -> (Foo -> num)

This is an easy trick for me to remember the associativity of the lambda operator. If you wanted something with the declaration

applyMapping :: (A -> B) -> A -> B,

in Java you would declare it like this:

static B applyMapping(Function<A,B> mapping, A argument);
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!