I am trying to understand a relatively simple piece of code, but I am not quite able to reason what is happening (I am a Julia newbie coming from Python/Matlab background).
function myfunc(number::Integer)
double() = 2*number
square() = number^2
return _ -> (number, double, square)
end
I understand myfunc
is returning an anonymous function that does not care for the value passed to it. So these cases make sense to me:
julia> n4 = myfunc(4)
#9 (generic function with 1 method)
julia> n4(50)
(4, var"#double#10"{Int64}(4), var"#square#11"{Int64}(4))
In the first line n4
refers to the anonymous function itself, whereas in the second the anonymous function is called with parameter 50
and does what it is supposed to: discards 50 and returns the tuple containing data it was defined with.
What I don't understand is how I am able to do:
julia> n4.square
(::var"#square#11"{Int64}) (generic function with 1 method)
julia> n4.square()
16
The fact that n4
which refers to an anonymous function has child objects n4.number
, n4.double
, n4.square
is a surprise to me. How is n4
behaving as if it were a struct? Doing n4(*)[2]()
to get back 8 as answer makes sense but when fieldnames(n4)
fails something is happening behind the scenes that I don't understand to make n4.double()
work. Where/what is the mechanism by which I am able to use .
after n4
to get at the functions/data?
'return' keyword in Julia is used to return the last computed value to the caller function. This keyword will cause the enclosing function to exit once the value is returned. return keyword will make the function to exit immediately and the expressions after the return statement will not be executed.
A return type can be specified in the function declaration using the :: operator. This converts the return value to the specified type. This function will always return an Int8 regardless of the types of x and y .
No, you cannot return a value from an asynchronous callback. Event callback will be called on click, but you can't assign its result.
an exclamation mark is a prefix operator for logical negation ("not") a! function names that end with an exclamation mark modify one or more of their arguments by convention. # the number sign (or hash or pound) character begins single line comments.
In Julia, all generic functions (that is, all regular Julia-defined functions) are structs. Any struct can be made callable in Julia, so by default, a normal function is just a zero-field struct (a singleton) made callable. In other words, doing
foo(x) = x+1
is similar to
struct Foo end
const foo = Foo()
(::Foo)(x) = x + 1
This works great for normal functions, but for anonymous functions, this can cause the creation of a large number of new types. For example, you could do:
functions = [x -> x+i for i in 1:1000]
.
Instead of creating 1000 new types, each with a new value of i
, Julia here creates a single type containing i
as a field, and 1000 instances.
In your case, instead of myfunc
returning a new type for every invokation and returning the singleton instance of that type, it returns an instance of a type with the fields number
, double
and square
.
Also, you can totally call fieldnames, you just have to call it on a type: fieldnames(typeof(myfunc(4)))
.
It's just an optimization, and it feels a little strange that you have code relying on the internals of how functions are represented in memory. You probably shouldn't do that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With