Hello. I just tested the following small code on Julia, and found that the value g() is changed after redefining the function f, but c is unchanged. I was wondering the reason behind this difference, and how to keep g() unchanged as well. Thanks.
I think it’s just because c refers to the value 2, which was computed by evaluating the expression (as it was defined at that time) f(1), while g is looking up whatever the current definition of f is when you call it, and then executing.
c does not change because it took the value of f(1) before you changed the meaning of function f. g does change, because it calls function f. This allows you to have all sorts of functions and not having to worry to recompile all functions that use your changed f down the line, just recompile f.
I think so. But why c took the value of f at the time it was defined while g needed to look up the definition of f? c and g() were defined in the same way. Any mechanism behind it?
Functions run code. Assignments simply give names to values.
While f() = x and f = x look similar, they are wildly different things. The former defines a function that can be run later, whereas the latter gives another name to whatever value x is at that point.
If you want your function be be more flexible, instead of redifining it every time, you could define it as follows:
f(x,y) = x + y
g(x) = f(3,x+2)
# example, note the x is local to the function,
# so the y in f becomes the value of x+2
julia> c = f(1,1) # c=2
julia> c = f(1,2) # c=3
julia> c = g(2) # c=7
although I would not bother if the function is not more than one + etc. operator.
There is really not much to say about that. A function runs its content when it is called, not when it’s defined. Take e.g. the definition:
function myprint(x)
print("DEBUG: ")
println(x)
end
The whole point with functions is that the text DEBUG: and the textual representation of the value of x is printed whenever you exectute a myprint(whatever) in your program. Not when the function myprint is defined.
The manual is a bit vague on which scope the default values are evaluated in. With a bit of good will it can be surmised that the scope consists of the previous arguments and the scope where the function was defined.
It wouldn’t really make sense to use the caller’s scope. The writer of the function would lose all control, and the caller could inadvertently change the defaults by defining a variable which happens to be used in the defaults.
julia> function f(; x = x/2, y = x)
@show x y
end
f (generic function with 1 method)
julia> f();
ERROR: UndefVarError: `x` not defined in `Main`
julia> x = 1;
julia> f();
x = 0.5
y = 0.5
julia> f(x=2);
x = 2
y = 2
I’m very confused about what is confusing here. Keyword defaults and positional defaults work exactly the same way. Default expressions, like everything else about a function definition, are evaluated in the scope where the function is defined.
I think the confusion is about why g()=f(1) do not store the definition of f at the time of evaluation, just like c=f(1) does. g() is affected by redefining f, c does not.