There are times when a return type for a function needs controlled dynamically instead of statically. I recommend a Func constructor that lets you specify return types dynamically. Here's an example usage:
List callMap(List list, |Obj?, Int -> Obj?| mapper) {
list.map(Func(mapper.params, mapper.returns) |Obj? val, Int i -> Obj?| {
// Just ridiculous changes here to justify wrapping the function.
mapper(val, list.size - i - 1)
})
}
Such a constructor would be similar, say, to the List constructor that lets you explicitly set the type via a Type variable.
brianWed 3 Jun 2009
Promoted to ticket #620 and assigned to brian
Not quite sure about that - I guess we could do something to parameterize a func which wraps another func.
But I'll mark it as a ticket to track it
tompalmerThu 4 Jun 2009
Not quite sure about that - I guess we could do something to parameterize a func which wraps another func.
Mostly what I was thinking. Could be optimized/compressed down to one function in some cases. Not sure. Whatever's easiest (especially if it avoids reflection) would be fine to start with, I think.
By the way, my use case was for my matrix stuff I'm working on. I have a constructor to generate matrix data from a passed in function:
It doesn't work from another matrix, but I figured that the map function (which does work from an existing matrix) could make nice use of this:
Mat map(|Obj?, Int[] -> Obj?| mapper) {
// TODO How to use the return type of mapper to control the return type below?
i := 0
return ObjMat.generate(shape) |Int[] coords -> Obj?| {
mapper(get(i++), coords)
}
}
That "TODO" part is where I hit this issue.
I'm also willing to believe there will be other use cases for generating functions with dynamically defined types (even though my poor example starting this thread is obviously a bogus case).
Lacking this feature, I could recode this not to reuse the generate constructor. More likely I'll have to ignore the matrix type. Alternatively, I might add the explicit type literal for the matrix's of, which was decided against for List#map.
brianSat 11 Jul 2009
Ticket resolved in 1.0.45
Tom,
I added a new Func.retype method:
**
** Return a new function which wraps this function but with
** a different reflective type signature. No verification is
** done that this function actually conforms to new signature.
** Throw ArgErr if 't' isn't a parameterized function type.
**
** Examples:
** f := |a,b->Obj| { "$a, $b" }
** g := f.retype(|Int,Int->Str|#)
** f.type => |Obj?,Obj?->Obj|
** g.type => |Int,Int->Str|
**
Func retype(Type t)
Why don't you try it out and see how it works for your use case.
tompalmerMon 13 Jul 2009
I haven't tried it out, but I don't think it will work for the general case, because you still can't specify a function type given Type variables for the args and return type, right? I think your current proposal can already be done like so, anyway, right?
I haven't tried it out, but I don't think it will work for the general case, because you still can't specify a function type given Type variables for the args and return type, right?
Thanks. I had missed (or forgotten) that. I might try profiling it. I'm afraid of the speed of using reflective names at the moment.
brianTue 14 Jul 2009
Thanks. I had missed (or forgotten) that. I might try profiling it. I'm afraid of the speed of using reflective names at the moment.
Type.parameterize is purely munging of data structures, it is pretty light weight. The heaviest part if creating the map to use an argument which you can cache if you know it ahead of time.
tompalmer Wed 3 Jun 2009
There are times when a return type for a function needs controlled dynamically instead of statically. I recommend a
Func
constructor that lets you specify return types dynamically. Here's an example usage:Such a constructor would be similar, say, to the
List
constructor that lets you explicitly set the type via aType
variable.brian Wed 3 Jun 2009
Promoted to ticket #620 and assigned to brian
Not quite sure about that - I guess we could do something to parameterize a func which wraps another func.
But I'll mark it as a ticket to track it
tompalmer Thu 4 Jun 2009
Mostly what I was thinking. Could be optimized/compressed down to one function in some cases. Not sure. Whatever's easiest (especially if it avoids reflection) would be fine to start with, I think.
By the way, my use case was for my matrix stuff I'm working on. I have a constructor to generate matrix data from a passed in function:
It doesn't work from another matrix, but I figured that the map function (which does work from an existing matrix) could make nice use of this:
That "TODO" part is where I hit this issue.
I'm also willing to believe there will be other use cases for generating functions with dynamically defined types (even though my poor example starting this thread is obviously a bogus case).
Lacking this feature, I could recode this not to reuse the
generate
constructor. More likely I'll have to ignore the matrix type. Alternatively, I might add the explicit type literal for the matrix'sof
, which was decided against forList#map
.brian Sat 11 Jul 2009
Ticket resolved in 1.0.45
Tom,
I added a new
Func.retype
method:Why don't you try it out and see how it works for your use case.
tompalmer Mon 13 Jul 2009
I haven't tried it out, but I don't think it will work for the general case, because you still can't specify a function type given
Type
variables for the args and return type, right? I think your current proposal can already be done like so, anyway, right?My specific use cases, by the way, can be seen at the 'map' and related functions here.
tompalmer Mon 13 Jul 2009
Been off on vacation, by the way.
brian Tue 14 Jul 2009
Use
sys::Type.parameterize
, for example:tompalmer Tue 14 Jul 2009
Thanks. I had missed (or forgotten) that. I might try profiling it. I'm afraid of the speed of using reflective names at the moment.
brian Tue 14 Jul 2009
Type.parameterize
is purely munging of data structures, it is pretty light weight. The heaviest part if creating the map to use an argument which you can cache if you know it ahead of time.tompalmer Tue 14 Jul 2009
Thanks for the info.