Series of let definitions - functional-programming

I'm a beginner in OCaml, and i have a problem with series of let, like:
let x = myFun y in
let z = myFun x in
...
But, between the lets, i use Hashtbl.iter and other functions that returns unit. If i do:
let x = myFun y in
Hashtbl.iter (...) ...
let z = myFun x in
...
The compiler raises an error. But, if i do:
let x = myFun y in
let h = Hashtbl.iter (...) ...
let z = myFun x in
...
The compiler don't raise any error, just warnings showing that "h" is never used. What's the best way to do that without any problem? Thanks.

You have to use ; to separate expressions:
e1 ; e2
This performs the side-effects in e1 and discards the result, and then evaluates `e2.
So in your case:
let x = myFun y in
Hashtbl.iter (...) ... ;
let z = myFun x in
...

Note that you can write
let x = ... in
let _ = Hashtbl.iter in ...

Related

pass parameters to insided functions

Suppose I have a very simple function,
function func_in(x; y, z)
println(x + z)
end
which is called by another function
function test_dict(x, y, z...)
println(x + y )
func_in(z...)
end
I would like to pass parameter in z... to func_in. How could I do it in the right way? Note in func_in there are kargs and I could not find a way to pass parameter correctly.
The following code doesn't work
test_dict(1, 2, 15, 17, 19)
Many thanks!
UPDATE
I would like to be a little more elaborate about possible scenarios that parameters in z... could be very flexible.
function func_in(x; y, z, t1, t2, t3, t4)
println(x + t4)
end
Then how do I only pass x and t4, something like:
test_dict(1, 2, (x = 15, t4 = 19))
In R language, the ... works straightforwardly. Anything in ... would be used when it is cited. Like following, ... is directly passed to fn_2 and depatached accordingly. How to get similar behivor in Julia? I hope I have made myself clear.
fn_1 <- function(x, y, ...) {
fn_2(...)
}
Positional args and kwargs must be splatted separately:
func_in(args...; kwargs...)
Right now, you only pass positional inputs.
If you want to only pass kwargs to a function, you must do (note leading ;)
foo(; kwargs...)
BTW, it is considered good practice to always distinguish kwargs with a leading ;, even when it is not strictly necessary:
foo(x, y, a="hello", b=4) # legal
foo(x, y; a="hello", b=4) # better style
foo(a="hello", b=4) # legal
foo(; a="hello", b=4) # better style
Response to update: Keyword arguments must either have a default value, or you must provide a value for it when you call the function. You can for example write:
function func_in(x; y=nothing, z=nothing, t1=nothing, t2=nothing, t3=nothing, t4=nothing)
Another problem in your function test_dict, is that you must call it with three positional arguments, two for println and one for func_in, but you are only calling it with two positional arguments.
This will work:
function func_in(x; y=nothing, z=nothing, t1=nothing, t2=nothing, t3=nothing, t4=nothing)
println(x + t4)
end
function test_dict(x, y, z; w...) # note: *three* positional args
println(x + y )
func_in(z; w...)
end
test_dict(1, 2, 3; y = 15, t4 = 19) # three positional args
You can also use a named tuple and splat it:
kwargs = (y = 15, t4 = 19) # named tuple
test_dict(1, 2, 3; kwargs...)
Is this what you have in mind? :
julia> function func_in(x; y, z)
println(x + z)
end
func_in (generic function with 1 method)
julia> function test_dict(x, y, z...)
println(x + y )
func_in(z[1]; y = z[2], z = z[3])
end
test_dict (generic function with 1 method)
julia> test_dict(1, 2, 15, 17, 19)
3
34

How is lazy evaluation working in this example?

If I have this function:
let x = print_endline "foo" in x,x;;
it has this signature: unit * unit = ((), ())
and evaluates to foo
I dont understand why it prints foo once.
On the other hand: let x () = print_endline "foo" in x(),x();; will print foo twice and has the signature:
unit * unit = ((), ())
can someone explain the principle behind this and how it works in this specific example?
OCaml is an eager language unless directed otherwise. To create lazy values we use the lazy keyword, e.g., lazy (print_endline "foo") will create a lazy value of type unit Lazy.t that will print foo, once it is forced with Lazy.force.
All other values in OCaml are eager and are evaluated immediately. You got confused with the let .. in ... syntactic form.
The syntactic form
let <var> = <expr1> in <expr2>
first evaluates <expr1> and then evaluates <expr2> with the value of <expr1> bound to <var>. Finally, the result of <expr2> becomes the value of the whole form.
So when you say, let x = 2 in x + x you first evaluate 2 and bind it to x and then evaluate x + x with x=2, which is 4, so the value of the expression let x = 2 in x + x in 4. This is a pure expression, it doesn't define any functions and doesn't bind x in the global context.
Going back to your example,
let x = print_endline "foo" in x, x
we first evaluate <expr1>, which is print_endline "foo" that has the side effect of printing foo and returns the value () of type unit. Next, () is bound to x and the <expr2> is evaluated, which x,x, and which is equal to (),().
Your second example,
let x () = print_endline "foo" in x (), x ()
binds x to the function fun () -> print_endline "foo" since
let f x = <expr>
is the syntactic sugar for
let f = fun x -> <expr>
i.e., to a definition of a function.
Therefore, your expression first evaluates <expr1>, which is now fun () -> print_endline "foo" and binds it to x. Now you evaluate x (), x () and calls x () twice, both calls return ().
Finally, you said in your question that,
If I have this function: let x = print_endline "foo" in x,x;;
You don't have any functions there. Much like in let x = 2 in x + x, you are not defining any functions but just evaluate x+x with x bound to 2. After it is evaluated, there are no leftovers, x is not bound to anything. In C-like syntax, it is the same as
{
int x = 2;
x + x;
}
So if you want to define a function, you have to use the syntax
let <name> <params> =
<expr>
Where <expr> is the body of the function that is evaluated in a context where each parameter is substituted with its actual value (argument).
E.g.,
let print_foo () =
print_endline "foo"
or,
let sum_twice x y =
let z = x + y in
2 * z
I would suggest reading the OCaml Tutorial to get a better idea of OCaml syntax.
There is no lazy evaluation involved in this code at all. It would be more the other way around: lazy code (in OCaml) often involves having a function of the form () -> 'a instead of a value 'a, but this doesn't mean that any function of this form has to do with lazy evaluation.
In the first snippet, let x = print_endline "foo" in x, x, you are binding x to a value, the result of print_endline "foo", and then returning x, x. However, by doing so you must call print_endline "foo", which will print foo. At this point, x : unit = (). Then, you return x, x, that is, (), ().
In the second snippet, let x () = print_endline "foo" in x (), x (), you are defining a function x. That form is syntax sugar for let x = fun () -> print_endline "foo" in x (), x (). For this reason, before the evaluation of x (), x (), you have x : unit -> unit = <fun>. Then, you call that function twice, each time printing foo, and returning ().
Note that, when you write something like let x () = ..., you could also be writing let x (y: unit) = ..., except that since the type unit has a single constructor (()), OCaml allows you to deconstruct it directly in the function declaration. Which is why you are allowed to write let x () = ....

How to compute and evaluate composite function in GP?

I found a workaround to make composite function, but I believe there should be a better way to do this:
? f = x^2
%1 = x^2
? g = x^3
%2 = x^3
? x = g
%3 = x^3
? fog = eval(f)
%4 = x^6
? x = 2
%5 = 2
? result = eval(fog)
%6 = 64
In this method, I need to assign x many times and I don't want to use eval function. The code is not readable and maintainable.
You can simplify Piotr's nice answer to
comp(f, g) = x->f(g(x));
Indeed, you do not need to assign to the (global) variable h in the comp function itself. Also, the braces are not necessary for a single-line statement, and neither are type annotations (which are meant to optimize the byte compiler output or help gp2c; in this specific case they do not help).
Finally the parentheses around the argument list are optional in the closure definition when there is a single argument, as (x) here.
I would modify the examples as follows
f(x) = x^2;
g(x) = x^3;
h = comp(f, g);
? h('x) \\ note the backquote
%1 = x^6
? h(2)
%2 = 64
The backquote in 'x makes sure we use the formal variable x and not whatever value was assigned to the GP variable with that name. For the second example, there is no need to assign the value 2 to x, we can call h(2) directly
P.S. The confusion between formal variables and GP variables is unfortunate but very common for short names such as x or y. The quote operator was introduced to avoid having to kill variables. In more complicated functions, it can be cumbersome to systematically type 'x instead of x. The idiomatic construct to avoid this is my(x = 'x). This makes sure that the x GP variable really refers to the formal variable in the current scope.
PARI/GP supports the anonymous closures. So you can define the function composition on your own like this:
comp(f: t_FUNC, g: t_FUNC) = {
h = (x) -> f(g(x))
};
Then your code can be transformed to a more readable form:
f(x) = x^2;
g(x) = x^3;
h = comp(f, g);
h(x)
? x^6
x = 2; h(x)
? 64
Hope, this helps.

Can I pass keyword args to do-blocks in julia?

Below is an example:
def(f::Function) = f
f1 = def() do x
x
end
f2 = def() do x, y
x, y
end
f3 = def() do x, y; z # this syntax is accepted
x, y, z
end
f1(1)
f2(1, 2)
f3(1, 2, z=3) # ERROR: LoadError: function #13 does not accept keyword arguments
The example below is not my actual use case, but it illustrates the question. How should I handle kwargs in a do-block?
As far as I know this is not possible. If you look at /src/julia-parser.scm file you can find that parsing of a do block is defined in parse-do here. And you can see that do-block is rewritten to an anonymous function that can only accept positional arguments in doargs variable separated by commas.
In this line you can see that ; explicitly terminates parsing of arguments of do-block. This means that:
julia> z = "hello"
"hello"
julia> f3 = def() do x, y; println(z) # this syntax is accepted
x, y, z
end
#24 (generic function with 1 method)
julia> f3(100, 1000)
hello
(100, 1000, "hello")
will work as the code past ; is treated as a part of do-block body.
You could try to put ( and ) around the arguments like this:
julia> f3 = def() do (x, y; z)
x, y, z
end
ERROR: syntax: invalid assignment location "; z"
julia> f3 = def() do (y; z)
y, z
end
ERROR: syntax: "begin
y
# REPL[52], line 1
z
end" is not a valid function argument name
This will go through parser, but then julia-syntax.scm will throw an error. This probably could be improved as:
f3 = def(function(x, y; z)
x, y, z
end)
works correctly (you can consider opening an issue for this on https://github.com/JuliaLang/julia/issues).
Until this is fixed the only thing you can do is to use anonymous function definition approach I have given above (although it is not very clean).
You can do this, you just need to pass the kwargs before the do:
julia> f(g, xs; kwargs...) = begin
println(kwargs...)
map(g,xs)
end
f (generic function with 1 method)
julia> f(1:5; thisworks=true) do x x^2 end
:thisworks => true
5-element Array{Int64,1}:
1
4
9
16
25

Scope/order of evaluation of nested `let .. in ..` in OCaml

I have a little problems here that I don't 100% understand:
let x = 1 in let x = x+2 in let x = x+3 in x
I know the result of this expression is 6, but just want to make sure the order of calculating this expression; which part is calculated first?
You asked about the order of the evaluation in the expression let x=1 in let x=x+2 in .... The order is "left-to-right"! When you have a chain of let a=b in let c=d in ..., the order of evaluation is always left-to-right.
However, in your example there is a confusing part: you used the same variable name, x, in every let construct. This is confusing because you then see things like let x=x+1, and this looks like you are "redefining" x or "changing the value of x". But no "changing" of "x" actually happens here in OCAML! What happens here, as already pointed out above, is that a new variable is introduced every time, so your example is entirely equivalent to
let x = 1 in let y = x+2 in let z = y+3 in z;;
Note that here the order of evaluation is also left-to-right. (It is always left-to-right in every chain of let constructs.) In your original question, you chose to call all these new variables "x" rather than x, y, and z. This is confusing to most people. It is better to avoid this kind of coding style.
But how do we check that we renamed the variables correctly? Why "let x=1 in let y=x+2" and not "let x=1 in let x=y+2"? This x=x+2 business is quite confusing! Well, there is another way of understanding the evaluation of let x=aaa in bbb. The construct
let x=aaa in bbb
can be always replaced by the following closure applied to aaa,
(fun x -> bbb) aaa
Once you rewrite it in this way, you can easily see two things: First, OCAML will not evaluate "bbb" inside the closure until "aaa" is evaluated. (For this reason, the evaluation of let x=aaa in bbb proceeds by first evaluating aaa and then bbb, that is, "left-to-right".) Second, the variable "x" is confined to the body of the closure and so "x" cannot be visible inside the expression "aaa". For this reason, if "aaa" contains a variable called "x", it must be already defined with some value before, and it has nothing to do with the "x" inside the closure. For reasons of clarity, it would be better to call this variable by a different name.
In your example:
let x=1 in let x=x+2 in let x=x+3 in x
is rewritten as
(fun x -> let x=x+2 in let x=x+3 in x) 1
Then the inner let constructs are also rewritten:
(fun x -> (fun x -> let x=x+3 in x) x+2 ) 1
(fun x -> (fun x -> (fun x-> x) x+3) x+2 ) 1
Now let us rename the arguments of functions inside each function, which we can always do without changing the meaning of the code:
(fun x -> (fun y -> (fun z -> z) y+3) x+2 ) 1
This is the same as
let x=1 in let y=x+2 in let z=y+3 in z
In this way, you can verify that you have renamed the variables correctly.
Imagine parens:
let x = 1 in (let x = (x+2) in (let x = (x+3) in x))
Then substitute (x=1) where x it's not covered by another declaration of x and eliminate outermost let:
let x = (1+2) in (let x = (x+3) in x)
Evaluate:
let x = 3 in (let x = (x+3) in x)
Substitute:
let x = (3+3) in x
Evaluate:
let x = 6 in x
Substitute:
6
(This is a little long for a comment, so here's a smallish extra answer.)
As Chuck points out, there is no closure involved in this expression. The only complexity at all is due to the scoping rules. OCaml scoping rules are the usual ones, i.e., names refer to the nearest (innermost) definition. In the expression:
let v = e1 in e2
The variable v isn't visible (i.e., cannot be named) in e1. If (by chance) a variable of that name appears in e1, it must refer to some outer definition of (a different) v. But the new v can (of course) be named in e2. So your expression is equivalent to the following:
let x = 1 in let y = x+2 in let z = y+3 in z
It seems to me this is clearer, but it has exactly the same meaning.

Resources