Naive suggestion: since you can eval inside the macro body (à la FastAnonymous), couldn't your generated function expand into a macro call?
On Friday, August 12, 2016 at 12:19:49 PM UTC-4, Erik Schnetter wrote: > > On Fri, Aug 12, 2016 at 4:06 AM, Tomas Lycken <tomas....@gmail.com > <javascript:>> wrote: > >> Julia’s parametric types are not generic enough to support this. >> >> In my experience, any time I’ve been inclined to reason like this about >> one of my use cases, someone (usually Tim Holy :P) has been able to show me >> a way that works just fine, without magic, by just using the type system in >> a smarter way than I was able to figure out myself. So, if you’ll forgive >> my delusions of grandeur, I’ll attempt to suggest a way to support the >> cases you’ve mentioned so far! >> >> The code turned out to be quite lengthy, so I put it in a gist instead: >> https://gist.github.com/tlycken/e501e1079d947d699b71941d93b7113e >> > That's similar to the approach I'm currently trying. The added difficulty > is that I don't know ahead of time how many fields I need in the immutable > type, hence I'm passing a single type parameter that is a tuple. > > Also, I really want the type generating function to be type-stable. If I > relax this restriction, then I can keep my current code, use a regular (not > generated) function, and call `eval` there to create the type I needed > (properly memoized of course). However, this makes code that first declares > a variable and then uses it quite inefficient; one will always have to put > the variable declaration and its use into separate functions, declaring > variables "further outside", so that Julia's method call selection can > allow type inference to kick in. > > -erik > > >> Basically, what I’ve done is to create a generic type that holds all the >> information you need ((lower bound, stride, end) for each dimension) in >> its type arguments, and then a generator function that lets you specify >> these the same way you do today - with symbols as placeholders to be filled >> in when instantiated. >> >> The generator function won’t be type stable, because the return type will >> depend on values of keyword arguments, but that shouldn’t be a big problem >> since it’s just upon array initialization; I suspect you will do the actual >> work in some kernel function, which then has access to the full type >> information. >> >> // T >> >> On Friday, August 12, 2016 at 7:38:07 AM UTC+2, Andy Ferris wrote: >> >> > I'm encountering the error "eval cannot be used in a generated >>> function" in Julia 0.5 for code that is working in Julia 0.4. >>> >>> I feel your pain, Erik! >>> >>> > AFAICT, it remains possible to do dynamic type generation if you (1) >>> print the code that would define the type to a file, and (2) `include` the >>> file. >>> >>> While this is true, is your example meant to be a generated function? If >>> I need to recreate an existing type by calling `create_type_dynamically` >>> again with the same parameters, it won't be free at run-time. Unless we can >>> get it to recompile, and `isdefined()` is `@pure` or (evaluated by >>> inference)... hmm... >>> >>> > The definition of a generated function is "a pure function which >>> computes a function body based solely upon properties of the input argument >>> types". Since `eval` isn't pure, that would violate the definition of what >>> `@generated` is, and therefore it isn't usable. This isn't supposed to be >>> complicated, what an `@generated` function is actually supposed to be >>> allowed to do is just extremely limited, to make sure the system doesn't >>> fall apart on edge cases. >>> >>> Jameson - I suppose most of us think not of Julia as like the C or C++ >>> language standards, but as an implementation. A beautifully hackable >>> implementation, at that! I would assert that the definition of a generated >>> function is written in C++, lisp, Julia, etc. So it seemed to us users that >>> what "pure" meant was in this context was whatever we observed to work: >>> that it should always produce the same output code, and it seemed obvious >>> that the generator itself runs one or more times before the function is >>> called. Side effects that don't cause the compiler to get confused? Well, >>> why not? We can `println` in the generator, and that is rather useful for >>> debugging. In the past months several people have independently come up >>> with the same incredibly useful trick/hack, and there is now a bit of >>> sadness felt that our clever/insane code has died! >>> >>> I'm not saying this is terribly bad. Fixing #265 would be wonderful, and >>> we shouldn't get in the way of that. But Julia has always appeared to be >>> driven by community desires, and I feel these generated types are pretty >>> nifty. Constructive thoughts on any way forward would be greatly >>> appreciated. As would an actual example of this not working as expected in >>> the current implementation of Julia (though I think you may have provided >>> this for planned work on #265??). >>> >> >> > > > > -- > Erik Schnetter <schn...@gmail.com <javascript:>> > http://www.perimeterinstitute.ca/personal/eschnetter/ >