Since Ocaml utilizes type inferences, and functions are a type, do I have to use fun to declare a function? For example, the REPL/interpreter for Ocaml executes this statement without complaint:
let average a b =
(a +. b) /. 2.0;;
Does this mean that I can dispense with fun when declaring functions? When is it needed, or is it ever needed?
The keyword fun is needed with anonymous functions. For instance, the following code doubles each elements of the list l = [ 1; 2; 3; 4]
let l = [1; 2; 3; 4]
let doubled_l = List.map (fun x -> 2 * x) l
but this snippet could be rewritten as
let l = [1; 2; 3; 4]
let double x = 2 * x
let doubled_l = List.map double l
( or even List.map ( ( * ) 2 ) l )
Contrarily, your average function could be rewritten as
let average = fun x y -> (x +. y) /. 2.
or
let average = fun x -> fun y -> (x +. y) /. 2.
(the syntax average x y = ... is in fact a syntactic sugar for this form)
let average a b = ... is exactly equivalent to let average = fun a b -> ... - you can always use the former over the latter. It's just a matter of style which one you prefer. My feeling is that most programmers use the former form, but some introductory materials use the latter form to make it clear that functions are values just like any other and can be created using the fun keyword.
However let f = fun ... is not the only way to use fun. You can use it wherever a value of a function type is expected, for example as an argument to map. So if you have something like List.map (fun x -> x+1) xs, you can't just put a let in place of the fun because a definition makes no syntactic sense there. You could of course use let add1 x = x+1 in List.map add1 xs and that works fine, but that's more verbose and introduces a new name that's only used once and doesn't really add anything.
So fun is useful when you want to pass a function around without giving it a name.
Related
Lets assume the following function
val foo : int -> int -> bool -> int
let foo x y b =
let x,y = if x > y then y,x else x,y in
let rec loop x y b =
if x >= then x
else if b then loop (x+1) y (not b)
else loop x (y-1) (not b)
in
loop x y b
I still don't quite understand the concept of the "in".
Does the line mean "let x,y = ... in" that it is executed immediately or only when you "Call" it? And when i dont need to call it why do i need the last line loop x y b?
Thanks in advance :)
in is just part of the OCaml syntax - let PATTERN = EXPR1 in EXPR2 is an expression which binds the result of EXPR1 to PATTERN and then evaluates EXPR2 with the new bindings present. In some languages like F# and Haskell, you don't (always) need in - it's inferred from the indentation. OCaml syntax is indentation insensitive which requires it to have an explicit in.
Does the line mean "let x,y = ... in" that it is executed immediately or only when you "Call" it?
It's evaluated immediately.
And when i dont need to call it why do i need the last line loop x y b?
In this code, the previous line defines a function named loop with 3 arguments, and then later you call the function with the arguments x y b.
I am trying to write a function in Julia that takes in a multi-dimensional array (a data cube) and rescales every entry from 0 to 1. However, whenever I run the code in atom, I get the error
LoadError: MethodError: no method matching -(::Array{Float64,2}, ::Float64)
Closest candidates are:
-(::Float64, ::Float64) at float.jl:397
-(::Complex{Bool}, ::Real) at complex.jl:298
-(::Missing, ::Number) at missing.jl:97
...
Stacktrace:
[1] rescale_zero_one(::Array{Float64,2}) at D:\Julio\Documents\Michigan_v2\CS\EECS_598_Data_Science\codex\Codex_3\svd_video.jl:40
[2] top-level scope at D:\Julio\Documents\Michigan_v2\CS\EECS_598_Data_Science\codex\Codex_3\svd_video.jl:50 [inlined]
[3] top-level scope at .\none:0
in expression starting at D:\Julio\Documents\Michigan_v2\CS\EECS_598_Data_Science\codex\Codex_3\svd_video.jl:48
I have the basics of what my function must do, but I really don't understand some of the notation and what the error is telling or how to fix it.
function rescale_zero_one(A::Array)
B = float(A)
B -= minimum(B)
B /= maximum(B)
return B
end
m,n,j = size(movie_cube)
println(j)
C = Array{Float64}(UndefInitializer(),m,n,j)
for k in 1:j
println(k)
C[:,:,j] = rescale_zero_one(movie_cube[:,:,j])
end
the variable movie_cube is a 3 dimensional data array of Float64 entries and I just want to rescale the entries from zero to one. However, the error that I mentioned keeps appearing. I would really appreciate any help with this code!
Try to use dot syntax for doing some operations in an array!
function rescale_zero_one(A::Array)
B = float.(A)
B .-= minimum(B)
B ./= maximum(B)
return B
end
This code is a bit faster and simpler (it only makes two passes over the input matrix rather than five in the previous answer):
function rescale(A::Matrix)
(a, b) = extrema(A)
return (A .- a) ./ (b - a)
end
This can be generalized to three dimensions, so that you don't need the outer loop over the dimensions in C. Warning: this solution is actually a bit slow, since extrema/maximum/minimum are slow when using the dims keyword, which is quite strange:
function rescale(A::Array{T, 3}) where {T}
mm = extrema(A, dims=(1,2))
a, b = first.(mm), last.(mm)
return (A .- a) ./ (b .- a)
end
Now you could just write C = rescale(movie_cube). You can even generalize this further:
function rescale(A::Array{T, N}; dims=ntuple(identity, N)) where {T,N}
mm = extrema(A, dims=dims)
a, b = first.(mm), last.(mm)
return (A .- a) ./ (b .- a)
end
Now you can normalize your multidimensional array along any dimensions you like. Current behaviour becomes
C = rescale(movie_cube, dims=(1,2))
Rescaling each row is
C = rescale(movie_cube, dims=(1,))
Default behaviour is to rescale the entire array:
C = rescale(movie_cube)
One more thing, this is a bit odd:
C = Array{Float64}(UndefInitializer(),m,n,j)
It's not wrong, but it is more common to use the shorter and more elegant:
C = Array{Float64}(undef, m, n, j)
You might also consider simply writing: C = similar(movie_cube) or C = similar(movie_cube, Float64).
Edit: Another general solution is to not implement the dimension handling in the rescale function, but to rather leverage mapslices. Then:
function rescale(A::Array)
(a, b) = extrema(A)
return (A .- a) ./ (b - a)
end
C = mapslices(rescale, A, dims=(1,2))
This is also not the fastest solution, for reasons I don't understand. I really think this ought to be fast, and might be sped up in a future version of Julia.
i am trying to make a function that returns the value of first k elements in a list. This is not working. I do not know why.
Can someone help?
This is the tl function -
let tl j = match j with
| [] -> []
| x :: xs -> xs;;
This is the real take function-
let rec take k xs = function
| [] -> failwith "take"
| x :: xs -> if k = List.length ([x] # xs) then [x] # xs
else [x] # take List.length xs (tl(List.rev.xs))
The cause for the message is that you left out a pair of parentheses, so you're trying to pass List.length as the first parameter to take.
Another problem is that you're defining a function with three parameters – your definition says that take k xs returns a function that takes a list argument (which is unnamed).
A third problem is take (List.length xs) (tl(List.rev xs)).
This attempts to take one more element than there are from the tail of xs (and, for some reason, in reverse).
So I'm going to rewrite it completely.
First of all, you should not use List.length for this.
(List.length is almost never a good solution.)
You only need to care about whether the list is empty or not, it doesn't matter how long it is.
Now, a more formal definition:
take k xs is
if k is 0, it's the empty list
otherwise, if xs is the empty list, it's an error
otherwise, it is the list whose first element is the head of xs, and whose tail is the result of taking k - 1 elements from the tail of xs.
That is,
let rec take k xs = match k with
| 0 -> []
| k -> match xs with
| [] -> failwith "take"
| y::ys -> y :: (take (k - 1) ys)
Your function accepts an integer n, and takes n elements from a list list, which is the list which contains the n first elements of list.
So your signature is likely to be:
int -> 'a list -> 'a list = <fun>
You probably already can guess that the function is going to be defined recursively, so you can already write the definition of your function like this:
let rec take n list = ...
You have to build a list, but let's first consider three major classes of values for n:
n = 0 : just return an empty list
n > 0 : take one element and recurse with n - 1
n < 0 : The negative case is easy to miss, but if you are not cautious, you can easily enter an infinite recursion at runtime with invalid inputs. Here, fortunately, we are going to use an exception and make things terminate down the recursive chain (that's what happens in moldbino's answer, for example), but other functions might not behave as nicely.
Some implementations of take, when given a negative numbers, try to be useful and takes n elements from the end of the list.
Here we will simply treat any n that is not strictly positive as-if if was null.
Null or negative N
When we take zero elements from a list, that means that we return the empty list:
let rec take n list =
if n > 0
then ...
else [];;
Positive N
Now, we consider the case where we take n > 0 elements from a list.
Following the recursive definition of lists, we have to consider each possible kind of lists, namely the empty list and non-empty lists.
let rec take n list =
if n > 0
then
match list with
| [] -> ...
| x :: xs -> ...
else [];;
What happens when we want to take n > 0 elements from an empty list?
We fail.
let rec take n list =
if n > 0 then
match list with
| [] -> failwith "Not enough elements in list"
| x :: xs -> ...
else [];;
Now, the general case of recursion. We have a non-empty list, and n > 0, so we know that we can take at least one element from the list.
This value is x, which forms the head of the list we want to return. The tail of the list is the one made of the n-1 elements of xs, which is easily computed by take itself:
let rec take n list =
if n > 0 then
match list with
| [] -> failwith "Not enough elements in list"
| x :: xs -> x :: (take (n - 1) xs)
else [];;
Your immediate problem is that you need parentheses around (List.length xs). The code also treats an empty input list as an error in all cases, which is not correct. An empty list is a legitimate input if the desired length k is 0.
Update
You also have one extra parameter in your definition. If you say this:
let myfun k xs = function ...
the function myfun has 3 parameters. The first two are named k and xs and the third is implicitly part of the function expression.
The quick fix is just to remove xs.
I think you might be asking for the wrong number of elements in your recursive call to take. Something to look at anyway.
I have two functions f and g:
let f (x:float) (y:float) =
x * y
let g (x:float) =
x * 2.0
I want to compose (>>) them to get a new function that performs f and then g on the result.
The solution should behave like:
let h x y =
(f x y) |> g
This does not work:
// Does not compile
let h =
f >> g
How should >> be used?
I think you want to achieve this:
let fog x = f x >> g
You can't compose them directly f >> g in that order, it makes sense since f expects two parameters, so doing f x will result in a partially applied function, but g expects a value, not a function.
Composing the other way around works and in your specific example you get even the same results, because you are using commutative functions. You can do g >> f and you get a composition that results in a partially applied function since g expects a single value, so by applying a value to g you get another value (not a function) and f expects two values, then you will get a partially applied function.
Writing in point-free style, i.e. defining functions without explicit arguments, can become ugly when the implicit arguments are more than one.
It can always be done, with the correct combination of operators. But the outcome is going to be a disappointment and you will lose the primary benefit of point-free style - simplicity and legibility.
For fun and learning, we'll give it a try. Let's start with the explicit (a.k.a. "pointful") style and work from there.
(Note: we're going to rearrange our composition operators into their explicit form (>>) (a) (b) rather than the more usual a >> b. This will create a bunch of parentheses, but it will make things easier to grok, without worrying about sometimes-unintuitive operator precedence rules.)
let h x y = f x y |> g
let h x = f x >> g
// everybody puts on their parentheses!
let h x = (>>) (f x) (g)
// swap order
let h x = (<<) (g) (f x)
// let's put another pair of parentheses around the partially applied function
let h x = ((<<) g) (f x)
There we are! See, now h x is expressed in the shape we want - "pass x to f, then pass the result to another function".
That function happens to be ((<<) g), which is the function that takes a float -> float as argument and returns its composition with g.
(A composition where g comes second, which is important, even if in the particular example used it doesn't make a difference.)
Our float -> float argument is, of course, (f x) i.e. the partial application of f.
So, the following compiles:
let h x = x |> f |> ((<<) g)
and that can now be quite clearly simplified to
let h = f >> ((<<) g)
Which isn't all that awful-looking, when you already know what it means. But anybody with any sense will much rather write and read let h x y = f x y |> g.
The following code gives an error:
let alpha = Hashtbl.create 26 in
let print_and_add a =
print_char a;
Hashtbl.add alpha a true;;
let str = read_line () in
String.iter (fun x -> if Hashtbl.mem alpha x=false then print_and_add x) str
What it's supposed to do:each time the function is called (with a char argument),it should print the char,and add it to the Hash table (alpha).
I tried using the other syntax for functions:
let alpha = Hashtbl.create 26 in
let print_and_add = (fun a ->
print_char a;
Hashtbl.add alpha a true) in
let str = read_line () in
String.iter (fun x -> if Hashtbl.mem alpha x=false then print_and_add x) str
But I still want to know why the first code fails.
-Thanks for any help.
The ;; symbol specifically marks the end of an expression at the global level. So everything after it has to be part of a different expression. Hence alpha can't be defined after that.
I never use ;; in source code, only when typing to the toplevel. In my opinion, that's what it's for.
Your code also has let print_and_add ... without a corresponding in. This is valid only at the global level (not inside an expression).
If you change ;; to in in your original code, you get something that works. At least it works for me.
alpha is no longer in scope when you attempt to use it the second time in the first snippet.