Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia function returning anonymous function

Tags:

julia

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?

like image 619
ITA Avatar asked May 26 '20 08:05

ITA


People also ask

How do you return a function in Julia?

'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.

What is :: In Julia?

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 .

Can anonymous function return Javascript?

No, you cannot return a value from an asynchronous callback. Event callback will be called on click, but you can't assign its result.

What is Julia exclamation mark?

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.


Video Answer


1 Answers

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.

like image 188
Jakob Nissen Avatar answered Nov 10 '22 20:11

Jakob Nissen