Several exercices in “learn-kotlin” are ill designed and information is misleading if not erroneous.
For example, in the “Arithmetic” section it is written
var a=2020;
a++ // 2021
This is misleading, since the result of a++ is 2020, not 2021: see “print(a++)”.
It would be much better to teach to use “++a” instead (or avoid ++ in favour of “+= 1”.)
Also, in the section on conditionals, you ask to print a message if isTuesday (is true is true…). However, the correct command to do this,
if(isTuesday) print(…)
is not accepted, because the designer of the exercise does not seem to know that { … } is only needed when you have/need a block of (more than one) instructions. (The author also confuses here and elsewhere* “if expression” (which needs an else part) and “if statement” which does not need the else part).
[* lesson/ exercise on “else” where again {…} is implicitly required in the exercise but not in the language; idem in CoffeeRewards.kt etc…]
There are many other such bugs, e.g.:
in the exercise where a tip is to be calculated, it is not recognized that total*(1+tip) is the correct formula, the author requires you to use " total + total*tip " instead (although this results in the same value stored in the variable and printed to the console)
in the exercise on order-of-operations it is claimed that multiplication is done before division, and addition before subtraction. This is wrong. This would mean e.g. that 10 - 1 + 2 = 10 - 3 = 7, but of course the subtraction is done before the addition and the result is 9 + 2 = 11. Similarly, if multiplication would be done before division, then 8 / 22 = 8 / 4 = 2, but fortunately 8/22 = 4*2 = 8 as expected according to standard mathematical definitions.
and so on …
PS: I did not find a better place to post this… please transfer if not appropriate in this category.
I can see where you’re coming from on these points, but if you look at it from the perspective of an absolute zero-knowledge beginner…
Depends on how you’re defining “result”.
If you mean return value, then sure; as a postfix operator, the return value of a++ is the original value of a (or a0). The effect on the operand, though, is a+1 as stated.
++a does the same thing, but as a prefix operator its return value is the modified value of a rather than the original value.
This behaviour is not unique to Kotlin, but at the point of introducing an absolute beginner to increment operators in the language I’m not sure that explaining this would aid comprehension. Whether this is erroneous would depend greatly on the text of the exercise, I think.
You can equally write:
if (isTuesday) {
print(...)
}
and have it accepted by Kotlin.
This is an introductory course, after all; the designers may well have opted to introduce the more broadly applicable grammar of if (expression) { statement(s) } deliberately. To an absolute novice, immediately introducing both forms of the if expression might cause unnecessary confusion. (Again, I’ve not done the course and haven’t seen the text…)
I wonder whether this is an unfortunate consequence of US mathematics teaching using the mnemonic of PEMDAS, which would suggest that multiplication and addition take precedence over division and subtraction… but yeah, that doesn’t seem right. If you have the link, I’ll take a look and report it as necessary.
If we wanted to be truly pedantic...
The US mnemonic (PEMDAS) and the UK mnemonic (BODMAS) are equally incorrect if taken literally…
Division and multiplication are of equal precedence, as are addition and subtraction. In a mathematical expression which only features MD or AS operations, one simply evaluates in-order from left to right.
This is why 8 ÷ 2 * 2 = 8, and why 10 - 1 + 2 = 11… and Kotlin correctly groups multiplicative and additive operators:
I have a feeling that you know more about Kotlin than the course designers anticipated for those taking the course; the material is likely assuming zero prior knowledge, which doesn’t seem to be an accurate description for your level of understanding.
In any case if you can give us a link to the exercises in question, we’ll take a look over them and see whether these things are actually bugs or potentially “by design” decisions made to make learning the basics a little easier.
This is not to say that you’re wrong, per se, simply that you know the language well enough to recognise where things might have been simplified for those coming to the material without that level of understanding.
Yes – which confirms that “2°) multiplication, 3°) division” doesn’t make sense : both must be on the same level , and it is so-called associativity which rules in which order they are executed “within their group”.
Yes, of course I know about this behaviour and the numerous discussions about i++ vs. ++i .
I think most of those who have pondered the problem agree that i++ should not be taught to newcomers – it may be counter-intuitive, error-prone, and also have considerable performance impact.
Of course people (like me) who have used i++ for 30++ years are used to read and write this more easily than ++i, but we should maybe try to convert our habits. But most of all, we should avoid newcomers take this bad habit. Only when really needed, i++ should be used ; in most cases we want ++i, and I think this is easy to teach (just say: “++” means “increase” : you say “increase i”, not “i increase” - unless you’re Yoda).
I think for newcomers a prefix operator (already known from NOT, minus sign, etc…) is much more intuitive than a postfix operator. And the post-increment operation is complicated. It is incorrect to tell the newbies that “a++” is “a incremented by 1” – it is “the value of a before incrementing it by 1”. If one wants to avoid ugly complications like that, don’t introduce a++ ; introduce (only) ++a if you wish. If they learn later on that “a++” also exists and it does a weird thing, there’s no harm to that.
var pungency: String
if (sHU in 0..699 ) {pungency="very mild"}
else if (sHU in 700..2999) {pungency="mild"}
else if (sHU in ...) {pungency="..."}
else if (sHU in ...) {pungency="..."}
else ...
(with {…} or else the answer isn’t accepted),
although in the previous lecture(s) it has just been said that "programmers often use when to avoid lengthy if - else chains. So it is inconsistent to oblige the learners to do what they know how to and should avoid. It could be coded more concisely
var pungency: String =
when (sHU){
in 0..699 -> "very mild"
in 700..2999 -> "mild"
in 3000..24999 -> "moderate"
in 25000..69999 -> "high"
else -> "very high"}
or, with if-then, as
pugnency =
if( sHU in ...) "very mild"
else if ( sHU in ...) "mild"
//...
else "very high"
to avoid at least the unneeded duplication of the assignment operator.
No, it seems you didn’t read the phrase. Within the group of operators of same precedence (e.g., the group { +, - } or the group { *, / }), as I wrote, it is associativity which decides in which order they are done.
Your example misses the spot, no-one doubts that the product * is to be evaluated first, and then the +. The question is, e.g., in 5 - 3 - 1, or 5 / 3 * 2, what is to be done first. Here the rule is “from left to right” (e.g.: (5 - 3) - 1, and not 5 - (3 - 1)), for other operators it may be “from right to left”, e.g. " a := b := c" (in languages which allow that, it is always a := (b:=c), so the rightmost one is done first), or a^b^c (where “^” means “to the power of”, which usually is a^(b^c) in languages that allow this.)
This clearly states that Subtraction is done AFTER Addition, which is wrong!
Proof/Example (already given in the O.P. but…): Compute 6 - 2 + 3.
If addition were done before subtraction, as the above list claims, this would yield 6 - (2+3) = 6 - 5 = 1.
But this is not the result that Kotlin will give! Here the subtraction will be done BEFORE addition: it will yield (6-2)+3 = 4+3 = 7.
Similarly, if Multiplication were to be done BEFORE division, as the table claims, then
6 / 2 * 3 =?= 6 / (2*3) = 6 / 6 = 1. But this is NOT correct and NOT the order of operations in Kotlin.
In Kotlin, 6 / 2 * 3 = (6 /2) * 3 = 3 * 3 = 9, so here Division is done BEFORE multiplication, not after as the above table claims.
So the above erroneous numbering HAS to be removed to make the statement correct! Else it is wrong!
It must say:
Parentheses
Multiplication or division or modulus, from left to right
Yes, that’s what I’m saying since the beginning… (up to a small detail:
“so they are done from left to right” is not correct, it must read “…, they are done from left to right”, without “so”.
Because, as I explain above in other posts, this is not necessarily so: There may be right-to-left associative operators. When such operator occur multiple times, they are evaluated from right to left. I gave the examples of exponential/power (^ or **) and assignment ( := ) operators, even though these examples don’t apply to Kotlin which has no ** and where assignment is a statement. (So you can’t do a = b = c, or can you? If so, it certainly would be a = (b=c), i.e., from right to left, and not left to right, (a=b)=c.) I don’t now Kotlin well enough to provide a better example here.)