3

Is it possible to access function defined in another function in julia? For example:

julia> function f(x)
         function g(x)
           x^2
         end
         x * g(x)
       end

f (generic function with 1 method)

julia> f(2)
8

julia> f.g(2)
ERROR: type #f has no field g
 in eval_user_input(::Any, ::Base.REPL.REPLBackend) at ./REPL.jl:64
 in macro expansion at ./REPL.jl:95 [inlined]
 in (::Base.REPL.##3#4{Base.REPL.REPLBackend})() at ./event.jl:68
Phuoc
  • 1,073
  • 8
  • 20
  • 6
    Not unless you return it or have a pointer to it defined in the scope of where you want to use it. – Colin Schoen Apr 07 '17 at 00:00
  • You can *return* a function that is defined inside another function. Is that what you're looking for? For example, return the anonymous function x->x * g(x) in your example. – David P. Sanders Apr 07 '17 at 12:06

2 Answers2

5

No. In julia, it is often more ideomatic to use a module for local functions

module F
function g(x)
    x^2
end

function f(x)
    x * g(x)
end

export f
end

using F

f(2)
F.g(2)

What's the use case? You can define a custom type, give it a function field, and then make the type callable (a closure) to achieve the behaviour you want. But whether that is the best way of solving your issue in julia is a different question.

Michael K. Borregaard
  • 7,864
  • 1
  • 28
  • 35
  • 1
    Rather than saying " But whether that is the best way of solving your issue in julia is a different question." you might just say "But this is probably not the best way to solve your problem." I think being un-ambigious here is worth wild, because it is a moderately common newcomer mistake to think they can implement OO in julia like this. (and they are not wrong, as such. But you know how unidiomatic such code would be, I am sure.) – Frames Catherine White Apr 07 '17 at 12:39
  • 2
    @LyndonWhite , just for the laughs, though, check out this post and the response from Jeff B: http://stackoverflow.com/questions/39133424/how-to-create-a-single-dispatch-object-oriented-class-in-julia-that-behaves-l – Michael K. Borregaard Apr 07 '17 at 14:30
  • 1
    A yes, great question that! Excellent even. The guy who wrote it must be really amazing. :ppp – Tasos Papastylianou Apr 07 '17 at 19:24
  • Muarhaha, absolutely :-) – Michael K. Borregaard Apr 07 '17 at 19:41
  • Sorry, I just realised that my answer below is essentially what you suggested below your code snippet (except for the closure part, I think you got that the other way round) – Tasos Papastylianou Apr 07 '17 at 20:12
  • Not sure what you mean, I did mean exactly what you suggested below :-) – Michael K. Borregaard Apr 08 '17 at 10:27
  • 1
    @MichaelK.Borregaard Yes, sorry, I realised that after I wrote it; the closure bit threw me off the first time when reading in a hurry, so I didn't realise that's what you meant; I thought you were suggesting using a closure, which seemed a bit overkill to me. Happy for you to merge my answer into yours if you like. What I meant by my "other way round" comment is that the way you wrote this implies callable types are (implemented as) closures. I believe it's actually the other way round: closures in julia are implemented internally via callable types. But not all callable types are closures. – Tasos Papastylianou Apr 08 '17 at 22:57
  • Ahh, cool, I think I am the one who is not completely sharp on the terminology. I used closure simply to mean callable type and didn't appreciate the distinction. – Michael K. Borregaard Apr 09 '17 at 11:32
1

You can do this if your function f is an instance of a callable type, containing a function g as an accessible field:

julia> type F
         g::Function
       end

julia> function(p::F)(x)      # make type F a callable type
         x * p.g(x)
       end

julia> f = F(function (x) return x.^2 end)    # initialise with a function
F(#1)

julia> f(2)
8

julia> f.g
(::#1) (generic function with 1 method)

If g is always a fixed function, then you can introduce it via an internal constructor.

But to echo Lyndon's comments above, a better question is, why would you do this instead of something relying more on julia's dynamic dispatch features?

Tasos Papastylianou
  • 21,371
  • 2
  • 28
  • 57