Java Assignments are evaluated Left to Right

I think I’ve just found a mistake in the Java Tutorial.

Maybe I’m just being pedantic, but I think I’ve just found a mistake in the Java Tutorial. It claims:

All binary operators except for the assignment operators are evaluated from left to right; assignment operators are evaluated right to left.

The Java™ Tutorials » Language Basics » Operators

What is this supposed to mean? Evaluation from right to left would mean that when you have a line like the following you get the rightmost expression evaluated first:

int x = 42;
x += getNumber();
// The above would be equivalent to:
x = getNumber() + x;

But that’s not how Java actually evaluates this expression. And the JLS 12 (2019-02-08) clearly states in 15.26.2 that “the value of the left-hand operand is saved and then the right-hand operand is evaluated.”

This explains it best:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

JLS 12, 15.26.2 Compound Assignment Operators

So the above code is actually equal to this:

x = (int) (x + getNumber());

Addition is commutative, so it doesn’t matter. But we also have /=, which is not commutative. You can test this by using a static field for x and some side effect (such as System.out.println and some assignment to x) in getNumber().

public class SomeClass {
	static int x = 42;

	public static void main(String[] args) {
		// assignment operators are evaluated right to left?
		x += getNumber();
		// equal to:
		// x = x + getNumber();
		System.out.println(x);
	}

	static int getNumber() {
		System.out.println("wahr!");
		x = Integer.MIN_VALUE;
		return 58;
	}
}

This code will print 100. That’s because the old value of x (42) is used. If x was evaluated after getNumber() you would get -2147483590 instead.

Contrary to that the Tutorial says all assignments are evaluated left to right. But all the assignment operators are  right-associative. That might be the reason for the mix-up.

There are 12 assignment operators; all are syntactically right-associative (they group right-to-left). Thus, a=b=c means a=(b=c), which assigns the value of c to b and then assigns the value of b to a.

JLS 12, 15.26 Assignment Operators

Example:

public static void main(String[] args) {
	int x = 42, y = 58;
	x += y *= x;
	// equal to: 
	// x = x + (y = y*x);
	System.out.println(x);
}

It would not make any sense if they were left-associative.

The Tutorial should be corrected to say:

All binary operators except for the assignment operators are grouped from left to right; assignment operators are grouped right to left.

Or:

All binary operators except for the assignment operators are left-associative; assignment operators are right-associative.

Is Java easy?

Java isn’t easy. It’s often more complex than needed. But being easy for beginners shouldn’t be a design goal with high priority.

Should a programming language be easy?

I don’t know why so many educational establishments use Java to teach programming. They often start with Java in the first semester. Even the Oracle tutorials expect the reader to already know some basics.  Java was designed for programmers who already know C/C++ as seen in this example.

The main method is similar to the main function in C and C++; it’s the entry point for your application and will subsequently invoke all the other methods required by your program. [Lesson: A Closer Look at the “Hello World!” Application]

Continue reading “Is Java easy?”

Recursive FizzBuzz

FizzBuzz in two lines of code.

The only import you need is one for System.out:

import static java.lang.System.out;

Simple two-liner:

static void f(int a, int z) {
	out.println(a % 15 < 1 ? "FizzBuzz" : a % 3 < 1 ? "Fizz" : a % 5 < 1 ? "Buzz" : a);
	if (a < z) f(1 + a, z);
}

Without using the literal “FizzBuzz”:

static void g(int a, int z) {
  int x = 0;
  if (a % 3 < 1) { out.print("Fizz"); ++x; }
  if (a % 5 < 1) { out.print("Buzz"); ++x; }
  if (x < 1) out.print(a);
  out.println();
  if (a < z) g(1 + a, z);
}

Note that I use x<1 instead of x==0 to save a single character.

Set-theoretic explanation of IEEE 754

Why is 0.1+0.2 not equal to 0.3?

The IEEE Standard for Floating-Point Arithmetic is confusing for beginners. Here I try to give an alternative explanation. It’s not my goal to make it easy. It simply isn’t easy. But this might help understand some aspects of floating point arithmetic.

Continue reading “Set-theoretic explanation of IEEE 754”

Y Combinator in Java 8

The Y Combinator written in Java 8 with nothing but lambdas.

The Y Combinator allows us to use recursion without actually using the recursion that Java already has. And Java 8 actually doesn’t support recursion in lambdas. So this is one way of solving the problem. The simpler one would be to use a recursive Java method and then use a method reference to it (as in MyMathsFunctions::factorial). This is to show that Curry was right and we can do it with nothing but lambda expressions. Since Java is strongly typed I also need an interface, which references itself in the type declaration. This is necessary because at some point we need to apply a function to itself.

There are enough wiki and blog pages and articles on this. Even videos. So I won’t explain it in details. It’s nothing new, just written in Java 8.

Code on Pastebin

The full Code is here: https://pastebin.com/M2RmRqdU

	private static <T> T apply(UnaryOperator<UnaryOperator<T>> fn, T arg) {
		return ((Function<UnaryOperator<UnaryOperator<T>>, UnaryOperator<T>>)
				a -> ((Fn2Op<T>) b -> b.apply(b))
				.apply(
					c -> a.apply(
						x -> c.apply(c).apply(x)
					)
				)).apply(fn).apply(arg);
	}