OCaml meaning of "in" - function

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.

Related

How to write function in Julia v1.1 that inputs multi-dimensional array?

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.

F# function composition where the first function has arity >1

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.

ML variables in functions

I can't seem to find a simple answer to this seemingly simple SML question. I have the code:
fun inde(x, y, L) = if null L then nil else
if x=hd(L) then y+1::inde(x,y+1,tl L) else
inde(x,y+1,tl L);
I want y to be a variable outside the function, so it'll be inde(x,L) but have the y still count properly. When I declare it outside the function (to 0), when the function is recursively called, it resets to 0.
If you were to run this current function, it'd produce a list of where ever x is in the list (L).
so inde(1,0,[1,2,2,1,1]) would produce [1,4,5]
Idiomatic structure when using a functional programming style is to define an inner function that takes arguments that are of interest to the programmer, but not the user and then to call the inner function from the main function:
fun inde(x : int, L) =
let
fun inner(list1, list2, y : int) =
if null list1
then List.rev list2
else
if x = hd list1
then
inner(tl list1, y::list2, y + 1)
else
inner(tl list1, list2, y +1)
in
inner(L,[],1)
end
In the example function:
inner uses four values: the local variables list1,list2, and y. It also uses x from the enclosing scope.
inner builds (conses up) the list that will be returned using list2. It reverses the list with a call to List.rev from the SML Basis Library. This adds O(n) to the execution time.
The last part of the let...in...end construct: inner(L,[],1) is called "the trampoline" because the code gets all the way to the bottom of the source file and then bounces off it to start execution. It's a standard pattern.
Note that I started iterating with y equal to 1, rather than 0. Starting at zero wasn't getting anything done in the original file.

Error plotting a function of 2 variables

I am trying to plot the function
f(x, y) = (x – 3).^2 – (y – 2).^2.
x is a vector from 2 to 4, and y is a vector from 1 to 3, both with increments of 0.2. However, I am getting the error:
"Subscript indices must either be real positive integers or logicals".
What do I do to fix this error?
I (think) I see what you are trying to achieve. You are writing your syntax like a mathematical function definition. Matlab is interpreting f as a 2-dimensional data type and trying to assign the value of the expression to data indexed at x,y. The values of x and y are not integers, so Matlab complains.
If you want to plot the output of the function (we'll call it z) as a function of x and y, you need to define the function quite differently . . .
f = #(x,y)(x-3).^2 - (y-2).^2;
x=2:.2:4;
y=1:.2:3;
z = f( repmat(x(:)',numel(y),1) , repmat(y(:),1,numel(x) ) );
surf(x,y,z);
xlabel('X'); ylabel('Y'); zlabel('Z');
This will give you an output like this . . .
The f = #(x,y) part of the first line states you want to define a function called f taking variables x and y. The rest of the line is the definition of that function.
If you want to plot z as a function of both x and y, then you need to supply all possible combinations in your range. This is what the line containing the repmat commands is for.
EDIT
There is a neat Matlab function meshgrid that can replace the repmat version of the script as suggested by #bas (welcome bas, please scroll to bas' answer and +1 it!) ...
f = #(x,y)(x-3).^2 - (y-2).^2;
x=2:.2:4;
y=1:.2:3;
[X,Y] = meshgrid(x,y);
surf(x,y,f(X,Y));
xlabel('x'); ylabel('y'); zlabel('z');
I typically use the MESHGRID function. Like so:
x = 2:0.2:4;
y = 1:0.2:3;
[X,Y] = meshgrid(x,y);
F = (X-3).^2-(Y-2).^2;
surf(x,y,F);
xlabel('x');ylabel('y');zlabel('f')
This is identical to the answer by #learnvst. it just does the repmat-ing for you.
Your problem is that the function you are using uses integers, and you are trying to assign a double to it. Integers cannot have decimal places. To fix this, you can make it to where it increases in increments of 1, instead of 0.2

calling arrayfun; parameter estimation;

I have a problem with estimation.
I have a function, which is dependent on the values of an unknown vector V = [v1, …, v4].
I also have a vector of reference data YREF = [yref1, …, yrefn].
I would like to write a function, which returns the vector Y (in order to compare it later, say using lsqnonlin). I am aware of the “arrayfun”, but it seems not to work.
I have a subfunction, which returns a concrete value from the range [-100, 100],
%--------------------------------------------------------------------------
function y = SubFunction(Y, V)
y = fzero(#(x) v(1).*sinh(x./v(2)) + v(3).*x - Y, [-100 100]);
end
%--------------------------------------------------------------------------
then I make some operations on the results:
%--------------------------------------------------------------------------
function y = SomeFunction(Y,V)
temp = SubFunction (Y,V);
y = temp + v(4).*Y;
end
%--------------------------------------------------------------------------
These functions work well for a single value of Y, but not for the whole vector. How to store the results into a matrix for future comparison?
Thanks in advance
Chris
If Y is a vector, then the anonymous function defined as an argument to fzero returns a vector, not a scalar.
You can solve it by using a loop (notice the Y(k) inside the anonymous function definition):
function y = SubFunction(Y, v)
y = zeros (size(Y));
for k = 1 : length (Y)
y(k) = fzero(#(x) v(1).*sinh(x./v(2)) + v(3).*x - Y(k), [-100 100]);
end
end