A note to language designers: I can understand the { } but if you use them why do you also need the ( ) around the conditionals here?
if (n <= 1) {
n == 0
} else {
isOdd(n - 1)
}
The parser can find where the condition starts (after the if) and ends (at the {) and we won't have to type two useless characters. It's ergonomics. static function isEven(n)
return if (n <= 1)
n == 0;
else
isOdd(n - 1);
static function isOdd(n)
return if (n <= 1)
n == 1;
else
isEven(n - 1);
i.e. An if expression consists of other expressions that may or may not be a block expression ({ }).Python ends if lines with a : which might help the parser, but maybe not because it was a late addition to help readability. For me it adds work when moving code around because I have to add or remove the :
Ruby does totally without any terminator in that context (in other contexts it has its own {} or do...end). The parser keeps processing successive lines until it understands that what follows can't belong to the conditional. I prefer that approach because it's the language/compiler that has to help me, not the other way around.
But how's that possible in general? Example, JSON parsing of data from a HTTP request. This is pseudo code
# request.data is
# {"a":1, "b":2, "c":"a string"}
data = parse(request.data)
total = data["a"] + data["b"] # 3
total = total + data["c"] # ops!
The last line is either a compiler error (how? forbidding input is not an option) or a runtime error (Grain doesn't have that) or what? List<Animal> animals = [Dog()];
List<Cat> cats = animals;
What is a static type system worth if it doesn't catch type errors at compile time?