Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-13 Thread Cedric St-Jean
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  > 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 

Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-12 Thread Erik Schnetter
On Fri, Aug 12, 2016 at 4:06 AM, Tomas Lycken 
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 
http://www.perimeterinstitute.ca/personal/eschnetter/


Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-12 Thread Erik Schnetter
In what sense does a generated function need to be pure? I was not aware of
this. Does this mean that (1) the generating function needs to be pure (and
return only a quoted expression, not modifying any state), or that (2) the
quoted expression needs to be pure?

The documentation of generated might need to be updated. Purity is
currently not mentioned there; indeed, the example there contains a
`println`. The documentation also argues that side effects are bad since
the generating function might be evaluated multiple times. I understand
this to imply that idempotent side effects are fine.

-erik


On Fri, Aug 12, 2016 at 1:38 AM, 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 
http://www.perimeterinstitute.ca/personal/eschnetter/


Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-12 Thread Tomas Lycken


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

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??).
>
​


Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-11 Thread Andy Ferris
> 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??).


Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-11 Thread Erik Schnetter
On Thu, Aug 11, 2016 at 3:08 AM, Tomas Lycken 
wrote:

> Late to the party, but what’s wrong with writing FastArray{1,10,1,10} (or
> even FastArray{10,10} if you’re OK with implicit 1-based indexing)? It
> seems that those (valid) type arguments could convey just as much
> information as FastArray(1:10, 1:10), and you could then handle any
> special-casing on the size in the constructor. That way you’d only need one
> (generic) type. Or am I missing something important here?
>
The package supports many other cases as well. Both lower or upper index
can be either fixed in the type, or left flexible; depending on this, the
optimal way to access array elements is determined. Also, the number of
dimensions can change, so that there is `FastArray(1:10)` as well as
`FastArray(1:10,1:10,1:10,1:10)`. Julia's parametric types are not generic
enough to support this.

One example might be a `(3,n)` array, where the first dimension is known to
have size `3`, and the second can be arbitrary. You write `typealias
array3n FastArray(3,:)`, and later create arrays of this type e.g. via
`array3n{Float64}(:,100)`. At run time, this leads to better (faster) code
when accessing array elements in my use case.

-erik


> // T
>
> On Thursday, August 11, 2016 at 12:50:14 AM UTC+2, Erik Schnetter wrote:
>
> The upshot of the discussions seems to be "it won't work in 0.5 because
>> the experts say so, and there are no plans to change that". So I'm going to
>> accept that statement.
>>
>> I think I'll use the following work-around:
>> ```Julia
>> immutable Wrapper{Tag,Types}
>> data::Types
>> end
>> ```
>> where I use `Tag` as `Val{Symbol}` to generate many distinct types, and
>> `Types` will be a tuple. This allows me to "generate" any immutable type. I
>> won't be able to access fields via the `.fieldname` syntax, but that is not
>> important to me.
>>
>> -erik
>>
>>
>>
>> On Wed, Aug 10, 2016 at 6:09 PM, Tim Holy  wrote:
>>
>>> 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.
>>>
>>> function create_type_dynamically{T}(::Type{T})
>>> type_name = string("MyType", T)
>>> isdefined(Main, Symbol(type_name)) && return nothing
>>> filename = joinpath(tempdir(), string(T))
>>> open(filename, "w") do io
>>> println(io, """
>>> type $type_name
>>> val::$T
>>> end
>>> """)
>>> end
>>> eval(include(filename))
>>> nothing
>>> end
>>>
>>> Is this somehow less evil than doing it in a generated function?
>>>
>>> Best,
>>> --Tim
>>>
>>> On Wednesday, August 10, 2016 9:49:23 PM CDT Jameson Nash wrote:
>>> > > Why is it impossible to generate a new type at run time? I surely
>>> can do
>>> >
>>> > this by calling `eval` at module scope.
>>> >
>>> > module scope is compile time != runtime
>>> >
>>> > > Or I could create a type via a macro.
>>> >
>>> > Again, compile time != runtime
>>> >
>>> > > Given this, I can also call `eval` in a function, if I ensure the
>>> >
>>> > function is called only once.
>>> >
>>> > > Note that I've been doing this in Julia 0.4 without any (apparent)
>>> >
>>> > problems.
>>> >
>>> > Sure, I'm just here to tell you why it won't work that way in v0.5
>>> >
>>> > > I'm not defining thousands of types in my code. I define one type,
>>> and
>>> >
>>> > use it all over the place. However, each time my code runs (for
>>> days!), it
>>> > defines a different type, chosen by a set of user parameters. I'm also
>>> not
>>> > adding constraints to type parameters -- the type parameters are just
>>> `Int`
>>> > values.
>>> >
>>> > Right, the basic tradeoff required here is that you just need to
>>> provide a
>>> > convenient way for your user to declare the type at the toplevel that
>>> will
>>> > be used for the run. For example, you can just JIT the code for the
>>> whole
>>> > run at the beginning:
>>> >
>>> > function do_run()
>>> >   return @eval begin
>>> >  lots of function definitions
>>> >  do_work()
>>> >   end
>>> > end
>>> >
>>> > On Wed, Aug 10, 2016 at 5:14 PM Erik Schnetter 
>>> wrote:
>>> > > On Wed, Aug 10, 2016 at 1:45 PM, Jameson  wrote:
>>> > >> AFAIK, defining an arbitrary new type at runtime is impossible,
>>> sorry. In
>>> > >> v0.4 it was allowed, because we hoped that people understood not to
>>> try.
>>> > >> See also https://github.com/JuliaLang/julia/issues/16806. Note
>>> that it
>>> > >> is insufficient to "handle" the repeat calling via caching in a
>>> Dict or
>>> > >> similar such mechanism. It must always compute the exact final
>>> output
>>> > >> from
>>> > >> the input values alone (e.g. it must truly be const pure).
>>> > >
>>> > > The generated function first calculates the name of the type, then
>>> checks
>>> > > (`isdefined`) if this type is defined, and if so, returns it.
>>> Otherwise it
>>> > > is defined and then returned. This 

Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-11 Thread Tomas Lycken


Late to the party, but what’s wrong with writing FastArray{1,10,1,10} (or 
even FastArray{10,10} if you’re OK with implicit 1-based indexing)? It 
seems that those (valid) type arguments could convey just as much 
information as FastArray(1:10, 1:10), and you could then handle any 
special-casing on the size in the constructor. That way you’d only need one 
(generic) type. Or am I missing something important here?

// T

On Thursday, August 11, 2016 at 12:50:14 AM UTC+2, Erik Schnetter wrote:

The upshot of the discussions seems to be "it won't work in 0.5 because the 
> experts say so, and there are no plans to change that". So I'm going to 
> accept that statement.
>
> I think I'll use the following work-around:
> ```Julia
> immutable Wrapper{Tag,Types}
> data::Types
> end
> ```
> where I use `Tag` as `Val{Symbol}` to generate many distinct types, and 
> `Types` will be a tuple. This allows me to "generate" any immutable type. I 
> won't be able to access fields via the `.fieldname` syntax, but that is not 
> important to me.
>
> -erik
>
>
>
> On Wed, Aug 10, 2016 at 6:09 PM, Tim Holy  > wrote:
>
>> 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.
>>
>> function create_type_dynamically{T}(::Type{T})
>> type_name = string("MyType", T)
>> isdefined(Main, Symbol(type_name)) && return nothing
>> filename = joinpath(tempdir(), string(T))
>> open(filename, "w") do io
>> println(io, """
>> type $type_name
>> val::$T
>> end
>> """)
>> end
>> eval(include(filename))
>> nothing
>> end
>>
>> Is this somehow less evil than doing it in a generated function?
>>
>> Best,
>> --Tim
>>
>> On Wednesday, August 10, 2016 9:49:23 PM CDT Jameson Nash wrote:
>> > > Why is it impossible to generate a new type at run time? I surely can 
>> do
>> >
>> > this by calling `eval` at module scope.
>> >
>> > module scope is compile time != runtime
>> >
>> > > Or I could create a type via a macro.
>> >
>> > Again, compile time != runtime
>> >
>> > > Given this, I can also call `eval` in a function, if I ensure the
>> >
>> > function is called only once.
>> >
>> > > Note that I've been doing this in Julia 0.4 without any (apparent)
>> >
>> > problems.
>> >
>> > Sure, I'm just here to tell you why it won't work that way in v0.5
>> >
>> > > I'm not defining thousands of types in my code. I define one type, and
>> >
>> > use it all over the place. However, each time my code runs (for days!), 
>> it
>> > defines a different type, chosen by a set of user parameters. I'm also 
>> not
>> > adding constraints to type parameters -- the type parameters are just 
>> `Int`
>> > values.
>> >
>> > Right, the basic tradeoff required here is that you just need to 
>> provide a
>> > convenient way for your user to declare the type at the toplevel that 
>> will
>> > be used for the run. For example, you can just JIT the code for the 
>> whole
>> > run at the beginning:
>> >
>> > function do_run()
>> >   return @eval begin
>> >  lots of function definitions
>> >  do_work()
>> >   end
>> > end
>> >
>> > On Wed, Aug 10, 2016 at 5:14 PM Erik Schnetter > > wrote:
>> > > On Wed, Aug 10, 2016 at 1:45 PM, Jameson > > wrote:
>> > >> AFAIK, defining an arbitrary new type at runtime is impossible, 
>> sorry. In
>> > >> v0.4 it was allowed, because we hoped that people understood not to 
>> try.
>> > >> See also https://github.com/JuliaLang/julia/issues/16806. Note that 
>> it
>> > >> is insufficient to "handle" the repeat calling via caching in a Dict 
>> or
>> > >> similar such mechanism. It must always compute the exact final output
>> > >> from
>> > >> the input values alone (e.g. it must truly be const pure).
>> > >
>> > > The generated function first calculates the name of the type, then 
>> checks
>> > > (`isdefined`) if this type is defined, and if so, returns it. 
>> Otherwise it
>> > > is defined and then returned. This corresponds to looking up the type 
>> via
>> > > `eval(typename)` (a symbol). I assume this is as pure as it gets.
>> > >
>> > > Why is it impossible to generate a new type at run time? I surely can 
>> do
>> > > this by calling `eval` at module scope. Or I could create a type via a
>> > > macro. Given this, I can also call `eval` in a function, if I ensure 
>> the
>> > > function is called only once. Note that I've been doing this in Julia 
>> 0.4
>> > > without any (apparent) problems.
>> > >
>> > > Being able to define types with arbitrary constraints in the type
>> > >
>> > >> parameters works OK for toy demos, but it's intentionally rather
>> > >> difficult
>> > >> since it causes performance issues at scale. Operations on Array are
>> > >> likely
>> > >> to be much faster (including the allocation) than on Tuple (due to 
>> the
>> > >> cost
>> > >> of *not* allocating) unless that Tuple is very 

Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Erik Schnetter
The upshot of the discussions seems to be "it won't work in 0.5 because the
experts say so, and there are no plans to change that". So I'm going to
accept that statement.

I think I'll use the following work-around:
```Julia
immutable Wrapper{Tag,Types}
data::Types
end
```
where I use `Tag` as `Val{Symbol}` to generate many distinct types, and
`Types` will be a tuple. This allows me to "generate" any immutable type. I
won't be able to access fields via the `.fieldname` syntax, but that is not
important to me.

-erik



On Wed, Aug 10, 2016 at 6:09 PM, Tim Holy  wrote:

> 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.
>
> function create_type_dynamically{T}(::Type{T})
> type_name = string("MyType", T)
> isdefined(Main, Symbol(type_name)) && return nothing
> filename = joinpath(tempdir(), string(T))
> open(filename, "w") do io
> println(io, """
> type $type_name
> val::$T
> end
> """)
> end
> eval(include(filename))
> nothing
> end
>
> Is this somehow less evil than doing it in a generated function?
>
> Best,
> --Tim
>
> On Wednesday, August 10, 2016 9:49:23 PM CDT Jameson Nash wrote:
> > > Why is it impossible to generate a new type at run time? I surely can
> do
> >
> > this by calling `eval` at module scope.
> >
> > module scope is compile time != runtime
> >
> > > Or I could create a type via a macro.
> >
> > Again, compile time != runtime
> >
> > > Given this, I can also call `eval` in a function, if I ensure the
> >
> > function is called only once.
> >
> > > Note that I've been doing this in Julia 0.4 without any (apparent)
> >
> > problems.
> >
> > Sure, I'm just here to tell you why it won't work that way in v0.5
> >
> > > I'm not defining thousands of types in my code. I define one type, and
> >
> > use it all over the place. However, each time my code runs (for days!),
> it
> > defines a different type, chosen by a set of user parameters. I'm also
> not
> > adding constraints to type parameters -- the type parameters are just
> `Int`
> > values.
> >
> > Right, the basic tradeoff required here is that you just need to provide
> a
> > convenient way for your user to declare the type at the toplevel that
> will
> > be used for the run. For example, you can just JIT the code for the whole
> > run at the beginning:
> >
> > function do_run()
> >   return @eval begin
> >  lots of function definitions
> >  do_work()
> >   end
> > end
> >
> > On Wed, Aug 10, 2016 at 5:14 PM Erik Schnetter 
> wrote:
> > > On Wed, Aug 10, 2016 at 1:45 PM, Jameson  wrote:
> > >> AFAIK, defining an arbitrary new type at runtime is impossible,
> sorry. In
> > >> v0.4 it was allowed, because we hoped that people understood not to
> try.
> > >> See also https://github.com/JuliaLang/julia/issues/16806. Note that
> it
> > >> is insufficient to "handle" the repeat calling via caching in a Dict
> or
> > >> similar such mechanism. It must always compute the exact final output
> > >> from
> > >> the input values alone (e.g. it must truly be const pure).
> > >
> > > The generated function first calculates the name of the type, then
> checks
> > > (`isdefined`) if this type is defined, and if so, returns it.
> Otherwise it
> > > is defined and then returned. This corresponds to looking up the type
> via
> > > `eval(typename)` (a symbol). I assume this is as pure as it gets.
> > >
> > > Why is it impossible to generate a new type at run time? I surely can
> do
> > > this by calling `eval` at module scope. Or I could create a type via a
> > > macro. Given this, I can also call `eval` in a function, if I ensure
> the
> > > function is called only once. Note that I've been doing this in Julia
> 0.4
> > > without any (apparent) problems.
> > >
> > > Being able to define types with arbitrary constraints in the type
> > >
> > >> parameters works OK for toy demos, but it's intentionally rather
> > >> difficult
> > >> since it causes performance issues at scale. Operations on Array are
> > >> likely
> > >> to be much faster (including the allocation) than on Tuple (due to the
> > >> cost
> > >> of *not* allocating) unless that Tuple is very small.
> > >
> > > I'm not defining thousands of types in my code. I define one type, and
> use
> > > it all over the place. However, each time my code runs (for days!), it
> > > defines a different type, chosen by a set of user parameters. I'm also
> not
> > > adding constraints to type parameters -- the type parameters are just
> > > `Int`
> > > values.
> > >
> > > And yes, I am using a mutable `Vector{T}` as underlying storage, that's
> > > not the issue here. The speedup comes from knowing the size of the
> array
> > > ahead of time, which allows the compiler to optimize indexing
> expressions.
> > > I've benchmarked it, and examined the generated machine code. There's
> no

Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Jameson Nash
The `eval` there is redundant with `include`. But there's nothing wrong
with running julia code during compile-time to dynamically generate code.
The confusion there comes from the fact that Julia has a compile-step
between each toplevel statement, which allows you to intermix runtime and
compile. However, if you tried to do the same from inside `@generated`,
then there is only portion of a compile-step before the runtime, so some
constructs can't be handled.

In v0.6, it's possible we could allow the creation of some types (many
types are simple enough they could be constructed without needing to actual
execute the definition). However, the fix for #265 will soon bar you from
calling the constructor of this type, so I'm not sure what would be gained.

> This isn't much of an explanation. I think this would seem like less of a
"because I say so" if you provided an explanation of what the problem with
calling eval within a generated function is, rather than just an assertion
that it can't work.

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.



On Wed, Aug 10, 2016 at 6:10 PM Tim Holy  wrote:

> 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.
>
> function create_type_dynamically{T}(::Type{T})
> type_name = string("MyType", T)
> isdefined(Main, Symbol(type_name)) && return nothing
> filename = joinpath(tempdir(), string(T))
> open(filename, "w") do io
> println(io, """
> type $type_name
> val::$T
> end
> """)
> end
> eval(include(filename))
> nothing
> end
>
> Is this somehow less evil than doing it in a generated function?
>
> Best,
> --Tim
>
> On Wednesday, August 10, 2016 9:49:23 PM CDT Jameson Nash wrote:
> > > Why is it impossible to generate a new type at run time? I surely can
> do
> >
> > this by calling `eval` at module scope.
> >
> > module scope is compile time != runtime
> >
> > > Or I could create a type via a macro.
> >
> > Again, compile time != runtime
> >
> > > Given this, I can also call `eval` in a function, if I ensure the
> >
> > function is called only once.
> >
> > > Note that I've been doing this in Julia 0.4 without any (apparent)
> >
> > problems.
> >
> > Sure, I'm just here to tell you why it won't work that way in v0.5
> >
> > > I'm not defining thousands of types in my code. I define one type, and
> >
> > use it all over the place. However, each time my code runs (for days!),
> it
> > defines a different type, chosen by a set of user parameters. I'm also
> not
> > adding constraints to type parameters -- the type parameters are just
> `Int`
> > values.
> >
> > Right, the basic tradeoff required here is that you just need to provide
> a
> > convenient way for your user to declare the type at the toplevel that
> will
> > be used for the run. For example, you can just JIT the code for the whole
> > run at the beginning:
> >
> > function do_run()
> >   return @eval begin
> >  lots of function definitions
> >  do_work()
> >   end
> > end
> >
> > On Wed, Aug 10, 2016 at 5:14 PM Erik Schnetter 
> wrote:
> > > On Wed, Aug 10, 2016 at 1:45 PM, Jameson  wrote:
> > >> AFAIK, defining an arbitrary new type at runtime is impossible,
> sorry. In
> > >> v0.4 it was allowed, because we hoped that people understood not to
> try.
> > >> See also https://github.com/JuliaLang/julia/issues/16806. Note that
> it
> > >> is insufficient to "handle" the repeat calling via caching in a Dict
> or
> > >> similar such mechanism. It must always compute the exact final output
> > >> from
> > >> the input values alone (e.g. it must truly be const pure).
> > >
> > > The generated function first calculates the name of the type, then
> checks
> > > (`isdefined`) if this type is defined, and if so, returns it.
> Otherwise it
> > > is defined and then returned. This corresponds to looking up the type
> via
> > > `eval(typename)` (a symbol). I assume this is as pure as it gets.
> > >
> > > Why is it impossible to generate a new type at run time? I surely can
> do
> > > this by calling `eval` at module scope. Or I could create a type via a
> > > macro. Given this, I can also call `eval` in a function, if I ensure
> the
> > > function is called only once. Note that I've been doing this in Julia
> 0.4
> > > without any (apparent) problems.
> > >
> > > Being able to define types with arbitrary constraints in the type
> > >
> > >> parameters works OK for toy demos, but it's intentionally 

Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Tim Holy
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.

function create_type_dynamically{T}(::Type{T})
type_name = string("MyType", T)
isdefined(Main, Symbol(type_name)) && return nothing
filename = joinpath(tempdir(), string(T))
open(filename, "w") do io
println(io, """
type $type_name
val::$T
end
""")
end
eval(include(filename))
nothing
end

Is this somehow less evil than doing it in a generated function?

Best,
--Tim

On Wednesday, August 10, 2016 9:49:23 PM CDT Jameson Nash wrote:
> > Why is it impossible to generate a new type at run time? I surely can do
> 
> this by calling `eval` at module scope.
> 
> module scope is compile time != runtime
> 
> > Or I could create a type via a macro.
> 
> Again, compile time != runtime
> 
> > Given this, I can also call `eval` in a function, if I ensure the
> 
> function is called only once.
> 
> > Note that I've been doing this in Julia 0.4 without any (apparent)
> 
> problems.
> 
> Sure, I'm just here to tell you why it won't work that way in v0.5
> 
> > I'm not defining thousands of types in my code. I define one type, and
> 
> use it all over the place. However, each time my code runs (for days!), it
> defines a different type, chosen by a set of user parameters. I'm also not
> adding constraints to type parameters -- the type parameters are just `Int`
> values.
> 
> Right, the basic tradeoff required here is that you just need to provide a
> convenient way for your user to declare the type at the toplevel that will
> be used for the run. For example, you can just JIT the code for the whole
> run at the beginning:
> 
> function do_run()
>   return @eval begin
>  lots of function definitions
>  do_work()
>   end
> end
> 
> On Wed, Aug 10, 2016 at 5:14 PM Erik Schnetter  wrote:
> > On Wed, Aug 10, 2016 at 1:45 PM, Jameson  wrote:
> >> AFAIK, defining an arbitrary new type at runtime is impossible, sorry. In
> >> v0.4 it was allowed, because we hoped that people understood not to try.
> >> See also https://github.com/JuliaLang/julia/issues/16806. Note that it
> >> is insufficient to "handle" the repeat calling via caching in a Dict or
> >> similar such mechanism. It must always compute the exact final output
> >> from
> >> the input values alone (e.g. it must truly be const pure).
> > 
> > The generated function first calculates the name of the type, then checks
> > (`isdefined`) if this type is defined, and if so, returns it. Otherwise it
> > is defined and then returned. This corresponds to looking up the type via
> > `eval(typename)` (a symbol). I assume this is as pure as it gets.
> > 
> > Why is it impossible to generate a new type at run time? I surely can do
> > this by calling `eval` at module scope. Or I could create a type via a
> > macro. Given this, I can also call `eval` in a function, if I ensure the
> > function is called only once. Note that I've been doing this in Julia 0.4
> > without any (apparent) problems.
> > 
> > Being able to define types with arbitrary constraints in the type
> > 
> >> parameters works OK for toy demos, but it's intentionally rather
> >> difficult
> >> since it causes performance issues at scale. Operations on Array are
> >> likely
> >> to be much faster (including the allocation) than on Tuple (due to the
> >> cost
> >> of *not* allocating) unless that Tuple is very small.
> > 
> > I'm not defining thousands of types in my code. I define one type, and use
> > it all over the place. However, each time my code runs (for days!), it
> > defines a different type, chosen by a set of user parameters. I'm also not
> > adding constraints to type parameters -- the type parameters are just
> > `Int`
> > values.
> > 
> > And yes, I am using a mutable `Vector{T}` as underlying storage, that's
> > not the issue here. The speedup comes from knowing the size of the array
> > ahead of time, which allows the compiler to optimize indexing expressions.
> > I've benchmarked it, and examined the generated machine code. There's no
> > doubt that generating a type is the "right thing" to do in this case.
> > 
> > -erik
> > 
> > On Wednesday, August 10, 2016 at 1:25:15 PM UTC-4, Erik Schnetter wrote:
> >>> I want to create a type, and need more flexibility than Julia's `type`
> >>> definitions offer (see ).
> >>> Currently, I have a function that generates the type, and returns the
> >>> type.
> >>> 
> >>> I would like to make this a generated function (as it was in Julia 0.4).
> >>> The advantage is that this leads to type stability: The generated type
> >>> only
> >>> depends on the types of the arguments pass to the function, and Julia
> >>> would
> >>> be able to infer the type.
> >>> 
> >>> In practice, this looks like
> >>> 
> >>> using FastArrays
> >>> # A (10x10) fixed-size arraytypealias 

Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Stefan Karpinski
On Wed, Aug 10, 2016 at 5:49 PM, Jameson Nash  wrote:

> module scope is compile time != runtime


This isn't much of an explanation. I think this would seem like less of a
"because I say so" if you provided an explanation of what the problem with
calling eval within a generated function is, rather than just an assertion
that it can't work.


Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Jameson Nash
> Why is it impossible to generate a new type at run time? I surely can do
this by calling `eval` at module scope.

module scope is compile time != runtime

> Or I could create a type via a macro.

Again, compile time != runtime

> Given this, I can also call `eval` in a function, if I ensure the
function is called only once.

> Note that I've been doing this in Julia 0.4 without any (apparent)
problems.

Sure, I'm just here to tell you why it won't work that way in v0.5

> I'm not defining thousands of types in my code. I define one type, and
use it all over the place. However, each time my code runs (for days!), it
defines a different type, chosen by a set of user parameters. I'm also not
adding constraints to type parameters -- the type parameters are just `Int`
values.

Right, the basic tradeoff required here is that you just need to provide a
convenient way for your user to declare the type at the toplevel that will
be used for the run. For example, you can just JIT the code for the whole
run at the beginning:

function do_run()
  return @eval begin
 lots of function definitions
 do_work()
  end
end



On Wed, Aug 10, 2016 at 5:14 PM Erik Schnetter  wrote:

> On Wed, Aug 10, 2016 at 1:45 PM, Jameson  wrote:
>
>> AFAIK, defining an arbitrary new type at runtime is impossible, sorry. In
>> v0.4 it was allowed, because we hoped that people understood not to try.
>> See also https://github.com/JuliaLang/julia/issues/16806. Note that it
>> is insufficient to "handle" the repeat calling via caching in a Dict or
>> similar such mechanism. It must always compute the exact final output from
>> the input values alone (e.g. it must truly be const pure).
>>
>
> The generated function first calculates the name of the type, then checks
> (`isdefined`) if this type is defined, and if so, returns it. Otherwise it
> is defined and then returned. This corresponds to looking up the type via
> `eval(typename)` (a symbol). I assume this is as pure as it gets.
>
> Why is it impossible to generate a new type at run time? I surely can do
> this by calling `eval` at module scope. Or I could create a type via a
> macro. Given this, I can also call `eval` in a function, if I ensure the
> function is called only once. Note that I've been doing this in Julia 0.4
> without any (apparent) problems.
>
> Being able to define types with arbitrary constraints in the type
>> parameters works OK for toy demos, but it's intentionally rather difficult
>> since it causes performance issues at scale. Operations on Array are likely
>> to be much faster (including the allocation) than on Tuple (due to the cost
>> of *not* allocating) unless that Tuple is very small.
>>
>
> I'm not defining thousands of types in my code. I define one type, and use
> it all over the place. However, each time my code runs (for days!), it
> defines a different type, chosen by a set of user parameters. I'm also not
> adding constraints to type parameters -- the type parameters are just `Int`
> values.
>
> And yes, I am using a mutable `Vector{T}` as underlying storage, that's
> not the issue here. The speedup comes from knowing the size of the array
> ahead of time, which allows the compiler to optimize indexing expressions.
> I've benchmarked it, and examined the generated machine code. There's no
> doubt that generating a type is the "right thing" to do in this case.
>
> -erik
>
> On Wednesday, August 10, 2016 at 1:25:15 PM UTC-4, Erik Schnetter wrote:
>>>
>>> I want to create a type, and need more flexibility than Julia's `type`
>>> definitions offer (see ).
>>> Currently, I have a function that generates the type, and returns the type.
>>>
>>> I would like to make this a generated function (as it was in Julia 0.4).
>>> The advantage is that this leads to type stability: The generated type only
>>> depends on the types of the arguments pass to the function, and Julia would
>>> be able to infer the type.
>>>
>>> In practice, this looks like
>>>
>>> using FastArrays
>>> # A (10x10) fixed-size arraytypealias Arr2d_10x10 FastArray(1:10, 1:10)
>>> a2 = Arr2d_10x10{Float64}(:,:)
>>>
>>>
>>> In principle I'd like to write `FastArray{1:10, 1:10}` (with curly
>>> braces), but Julia doesn't offer sufficient flexibility for this. Hence I
>>> use a regular function.
>>>
>>> To generate the type in the function I need to call `eval`. (Yes, I'm
>>> aware that the function might be called multiple times, and I'm handling
>>> this.)
>>>
>>> Do you have a suggestion for a different solution?
>>>
>>> -erik
>>>
>>>
>>> On Wed, Aug 10, 2016 at 11:51 AM, Jameson  wrote:
>>>
 It is tracking the dynamic scope of the code generator, it doesn't care
 about what code you emit. The generator function must not cause any
 side-effects and must be entirely computed from the types of the inputs and
 not other global state. Over time, these conditions are likely to be 

Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Erik Schnetter
On Wed, Aug 10, 2016 at 1:45 PM, Jameson  wrote:

> AFAIK, defining an arbitrary new type at runtime is impossible, sorry. In
> v0.4 it was allowed, because we hoped that people understood not to try.
> See also https://github.com/JuliaLang/julia/issues/16806. Note that it is
> insufficient to "handle" the repeat calling via caching in a Dict or
> similar such mechanism. It must always compute the exact final output from
> the input values alone (e.g. it must truly be const pure).
>

The generated function first calculates the name of the type, then checks
(`isdefined`) if this type is defined, and if so, returns it. Otherwise it
is defined and then returned. This corresponds to looking up the type via
`eval(typename)` (a symbol). I assume this is as pure as it gets.

Why is it impossible to generate a new type at run time? I surely can do
this by calling `eval` at module scope. Or I could create a type via a
macro. Given this, I can also call `eval` in a function, if I ensure the
function is called only once. Note that I've been doing this in Julia 0.4
without any (apparent) problems.

Being able to define types with arbitrary constraints in the type
> parameters works OK for toy demos, but it's intentionally rather difficult
> since it causes performance issues at scale. Operations on Array are likely
> to be much faster (including the allocation) than on Tuple (due to the cost
> of *not* allocating) unless that Tuple is very small.
>

I'm not defining thousands of types in my code. I define one type, and use
it all over the place. However, each time my code runs (for days!), it
defines a different type, chosen by a set of user parameters. I'm also not
adding constraints to type parameters -- the type parameters are just `Int`
values.

And yes, I am using a mutable `Vector{T}` as underlying storage, that's not
the issue here. The speedup comes from knowing the size of the array ahead
of time, which allows the compiler to optimize indexing expressions. I've
benchmarked it, and examined the generated machine code. There's no doubt
that generating a type is the "right thing" to do in this case.

-erik

On Wednesday, August 10, 2016 at 1:25:15 PM UTC-4, Erik Schnetter wrote:
>>
>> I want to create a type, and need more flexibility than Julia's `type`
>> definitions offer (see ).
>> Currently, I have a function that generates the type, and returns the type.
>>
>> I would like to make this a generated function (as it was in Julia 0.4).
>> The advantage is that this leads to type stability: The generated type only
>> depends on the types of the arguments pass to the function, and Julia would
>> be able to infer the type.
>>
>> In practice, this looks like
>>
>> using FastArrays
>> # A (10x10) fixed-size arraytypealias Arr2d_10x10 FastArray(1:10, 1:10)
>> a2 = Arr2d_10x10{Float64}(:,:)
>>
>>
>> In principle I'd like to write `FastArray{1:10, 1:10}` (with curly
>> braces), but Julia doesn't offer sufficient flexibility for this. Hence I
>> use a regular function.
>>
>> To generate the type in the function I need to call `eval`. (Yes, I'm
>> aware that the function might be called multiple times, and I'm handling
>> this.)
>>
>> Do you have a suggestion for a different solution?
>>
>> -erik
>>
>>
>> On Wed, Aug 10, 2016 at 11:51 AM, Jameson  wrote:
>>
>>> It is tracking the dynamic scope of the code generator, it doesn't care
>>> about what code you emit. The generator function must not cause any
>>> side-effects and must be entirely computed from the types of the inputs and
>>> not other global state. Over time, these conditions are likely to be more
>>> accurately enforced, as needed to make various optimizations reliable
>>> and/or correct.
>>>
>>>
>>>
>>> On Wednesday, August 10, 2016 at 10:48:31 AM UTC-4, Erik Schnetter 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. My question
 is -- what exactly is now disallowed? For example, if a generated function
 `f` calls another (non-generated) function `g`, can `g` then call `eval`?
 Does the word "in" here refer to the code that is generated by the
 generated function, or does it refer to the dynamical scope of the code
 generation state of the generated function?

 To avoid the error I have to redesign my code, and I'd like to know
 ahead of time what to avoid. A Google search only turned up the C file
 within Julia that emits the respective error message, as well as the Travis
 build log for my package.

 -erik

 --
 Erik Schnetter  http://www.perimeterinstitute.
 ca/personal/eschnetter/

>>>
>>
>>
>> --
>> Erik Schnetter  http://www.perimeterinstitute.
>> ca/personal/eschnetter/
>>
>


-- 
Erik Schnetter 

Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Jameson
AFAIK, defining an arbitrary new type at runtime is impossible, sorry. In 
v0.4 it was allowed, because we hoped that people understood not to try. 
See also https://github.com/JuliaLang/julia/issues/16806. Note that it is 
insufficient to "handle" the repeat calling via caching in a Dict or 
similar such mechanism. It must always compute the exact final output from 
the input values alone (e.g. it must truly be const pure).

Being able to define types with arbitrary constraints in the type 
parameters works OK for toy demos, but it's intentionally rather difficult 
since it causes performance issues at scale. Operations on Array are likely 
to be much faster (including the allocation) than on Tuple (due to the cost 
of *not* allocating) unless that Tuple is very small.



On Wednesday, August 10, 2016 at 1:25:15 PM UTC-4, Erik Schnetter wrote:
>
> I want to create a type, and need more flexibility than Julia's `type` 
> definitions offer (see ). 
> Currently, I have a function that generates the type, and returns the type.
>
> I would like to make this a generated function (as it was in Julia 0.4). 
> The advantage is that this leads to type stability: The generated type only 
> depends on the types of the arguments pass to the function, and Julia would 
> be able to infer the type.
>
> In practice, this looks like
>
> using FastArrays
> # A (10x10) fixed-size arraytypealias Arr2d_10x10 FastArray(1:10, 1:10)
> a2 = Arr2d_10x10{Float64}(:,:)
>
>
> In principle I'd like to write `FastArray{1:10, 1:10}` (with curly 
> braces), but Julia doesn't offer sufficient flexibility for this. Hence I 
> use a regular function.
>
> To generate the type in the function I need to call `eval`. (Yes, I'm 
> aware that the function might be called multiple times, and I'm handling 
> this.)
>
> Do you have a suggestion for a different solution?
>
> -erik
>
>
> On Wed, Aug 10, 2016 at 11:51 AM, Jameson  wrote:
>
>> It is tracking the dynamic scope of the code generator, it doesn't care 
>> about what code you emit. The generator function must not cause any 
>> side-effects and must be entirely computed from the types of the inputs and 
>> not other global state. Over time, these conditions are likely to be more 
>> accurately enforced, as needed to make various optimizations reliable 
>> and/or correct.
>>
>>
>>
>> On Wednesday, August 10, 2016 at 10:48:31 AM UTC-4, Erik Schnetter 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. My question is -- what 
>>> exactly is now disallowed? For example, if a generated function `f` calls 
>>> another (non-generated) function `g`, can `g` then call `eval`? Does the 
>>> word "in" here refer to the code that is generated by the generated 
>>> function, or does it refer to the dynamical scope of the code generation 
>>> state of the generated function?
>>>
>>> To avoid the error I have to redesign my code, and I'd like to know 
>>> ahead of time what to avoid. A Google search only turned up the C file 
>>> within Julia that emits the respective error message, as well as the Travis 
>>> build log for my package.
>>>
>>> -erik
>>>
>>> -- 
>>> Erik Schnetter  
>>> http://www.perimeterinstitute.ca/personal/eschnetter/
>>>
>>
>
>
> -- 
> Erik Schnetter  
> http://www.perimeterinstitute.ca/personal/eschnetter/
>


Re: [julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Erik Schnetter
I want to create a type, and need more flexibility than Julia's `type`
definitions offer (see ).
Currently, I have a function that generates the type, and returns the type.

I would like to make this a generated function (as it was in Julia 0.4).
The advantage is that this leads to type stability: The generated type only
depends on the types of the arguments pass to the function, and Julia would
be able to infer the type.

In practice, this looks like

using FastArrays
# A (10x10) fixed-size arraytypealias Arr2d_10x10 FastArray(1:10, 1:10)
a2 = Arr2d_10x10{Float64}(:,:)


In principle I'd like to write `FastArray{1:10, 1:10}` (with curly braces),
but Julia doesn't offer sufficient flexibility for this. Hence I use a
regular function.

To generate the type in the function I need to call `eval`. (Yes, I'm aware
that the function might be called multiple times, and I'm handling this.)

Do you have a suggestion for a different solution?

-erik


On Wed, Aug 10, 2016 at 11:51 AM, Jameson  wrote:

> It is tracking the dynamic scope of the code generator, it doesn't care
> about what code you emit. The generator function must not cause any
> side-effects and must be entirely computed from the types of the inputs and
> not other global state. Over time, these conditions are likely to be more
> accurately enforced, as needed to make various optimizations reliable
> and/or correct.
>
>
>
> On Wednesday, August 10, 2016 at 10:48:31 AM UTC-4, Erik Schnetter 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. My question is -- what
>> exactly is now disallowed? For example, if a generated function `f` calls
>> another (non-generated) function `g`, can `g` then call `eval`? Does the
>> word "in" here refer to the code that is generated by the generated
>> function, or does it refer to the dynamical scope of the code generation
>> state of the generated function?
>>
>> To avoid the error I have to redesign my code, and I'd like to know ahead
>> of time what to avoid. A Google search only turned up the C file within
>> Julia that emits the respective error message, as well as the Travis build
>> log for my package.
>>
>> -erik
>>
>> --
>> Erik Schnetter  http://www.perimeterinstitute.
>> ca/personal/eschnetter/
>>
>


-- 
Erik Schnetter 
http://www.perimeterinstitute.ca/personal/eschnetter/


[julia-users] Re: "eval cannot be used in a generated function"

2016-08-10 Thread Jameson
It is tracking the dynamic scope of the code generator, it doesn't care 
about what code you emit. The generator function must not cause any 
side-effects and must be entirely computed from the types of the inputs and 
not other global state. Over time, these conditions are likely to be more 
accurately enforced, as needed to make various optimizations reliable 
and/or correct.



On Wednesday, August 10, 2016 at 10:48:31 AM UTC-4, Erik Schnetter 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. My question is -- what 
> exactly is now disallowed? For example, if a generated function `f` calls 
> another (non-generated) function `g`, can `g` then call `eval`? Does the 
> word "in" here refer to the code that is generated by the generated 
> function, or does it refer to the dynamical scope of the code generation 
> state of the generated function?
>
> To avoid the error I have to redesign my code, and I'd like to know ahead 
> of time what to avoid. A Google search only turned up the C file within 
> Julia that emits the respective error message, as well as the Travis build 
> log for my package.
>
> -erik
>
> -- 
> Erik Schnetter  
> http://www.perimeterinstitute.ca/personal/eschnetter/
>