Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't @gg user-defined functions #24

Closed
cscherrer opened this issue Oct 5, 2019 · 4 comments
Closed

Can't @gg user-defined functions #24

cscherrer opened this issue Oct 5, 2019 · 4 comments

Comments

@cscherrer
Copy link
Collaborator

Hi @thautwarm, I had mentioned this issue is the Soss issues, but I think I wasn't very specific about it.

Everything works great for models like this:

julia> m1 = @model begin
           x ~ Normal()
       end;

julia> rand(m1())
(x = -0.11329202445030989,)

Calling rand in this case passes the following to @gg:

julia> sourceRand()(m1)
quote
    x = rand(Normal())
    (x = x,)
end

I think it will be reasonably common for users to want to define their own distributions, and I'd hate for this always to require a PR to Distributions or Soss. So maybe they have a simple case like this:

julia> struct N end

julia> Distributions.rand(::N) = rand(Normal())

julia> rand(N())
0.02887276952144644

So far so good. But when they try to use it in a model, ...

julia> m2 = @model begin
           x ~ N()
       end;

julia> rand(m2())
ERROR: UndefVarError: N not defined
Stacktrace:
 [1] getproperty at ./Base.jl:13 [inlined]
 [2] macro expansion at /home/chad/.julia/packages/GeneralizedGenerated/x3uMp/src/closure_conv.jl:155 [inlined]
 [3] _rand(::Model{NamedTuple{(),T} where T<:Tuple,begin
    x ~ N()
end}, ::NamedTuple{(),Tuple{}}) at /home/chad/.julia/packages/GeneralizedGenerated/x3uMp/src/closure_conv.jl:155
 [4] rand(::Soss.JointDistribution{NamedTuple{(),Tuple{}},NamedTuple{(),T} where T<:Tuple,begin
    x ~ N()
end}) at /home/chad/git/jl/Soss/src/rand.jl:8
 [5] top-level scope at REPL[68]:1

I think this is because the source code is like this:

julia> sourceRand()(m2)
quote
    x = rand(N())
    (x = x,)
end

The generated function docs say users should not attempt...

Calling any function that is defined after the body of the generated function. This condition is relaxed for incrementally-loaded precompiled modules to allow calling any function in the module.

So my guess is this might be the root of the problem.

Some possibilities I can imagine (which might not all help or be feasible):

  1. Require everything user-defined to be passed as an argument. This currently works, but is kind of unwieldy.
  2. Allow $ interpolation. I think this could work, but it does leave the Soss-provided distributions feeling kind of magic, so anything a user builds is second-class.
  3. I had thought there could be a trick with the evaluation order, like defining N before using Soss. This doesn't help, but could there be some variant of this that will work?
  4. Ideally (though I have no idea if it's possible or how much work would be involved) it would be pretty great for @gg (or some variant of it) to allow anything in scope at call-time to be referenced.

Any ideas?

@thautwarm
Copy link
Member

Hi Chad, the problem has been detected.

The use of @gg in Soss is in Soss module, while the definition of N is in the Main module, thus
the reference of N failed in your case.

@thautwarm
Copy link
Member

I'll make a PR to refine the use of @gg in Soss. In fact, we should store the current module when invoking @model.

@thautwarm
Copy link
Member

It seems to be really difficult now to support the expected feature without using $.

Once the generalized functions get defined, its global scope is decided as well, thus, according to Soss/rand.jl, the module to look up global variables is specified to be Soss.

However, the best way IMHO to achieve the expected behaviour is,

  • Soss.jl side: adding an extra field to Soss.Model to store the model's definition module.
  • GG.jl side: introducing a new @gg macro to support passing in the module to look up global variables: @gg @__MODULE__ f(x) = N(x) # now N is from @__MODULE__

@cscherrer
Copy link
Collaborator Author

Fixed in #28

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants