Can everyone explain to me this piece of code ?
let safe_division n = function
| 0 -> failwith "divide by 0"
| m -> n / m
When I excute safeDiv 3 0
, what is the m
and n
in this case ?
In general case, when does the function match the first and second pattern ?
The pattern h :: t matches any non-empty list, calls the head of the list h (one element, the first one), and the tail of the list t (zero or more elements after the first one). The operator :: is the list constructor (often called "cons"), which is why these patterns match lists.
Pattern matching occurs when evaluating a function call, case- receive- try- expressions and match operator (=) expressions. In a pattern matching, a left-hand side pattern is matched against a right-hand side term. If the matching succeeds, any unbound variables in the pattern become bound.
It is usually used if you have a function or value that is very similar to some other, but is in some way new or modified. Regarding the :: symbol - as already mentioned, it is used to create lists from a single element and a list ( 1::[2;3] creates a list [1;2;3] ).
Basically, pattern matching works by providing some pattern you expect in the data and then checking whether this pattern matches the data. It all starts with the match operator, = . Yup. In Elixir, we don't assign variables; we match them. iex(1)> x = 1 1.
It is easy to see what this means once you realise that
let f x y z = e
is just a short-hand for
let f = function x -> function y -> function z -> e
That is, a function of n arguments actually is n nested functions of 1 argument. That representation is called "currying". It is what allows you to apply a function partially, e.g.
let g = f 3
returns a function of 2 arguments.
Of course, the short-hand above can be mixed freely with the explicit form on the right, and that's what your example does. You can desugar it into:
let safe_division = function n -> function
| 0 -> failwith "divide by 0"
| m -> n / m
When you execute safe_division 3 0
, first, 3
is bound to the name n
and the right-hand side of the declaration is then evaluated.
This is a function
, so the next argument, 0
, is matched against the different cases, in order. Here, it matches the first case, so the right-hand side is evaluated and an exception is thrown. In this case, the name m
is never bound to anything.
If the second argument was, for example, 1
, then it would have matched the second case (this case matches every possible value anyway, it's a default case), binding the name m
to the value 1
and then returning the result of n / m
.
let safe_division n
define a function which type is int -> ...
function
| 0 -> failwith "divide by 0"
| m -> n / m
define a function which type is int -> int
So the resulting type of the whole is int -> int -> int where n is the first argument, and m the second. The last int is the result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With