Consider the following,
val x: Int = 0
val variables cannot be changed so doing x += 1 wouldn't work
The compiler says Val cannot be reassigned
why then does x.inc() work fine
doesn't x.inc() reassign the value from 0 to 1
x.inc() does not increment the variable x. Instead, it returns a value that is one more than the value of x. It does not change x.
val x = 0
x.inc() // 1 is retuned, but discarded here
print(x) // still 0!
As its documentation says:
Returns this value incremented by one.
That might seem like a very useless method. Well, this is what Kotlin uses to implement operator overloading for the postfix/prefix ++ operator.
When you do a++, for example, the following happens:
Store the initial value of a to a temporary storage a0.
Assign the result of a0.inc() to a.
Return a0 as the result of the expression.
Here you can see how inc's return value is used.
I'm learning OCaml, and the docs and books I'm reading aren't very clear on some things.
In simple words, what are the differences between
-10
and
~-10
To me they seem the same. I've encountered other resources trying to explain the differences, but they seem to explain in terms that I'm not yet familiar with, as the only thing I know so far are variables.
In fact, - is a binary operator, so some expression can be ambigous : f 10 -20 is treated as (f 10) - 20. For example, let's imagine this dummy function:
let f x y = (x, y)
If I want produce the tuple (10, -20) I naïvely would write something like that f 10 -20 which leads me to the following error:
# f 10 -20;;
Error: This expression has type 'a -> int * 'a
but an expression was expected of type int
because the expression is evaluated as (f 10) - 20 (so a substract over a function!!) so you can write the expression like this: f 10 (-20), which is valid or f 10 ~-20 since ~- (and ~+ and ~-. ~+. for floats) are unary operators, the predecense is properly respected.
It is easier to start by looking at how user-defined unary (~-) operators work.
type quaternion = { r:float; i:float; j:float; k:float }
let zero = { r = 0.; i = 0.; j = 0.; k = 0. }
let i = { zero with i = 1. }
let (~-) q = { r = -.q.r; i = -.q.i; j = -. q.j; k = -. q.k }
In this situation, the unary operator - (and +) is a shorthand for ~- (and ~+) when the parsing is unambiguous. For example, defining -i with
let mi = -i
works because this - could not be the binary operator -.
Nevertheless, the binary operator has a higher priority than the unary - thus
let wrong = Fun.id -i
is read as
let wrong = (Fun.id) - (i)
In this context, I can either use the full form ~-
let ok' = Fun.id ~-i
or add some parenthesis
let ok'' = Fun.id (-i)
Going back to type with literals (e.g integers, or floats), for those types, the unary + and - symbol can be part of the literal itself (e.g -10) and not an operator. For instance redefining ~- and ~+ does not change the meaning of the integer literals in
let (~+) = ()
let (~-) = ()
let really = -10
let positively_real = +10
This can be "used" to create some quite obfuscated expression:
let (~+) r = { zero with r }
let (+) x y = { r = x.r +. y.r; i = x.i +. y.i; k = x.k +. x.k; j =x.k +. y.j }
let ( *. ) s q = { r = s *. q.r; i = s *. q.i; j = s *. q.j; k = s *. q.k }
let this_is_valid x = +x + +10. *. i
OCaml has two kinds of operators - prefix and infix. The prefix operators precede expressions and infix occur in between the two expressions, e.g., in !foo we have the prefix operator ! coming before the expression foo and in 2 + 3 we have the infix operator + between expressions 2 and 3.
Operators are like normal functions except that they have a different syntax for application (aka calling), whilst functions are applied to an arbitrary number of arguments using a simple syntax of juxtaposition, e.g., f x1 x2 x3 x41, operators can have only one (prefix) or two (infix) arguments. Prefix operators are very close to normal functions, cf., f x and !x, but they have higher precedence (bind tighter) than normal function application. Contrary, the infix operators, since they are put between two expressions, enable a more natural syntax, e.g., x + y vs. (+) x y, but have lower precedence (bind less tight) than normal function application. Moreover, they enable chaining several operators in a row, e.g., x + y + z is interpreted as (x + y) + z, which is much more readable than add (add (x y) z).
Operators in OCaml distinguished purely syntactically. It means that the kind of an operator is fully defined by the first character of that operator, not by a special compiler directive, like in some other languages (i.e., there is not infix + directive in OCaml). If an operator starts with the prefix-symbol sequence, e.g., !, ?#, ~%, it is considered as prefix and if it starts with an infix-symbol then it is, correspondingly, an infix operator.
The - and -. operators are treated specially and can appear both as prefix and infix. E.g., in 1 - -2 we have - occurring both in the infix and prefix positions. However, it is only possible to disambiguate between the infix and the prefix versions of the - (and -.) operators when they occur together with other operators (infix or prefix), but when we have a general expression, the - operator is treated as infix. E.g., max 0 -1 is interpreted as (max 0) - 1 (remember that operator has lower precedence than function application, therefore when they two appear with no parentheses then functions are applied first and operators after that). Another example, Some -1, which is interpreted as Some - 1, not as Some (-1). To disambiguate such code, you can use either the parentheses, e.g., max 0 (-1), or the prefix-only versions, e.g, Some ~-1 or max 0 ~-1.
As a matter of personal style, I actually prefer parentheses as it is usually hard to keep these rules in mind when you read the code.
1) Purists will say that functions in OCaml can have only one argument and f x1 x2 x3 x4 is just ((f x1) x2) x3) x4, which would be a totally correct statement, but a little bit irrelevant to the current discussion.
How can I check if a variable is equal to something, and set to a new variable in the child scope?
For example:
bar = 'foobar'
my_slice = bar[:3]
if my_slice == 'foo':
print(my_slice)
It seems like the new walrus operator here would be useful, but it's not immediately straightforward how you'd go about using it here
Walrus operators work here very well, we just need to understand exactly how they work.
if (my_slice := bar[3:]) == 'foo':
print(my_slice)
Walrus operators set a variable to the output of some expression. It's almost identical to the equal sign in function except it can be used inline.
So this expression:
(my_slice := bar[3:]) == 'foo'
Can be boiled down to (variable = expression) == value
So because the output of my_slice := bar[:3] is equal to bar[:3], the above is equivalent to
bar[3:] == 'foo'
Note: The parenthesis here are required, or else variable is going to equal the output of the comparison operation, i.e. True or False
I cannot think of a case where using the Kotlin built-in plus, minus, times etc. functions would return a different result from just using the corresponding operators (+, -, *). Why would you ever want to use these functions in your Kotlin code?
Just in case you aren't aware, these are operator overloads. The named functions are how the operators' functionality is defined.
There is a case for using the named versions. The function calls don't pay attention to operator precedence and are evaluated sequentially if you chain them.
val x = 1
val y = 2
val z = 3
println(x + y * z) // equivalent to 1 + (2 * 3) -> 7
println(x.plus(y).times(z)) // equivalent to (1 + 2) * 3 -> 9
This could be clearer than using the operators if you have a lot of nested parentheses, depending on the context of the type of math you're doing.
result = ((x - 7) * y - z) * 10
// vs
result = x.minus(7).times(y).minus(z).times(10)
It's not really applicable for basic algebra like this, but you might have classes with operator overloads where the logic can be more easily reasoned through with the sequential approach.
By explicitly stating function names you can perform a safe call on a nullable number which cannot be done with an operator.
For example:
fun doubleOrZero(num: Int?) : Int {
return num?.times(2) ?: 0
}
In code, why wouldn't this work?
intMax = intTopValue = 20
This is interpreted as intMax = (intTopValue = 20).
intTopValue = 20 will check whether intTopValue is equal to 20 and return true or false.
This boolean will then be assigned to intMax.
Most languages don't have this issue, since they use separate operators for assignment (= or :=) and equality (== or =).
By contrast, VB shares = for both operations. Therefore, when a = b is written as an expression, it always means equality.