Difference(s) between named function & anonymous function (Lua) - functional-programming

What is the differences between these myFuncs?
Code 1
function wrapper()
local someVariable = 0;
function myFunc(n)
if n > 0 then return myFunc(n-1) end
end
return myFunc;
end
Code 2
function wrapper()
local someVariable = 0;
local myFunc = function(n)
if n > 0 then return myFunc(n-1) end
end
return myFunc;
end
Code 3
function wrapper()
local someVariable = 0;
local myFunc;
myFunc = function(n)
if n > 0 then return myFunc(n-1) end
end;
return myFunc;
end
Because when I refer the function name myFunc inside the myFunc itself. Their behavior are not the same. (eg. the upvalue someVariable... problematic :-S )

[edit: I misread your code #2.]
Code #1 sets the global value of myFunc to the function. So every time you call wrapper, you will be setting this one global to a new value. Furthermore, any references to your myFunc call will be to this global (which is modifiable), not to a local (which would be an upvalue of the closure).
Code #2 sets a local variable myFunc. However, because of the rules of Lua, that local variable only comes into scope after the statement defining it is complete. This allows you to do things like this:
local x = x or 5
The x in the expression is a previously declared local or global. The new x doesn't come into scope until after the x or 5 expression has been evaluated.
The same goes for your function definition. Therefore any references to myFunc will be to a global variable, not a local.
Code #3 creates a local variable myFunc. Then it sets into that variable a function. Because the function is created after the local variable comes into scope, references to myFunc in the function will refer to the local variable, not to a global one.
Note that local function X is equivalent to local X; X = function.... Not to local X = function....

Nicol's answer is mostly correct, but there is one thing that is worth pointing out:
In Code 2 MyFunc doesn't need to be a global variable, it can be a local variable in some outer scope, which will become an upvalue for this function you are creating (the same comment also applies to Code 1). For example, this will print 100:
local function myFunc(n) return 100 end
function wrapper()
local someVariable = 0;
local myFunc = function(n)
if n > 0 then return myFunc(n-1) end
end
return myFunc;
end
print(wrapper()(1))
So, to summarize, there are four ways you can use to define myFunc:
local myFunc; myFunc = function(n) ... return myFunc(n-1) end
local function myFunc(n) ... return myFunc(n-1) end
local myFunc = function(n) ... return myFunc(n-1) end
myFunc = function(n) ... return myFunc(n-1) end
1 and 2 are full equivalents. 3 will not do what you expect as it will use whatever definition of myFunc is available when local myFunc is executed (which may point to an upvalue for MyFunc or a global variable). 4 will work, but only because it will assign the newly created function to (again) either an upvalue or a global variable (and reference the same value in the body of the function).

Related

Break Function without return

I have a function
function foo(a)
if a > 5
a = 5
end
some_more_code
end
If the if-statement is true I would like to end the function but I don't want to return anything - to change the value of a is all I need.
How do I do that?
You can write (note that I have also changed the syntax of function definition to make it more standard for Julia style):
function foo(a)
if a > 5
a = 5
return
end
# some_more_code
end
Just use the return keyword without any expression following it. To be precise in such cases Julia returns nothing value of type Nothing from a function (which is not printed in REPL and serves to signal that you did not want to return anything from a function).
Note though that the value of a will be only changed locally (within the scope of the function), so that outside of the function it will be unchanged:
julia> function foo(a)
if a > 5
a = 5
return
end
# some_more_code
end
foo (generic function with 1 method)
julia> x = 10
julia> foo(x)
julia> x
10
In order to make the change visible outside of the function you have to make a to be some kind of container. A typical container for such cases is Ref:
julia> function foo2(a)
if a[] > 5
a[] = 5
return
end
# some_more_code
end
foo2 (generic function with 1 method)
julia> x = Ref(10)
Base.RefValue{Int64}(10)
julia> foo2(x)
julia> x[]
5

Why does this happen when a user-defined R function does not return a value?

In the function shown below, there is no return. However, after executing it, I can confirm that the value entered d normally.
There is no return. Any suggestions in this regard will be appreciated.
Code
#installed plotly, dplyr
accumulate_by <- function(dat, var) {
var <- lazyeval::f_eval(var, dat)
lvls <- plotly:::getLevels(var)
dats <- lapply(seq_along(lvls), function(x) {
cbind(dat[var %in% lvls[seq(1, x)], ], frame = lvls[[x]])
})
dplyr::bind_rows(dats)
}
d <- txhousing %>%
filter(year > 2005, city %in% c("Abilene", "Bay Area")) %>%
accumulate_by(~date)
In the function, the last assignment is creating 'dats' which is returned with bind_rows(dats) We don't need an explicit return statement. Suppose, if there are two objects to be returned, we can place it in a list
In some languages like python, for memory efficiency, generators are used which will yield instead of creating the whole output in memory i.e. Consider two functions in python
def get_square(n):
result = []
for x in range(n):
result.append(x**2)
return result
When we run it
get_square(4)
#[0, 1, 4, 9]
The same function can be written as a generator. Instead of returning anything,
def get_square(n):
for x in range(n):
yield(x**2)
Running the function
get_square(4)
#<generator object get_square at 0x0000015240C2F9E8>
By casting with list, we get the same output
list(get_square(4))
#[0, 1, 4, 9]
There is always a return :) You just don't have to be explicit about it.
All R expressions return something. Including control structures and user-defined functions. (Control-structures are just functions, by the way, so you can just remember that everything is a value or a function call, and everything evaluates to a value).
For functions, the return value is the last expression evaluated in the execution of the function. So, for
f <- function(x) 2 + x
when you call f(3) you will invoke the function + with two parameters, 2 and x. These evaluate to 2 and 3, respectively, so `+`(2, 3) evaluates to 5, and that is the result of f(3).
When you call the return function -- and remember, this is a function -- you just leave the control-flow of a function early. So,
f <- function(x) {
if (x < 0) return(0)
x + 2
}
works as follows: When you call f, it will call the if function to figure out what to do in the first statement. The if function will evaluate x < 0 (which means calling the function < with parameters x and 0). If x < 0 is true, if will evaluate return(0). If it is false, it will evaluate its else part (which, because if has a special syntax when it comes to functions, isn't shown, but is NULL). If x < 0 is not true, f will evaluate x + 2 and return that. If x < 0 is true, however, the if function will evaluate return(0). This is a call to the function return, with parameter 0, and that call will terminate the execution of f and make the result 0.
Be careful with return. It is a function so
f <- function(x) {
if (x < 0) return;
x + 2
}
is perfectly valid R code, but it will not return when x < 0. The if call will just evaluate to the function return but not call it.
The return function is also a little special in that it can return from the parent call of control structures. Strictly speaking, return isn't evaluated in the frame of f in the examples above, but from inside the if calls. It just handles this special so it can return from f.
With non-standard evaluation this isn't always the case.
With this function
f <- function(df) {
with(df, if (any(x < 0)) return("foo") else return("bar"))
"baz"
}
you might think that
f(data.frame(x = rnorm(10)))
should return either "foo" or "bar". After all, we return in either case in the if statement. However, the if statement is evaluated inside with and it doesn't work that way. The function will return baz.
For non-local returns like that, you need to use callCC, and then it gets more technical (as if this wasn't technical enough).
If you can, try to avoid return completely and rely on functions returning the last expression they evaluate.
Update
Just to follow up on the comment below about loops. When you call a loop, you will most likely call one of the built-in primitive functions. And, yes, they return NULL. But you can write your own, and they will follow the rule that they return the last expression they evaluate. You can, for example, implement for in terms of while like this:
`for` <- function(itr_var, seq, body) {
itr_var <- as.character(substitute(itr_var))
body <- substitute(body)
e <- parent.frame()
j <- 1
while (j < length(seq)) {
assign(x = itr_var, value = seq[[j]], envir = e)
eval(body, envir = e)
j <- j + 1
}
"foo"
}
This function, will definitely return "foo", so this
for(i in 1:5) { print(i) }
evalutes to "foo". If you want it to return NULL, you have to be explicit about it (or just let the return value be the result of the while loop -- if that is the primitive while it returns NULL).
The point I want to make is that functions return the last expression they evaluate has to do with how the functions are defined, not how you call them. The loops use non-standard evaluation, so the last expression in the loop body you provide them might be the last value they evaluate and might not. For the primitive loops, it is not.
Except for their special syntax, there is nothing magical about loops. They follow the rules all functions follow. With non-standard evaluation it can get a bit tricky to work out from a function call what the last expression they will evaluate might be, because the function body looks like it is what the function evaluates. It is, to a degree, if the function is sensible, but the loop body is not the function body. It is a parameter. If it wasn't for the special syntax, and you had to provide loop bodies as normal parameters, there might be less confusion.

Evaluate expression with local variables

I'm writing a genetic program in order to test the fitness of randomly generated expressions. Shown here is the function to generate the expression as well a the main function. DIV and GT are defined elsewhere in the code:
function create_single_full_tree(depth, fs, ts)
"""
Creates a single AST with full depth
Inputs
depth Current depth of tree. Initially called from main() with max depth
fs Function Set - Array of allowed functions
ts Terminal Set - Array of allowed terminal values
Output
Full AST of typeof()==Expr
"""
# If we are at the bottom
if depth == 1
# End of tree, return function with two terminal nodes
return Expr(:call, fs[rand(1:length(fs))], ts[rand(1:length(ts))], ts[rand(1:length(ts))])
else
# Not end of expression, recurively go back through and create functions for each new node
return Expr(:call, fs[rand(1:length(fs))], create_single_full_tree(depth-1, fs, ts), create_single_full_tree(depth-1, fs, ts))
end
end
function main()
"""
Main function
"""
# Define functional and terminal sets
fs = [:+, :-, :DIV, :GT]
ts = [:x, :v, -1]
# Create the tree
ast = create_single_full_tree(4, fs, ts)
#println(typeof(ast))
#println(ast)
#println(dump(ast))
x = 1
v = 1
eval(ast) # Error out unless x and v are globals
end
main()
I am generating a random expression based on certain allowed functions and variables. As seen in the code, the expression can only have symbols x and v, as well as the value -1. I will need to test the expression with a variety of x and v values; here I am just using x=1 and v=1 to test the code.
The expression is being returned correctly, however, eval() can only be used with global variables, so it will error out when run unless I declare x and v to be global (ERROR: LoadError: UndefVarError: x not defined). I would like to avoid globals if possible. Is there a better way to generate and evaluate these generated expressions with locally defined variables?
Here is an example for generating an (anonymous) function. The result of eval can be called as a function and your variable can be passed as parameters:
myfun = eval(Expr(:->,:x, Expr(:block, Expr(:call,:*,3,:x) )))
myfun(14)
# returns 42
The dump function is very useful to inspect the expression that the parsers has created. For two input arguments you would use a tuple for example as args[1]:
julia> dump(parse("(x,y) -> 3x + y"))
Expr
head: Symbol ->
args: Array{Any}((2,))
1: Expr
head: Symbol tuple
args: Array{Any}((2,))
1: Symbol x
2: Symbol y
typ: Any
2: Expr
[...]
Does this help?
In the Metaprogramming part of the Julia documentation, there is a sentence under the eval() and effects section which says
Every module has its own eval() function that evaluates expressions in its global scope.
Similarly, the REPL help ?eval will give you, on Julia 0.6.2, the following help:
Evaluate an expression in the given module and return the result. Every Module (except those defined with baremodule) has its own 1-argument definition of eval, which evaluates expressions in that module.
I assume, you are working in the Main module in your example. That's why you need to have the globals defined there. For your problem, you can use macros and interpolate the values of x and y directly inside the macro.
A minimal working example would be:
macro eval_line(a, b, x)
isa(a, Real) || (warn("$a is not a real number."); return :(throw(DomainError())))
isa(b, Real) || (warn("$b is not a real number."); return :(throw(DomainError())))
return :($a * $x + $b) # interpolate the variables
end
Here, #eval_line macro does the following:
Main> #macroexpand #eval_line(5, 6, 2)
:(5 * 2 + 6)
As you can see, the values of macro's arguments are interpolated inside the macro and the expression is given to the user accordingly. When the user does not behave,
Main> #macroexpand #eval_line([1,2,3], 7, 8)
WARNING: [1, 2, 3] is not a real number.
:((Main.throw)((Main.DomainError)()))
a user-friendly warning message is provided to the user at parse-time, and a DomainError is thrown at run-time.
Of course, you can do these things within your functions, again by interpolating the variables --- you do not need to use macros. However, what you would like to achieve in the end is to combine eval with the output of a function that returns Expr. This is what the macro functionality is for. Finally, you would simply call your macros with an # sign preceding the macro name:
Main> #eval_line(5, 6, 2)
16
Main> #eval_line([1,2,3], 7, 8)
WARNING: [1, 2, 3] is not a real number.
ERROR: DomainError:
Stacktrace:
[1] eval(::Module, ::Any) at ./boot.jl:235
EDIT 1. You can take this one step further, and create functions accordingly:
macro define_lines(linedefs)
for (name, a, b) in eval(linedefs)
ex = quote
function $(Symbol(name))(x) # interpolate name
return $a * x + $b # interpolate a and b here
end
end
eval(ex) # evaluate the function definition expression in the module
end
end
Then, you can call this macro to create different line definitions in the form of functions to be called later on:
#define_lines([
("identity_line", 1, 0);
("null_line", 0, 0);
("unit_shift", 0, 1)
])
identity_line(5) # returns 5
null_line(5) # returns 0
unit_shift(5) # returns 1
EDIT 2. You can, I guess, achieve what you would like to achieve by using a macro similar to that below:
macro random_oper(depth, fs, ts)
operations = eval(fs)
oper = operations[rand(1:length(operations))]
terminals = eval(ts)
ts = terminals[rand(1:length(terminals), 2)]
ex = :($oper($ts...))
for d in 2:depth
oper = operations[rand(1:length(operations))]
t = terminals[rand(1:length(terminals))]
ex = :($oper($ex, $t))
end
return ex
end
which will give the following, for instance:
Main> #macroexpand #random_oper(1, [+, -, /], [1,2,3])
:((-)([3, 3]...))
Main> #macroexpand #random_oper(2, [+, -, /], [1,2,3])
:((+)((-)([2, 3]...), 3))
Thanks Arda for the thorough response! This helped, but part of me thinks there may be a better way to do this as it seems too roundabout. Since I am writing a genetic program, I will need to create 500 of these ASTs, all with random functions and terminals from a set of allowed functions and terminals (fs and ts in the code). I will also need to test each function with 20 different values of x and v.
In order to accomplish this with the information you have given, I have come up with the following macro:
macro create_function(defs)
for name in eval(defs)
ex = quote
function $(Symbol(name))(x,v)
fs = [:+, :-, :DIV, :GT]
ts = [x,v,-1]
return create_single_full_tree(4, fs, ts)
end
end
eval(ex)
end
end
I can then supply a list of 500 random function names in my main() function, such as ["func1, func2, func3,.....". Which I can eval with any x and v values in my main function. This has solved my issue, however, this seems to be a very roundabout way of doing this, and may make it difficult to evolve each AST with each iteration.

R get the environment created by a function at the call

I would like to get the environment created by a function when it is runned WITHOUT modifying the function source (ie from outside of the function), is it possible ?
fn=function()
{#Here a new environment is created at each call, how to get it ?
#This environment can be access with environment() but only (to what I know)
#from inside the function
...
}
I would like something like this:
env=some_function(fn())
where env is the environment id created by fn at the call.
You could trace the function to bind the call environment to a symbol in the global environment:
fn <- function() {x <- 2; 1}
trace(fn, quote(efn <<- environment()), at = 1)
fn()
#Tracing fn() step 1
#[1] 1
untrace(fn)
efn$x
#[1] 2

function variable does not live outside a for loop

I have a generic function in julia that the aim is to say if a member of a vector of
a given dimension is negative or not. After a few variations I have:
function any(vec)
dim = size(vec)
for i in 1:dim[2]
fflag = vec[1,i] < 0
println("Inside any, fflag = ", fflag)
if fflag == true
result = 0
println("blabla ", result)
break
else
result =1
println("blabla ", result)
continue
end
end
println("hey, what is result? ")
println(result)
return result
end
If I run a test I found the following result:
Inside any, fflag = false
blabla 1
Inside any, fflag = false
blabla 1
Inside any, fflag = false
blabla 1
hey, what is result?
result not defined
at In[7]:57
I don't know why the compiler says me that 'result' is not defined. I know the variable exist but why does not live outside the for loop?
The documentation on variable scoping clearly states that a for loop defines a new scope. This means result is going out of scope when execution leaves the for loop. Hence it is undefined when you call println(result)
Defining result in advance of the for loop should give the behaviour you are expecting:
function any(vec)
dim = size(vec)
result = -1
for i in 1:dim[2]
...
Or if you do not wish to assign a default value, and are sure the for loop will set its value, you can do:
function any(vec)
dim = size(vec)
local result
for i in 1:dim[2]
...
In the first example, if the for loop does not set a value, result will be -1.
In the the second example, not setting a value in the for loop will leave result undefined.

Resources