-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
WIP: Staged functions #7474
WIP: Staged functions #7474
Conversation
I don't think we should use |
@@ -690,7 +697,7 @@ function abstract_call_gf(f, fargs, argtypes, e) | |||
end | |||
end | |||
for (m::Tuple) in x | |||
linfo = m[3].func.code | |||
linfo = func_for_method(m[3],argtypes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the right approach. It means _methods
does not return anything useful unless you know how to fix up its result. We can change what _methods
returns instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree. Any thoughts on what _methods
should return? Just the lambda info rather than the method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though if we change it to not return the method, then _methods
as a name doesn't really make a whole lot of sense any more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JeffBezanson thoughts on what it should return. Just replace m[3]
by the actual lambda info? I can see one instance in which m.sig is being accesses but in all other instances it's just picking out the lambda info.
Hmm, that is odd behavior. It seems to suggest that the specifically-compiled variants are not getting inserted into the methods table properly. What does |
Also, am I right in guessing that more needs to be done to handle splatted arguments? |
A rule of thumb is that the system should behave as if the code generator did not exist, and all of its possible outputs have been written manually in a magic infinite source file. |
I'm not sure about splatted arguments. Haven't tried. About the method cache, I think it is being entered correctly (see the second call to foo). The problem is probably inlining. @JeffBezanson That analogy doesn't really work though, unless you want to add the generated methods to mt->defs and even then they would only be there after being called. |
The rule of thumb should be followed to the extent possible. It's there to resolve design decisions that could go either way. |
Looks like we're super-close, but that splatting seems to be a problem. Check this out (we are so close to having awesome array views!):
Ideally the compiled function should have a signature like this:
but I think it's just the naming that's causing problems. |
💯 just wanted to register my excitement and say it was very cool to see the initial prototype work on Saturday :) |
also is this going to make it into 0.3 or will it be an 0.4-pre thing? |
Definitely not 0.3 material. |
While this can legitimately be called a staged function, I feel that the concept of staged functions is much more broad then how they are being applied here. Calling this a stage function would be presumptuous since there could be other functions that fit the definition of what a staged function is. Since this is a function/macro that operates on types why not have the syntax be
or
|
|
|
I fail to see how it's presumptuous to apply a term to something that fits its definition. What would it mean for another design or implementation to be "more staged" than this? This can't have different syntax; the whole point is that it's part of the behavior of a generic function. Some methods might be staged, others not, transparently. |
I would also be ok with a more concrete, less-jargony name possibly evoking "code generator". or "generated method", or something along those lines. |
Ah, I didn't catch that these will mesh with generic functions. Very cool. |
@JeffBezanson The presumptuous bit is to allocate a piece of syntax for something that describes a family of functions. I would be a bit like a language defining I think the syntax
would be fine since in your initial mailing list post you say
This may however cause confusion with people trying to call them like macros.(which is why I also suggested |
I hope we can find a better name. |
Also something to consider would be something like type annotations but for functions. Like
something that describes what aspects of the arguments are passed into the function e.g. in a normal function their values are passed but in a |
Both
and
already have a meaning. |
@Keno then perhaps something like
I kinda like this idea. Instead of Anyway I've said my piece. I realize this is a bike shed issue so I am going to shut up about it now and let you experts take care of it. |
|
|
|
jinx @porterjamesj |
What about |
@yurivish +1 |
@mlubin, since they generate expressions, they are seem more like macros than functions, and hence I like |
If we're using white space anyway, seems reasonable to just use a macro – I also quite liked |
Oh, forgot about python generators :) (which I indeed hope that we will have at some point) |
+1 for |
Generated types can be implemented right now using the tricks used in #8432. Not perfect, but still very convenient until we have the full thing. In fact, it shouldn't be to hard to implement a general scheme for this using a macro, which could then be called With respect to name: I would also prefer |
Although |
I agree with the argument that it should be |
I like |
Indeed. I agree 100%. +1 for |
+1 for @generated. No whitespace in keywords is nice too. Visually, the macro syntax it also alerts you that something will run at an earlier stage. |
If we make this look like a macro, what will |
I agree with John. The |
How about using an empty curly? function f{}( ... )
end No new reserved word. No need to change editor model. The empty curly suggests that, Instead of parametrizing the function outside, we do that inside... Edit: ok, |
@johnmyleswhite The idea isn't to pretend it's a macro, but for it to actually be a macro. We have |
To follow up on @one-more-minute's point, see http://docs.julialang.org/en/latest/devdocs/meta/ |
I think the crucial point is that it's the definition of a generated function that involves a macro rather than the callsite—end users don't have to care. +1 for |
Hornéd hat of shame for the lack of documentation on this.... |
As I believe you noted elsewhere, it's hard to write documentation for something whose very name is likely to change. |
It seems like the consensus that was reached was for calling them generated (functions|types|...) using the |
I agree, but until the syntax change happens it seems very strange to document it (with either name choice). |
Why not document it with the current name, and then just update the documentation with the name change? I think a lot of people want to use staged functions and learn about them (on master), but going through the issues is a bit cumbersome for many. |
I realise this is more work, and I am in no position to help, but I (and I'm sure many others) would really appreciate something on those lines. Maybe even a gist with some docs and examples? |
I also confess some reluctance before #8504 gets fixed---it's a nasty problem, and it's holding even me back from using stagedfunctions more pervasively. But, let's go for it and see what happens. If nothing else it might be more incentive to at least get some discussion about my proposed fix. |
I wonder if we should treat function-typed argument differently in a stagedfunction. When testing types, we most likely want to do That said, it should be illegal to actually call the function-value argument at the staging phase. |
It's an interesting idea. Can you expand on your goal, why checking the signature during staging is better than just trying it and seeing what error you get? But one point is that in principle your suggestion could provide a mechanism for "function-valued argument inlining" (#3440 and perhaps #1864). |
I'm playing with the idea of Functors and Monads using Traits.jl and notice the ideas are not trivial. (PR# mauro3/Traits.jl#4 (comment)). I was trying to see if I can generate associated types with the package. Let's take Functor. A Functor must support a fmap function. In Haskell it imposes that using Traits
immutable FuncFullSig{TI, TO}
f::Function
end
@traitdef Functor{X{Y}} begin
fmap( FuncFullSig{Y,Z}, X{Y} ) -> X{Z}
end So when we do a = Float64[1.0,2.0] # assume we assert Array is a Functor
b = fmap( FuncFullSig{Float64,Float64}( sin ), a ) # b should be provably Array{Float64} It would do away with many boilerplate codes, as many types are just Functors in disguise (Nullable, Associative{K}, DataArray, etc.) . But writing
Ideally, all these would be better done only once per (Function, ArgTypes...) tuple, or the performance penalty would be massive. Stagedfunction would be an interesting place to put it, but |
This is my work in progress for staged functions (#7311). It almost works, but there's a few things left to discuss.
stagedfunction foo(); end
. @JeffBezanson proposedstaged foo(); end
, though there's the question if we want to reserve that keywordHopefully calling the staged function that many times can be avoided. In any case, this point isn't critical.
Thanks to @timholy and @jakebolewski for hacking on this with me on Saturday.