Can a function return another function?

Hello everyone! Can a function return another function?

julia> foo(x) = y -> y*x
foo (generic function with 1 method)

julia> f = foo(4)
#4 (generic function with 1 method)

julia> f(3)
12
3 Likes

Yes, of course:

julia> function sincos(x)
          sin(x)*cos(x)
       end
sincos (generic function with 1 method)

julia> sincos(1)
0.4546487134128409

1 Like

Looks to me like that is just a regular function which returns a numeric value.

But functions which return functions are no problem at all. Here is an example from Base:

julia> f = startswith("fun")
(::Base.Fix2{typeof(startswith), String}) (generic function with 1 method)

julia> f("function")
true

julia> f isa Function
true
1 Like

As others have already answered: yes. As I understand it: coming from a LISP/Scheme tradition of languages you can do quite a bit more with Julia. So what are you looking for, exactly?

1 Like

Reading all the answers helped a lot. I don’t know if I’m doing it the best way. Simplifying the code a bit, now it works:

using QuadGK

function func1(f:: Function, T)
	integral = quadgk(f, 0, T)[1]
	normalized(x) = f(x)/integral # normalize
	normalized
end

function test()
	g(x) = x^2 + x + 1
	gn = func1(g, 2.0)
	println( gn(2.0) )
end

test()
3 Likes

To be more specific, I need to create a new function, inside a function and return this created function to be used in the main scope. I am not sure if I am doing this safely.

function create_new_func(f1::Function, T)
# new function to return: f1n(t)
	if T < 10
		f1n(t) = f1(t) + 1
	else
		f1n(t) = f1(t) + 2
	end
	f1n
end

function test(x)
	f(x) = 2x
	g = create_new_func(f, x)
	println(g(2)) # 5
end

test(1) # WARNING: Method definition 
# test(11) # ERROR: LoadError: UndefVarError: f1n not defined 
1 Like

For this you need anonymous functions

So, do

if T < 10
	f1n = t -> f1(t) + 1
else
	f1n = t -> f1(t) + 2
end 
2 Likes

To be clear, this is a bug:
https://github.com/JuliaLang/julia/issues/15602
Using anonymous function is a work around it.

3 Likes

Elrod answered similarly, but I hadn’t understood. The function I posted was a simple example of the structure I needed. Now it worked in my code. Thanks again DNF, thanks everyone.

1 Like

Wow, this sounds like a new entry in the wat-thread, especially considering the date this bug was opened… (I always assumed these forms to be synonymous)

Edit: although I assume there are some pretty difficult technicalities to solve this…

Edit: Ah, I remember, this is a difference between f = x -> x and const f = x -> x

That issue with conditional multimethods is one example of how Julia is not as dynamic as other dynamic languages (another example is how we can’t simply redefine a struct). If the method table of a function was allowed to be conditional, it prevents a lot of optimization. On the other hand, if you fix the method table but allow variation of captured variables, you pretty much reuse the same underlying function that takes those captured variables as arguments, like a functor. So the compiler assumes that right now and builds the method table from every nested method, disregarding the conditions.

This just returns a numerical value, not a function. Maybe you meant

function sincos()
    x -> sin(x)*cos(x)
end
sincos (generic function with 1 method)

julia> sincos()(1)
0.4546487134128409

?

function sin_cos(ch::Bool)
  if ch
    return sin
  else
    return cos
  end
end