digitalmars.D - lazy evals + parameter passing
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= (31/31) Sep 04 2006 Hi, I've been away for a while working with Ruby.
- Chris Nicholson-Sauls (22/65) Sep 04 2006 First, D's interesting new Lazy feature is really not like Ruby's Block ...
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= (9/49) Sep 04 2006 I guess this has been discussed before, but I'm still curious - why are
Hi, I've been away for a while working with Ruby. It seems the D spec is now extended with lazy evaluation of function arguments. Very nice indeed. I tried to search the ng but haven't seen any mention about 'yield' in the context of lazy evals. Currently I think the implementation is only half ready or then I've forgotten how to program in D :) See, some Ruby here def inject(list, n) list.each { |v| n = yield(n, v) } return n end def sum(list) return inject(list, 0) { |n, v| n + v } end sum( [1,2,3] ) => 6 If I understand this correctly, currently D only supports yield's without arguments when used with anonymous delegates (Ok, it's lacking multiple return values too, but those can be simulated easily). The point is that the caller _can_ actually send parameters to the delegate, but there's no way to receive arguments from the sender. Is it too expensive to extend current lazy evals with arguments in a systems programming language like D? Does it even require the use of tuples? I think it's fully possible by introducing |par1, ..., parn | syntax so that { | a, b | a+b } would be the same as int _anonymous(inout a, inout b) { return a+b; } What do you think? Does it look ugly? Doesn't it offer a great deal of new functionality. I think we really NEED this - please Walter, make it pre-1.0 :)
Sep 04 2006
Jari-Matti Mäkelä wrote:Hi, I've been away for a while working with Ruby. It seems the D spec is now extended with lazy evaluation of function arguments. Very nice indeed. I tried to search the ng but haven't seen any mention about 'yield' in the context of lazy evals. Currently I think the implementation is only half ready or then I've forgotten how to program in D :) See, some Ruby here def inject(list, n) list.each { |v| n = yield(n, v) } return n end def sum(list) return inject(list, 0) { |n, v| n + v } end sum( [1,2,3] ) => 6 If I understand this correctly, currently D only supports yield's without arguments when used with anonymous delegates (Ok, it's lacking multiple return values too, but those can be simulated easily). The point is that the caller _can_ actually send parameters to the delegate, but there's no way to receive arguments from the sender. Is it too expensive to extend current lazy evals with arguments in a systems programming language like D? Does it even require the use of tuples? I think it's fully possible by introducing |par1, ..., parn | syntax so that { | a, b | a+b } would be the same as int _anonymous(inout a, inout b) { return a+b; } What do you think? Does it look ugly? Doesn't it offer a great deal of new functionality. I think we really NEED this - please Walter, make it pre-1.0 :)First, D's interesting new Lazy feature is really not like Ruby's Block feature at all -- although I for one wouldn't mind seeing something like yielding show up in D. Instead, Lazy is primarily about affirming that an expression will not be evaluated until it is neccessary to do so. In other words, that you could for example pass a complicated string expression to a function which MAY or MAY NOT output that string somewhere. Lazy evaluation promises you that the string won't get processed unless that function DOES output it. That noted, of course, they do behave essentially as delegates (and internally ARE delegates I believe) and so the given expression MAY be evaluated multiple times. One would have to note the documentation for the function in question before relying on or protecting against any side effects. Second, the new anonymous delegate syntax already gives us more-or-less what you want except for two missing items: a delegate body containing nothing but an expression should get an implicit 'return ... ;' wrapped around it, yielding capability. { | a, b | a + b } is actually (a,b){ a + b } I'm also not positive if type inferance would handle this case or not, so it may more correctly be: (int a, int b){ a + b } -- Chris Nicholson-Sauls
Sep 04 2006
Chris Nicholson-Sauls wrote:Jari-Matti Mäkelä wrote:No, but it's pretty near.I think it's fully possible by introducing |par1, ..., parn | syntax so that { | a, b | a+b } would be the same as int _anonymous(inout a, inout b) { return a+b; } What do you think? Does it look ugly? Doesn't it offer a great deal of new functionality. I think we really NEED this - please Walter, make it pre-1.0 :)First, D's interesting new Lazy feature is really not like Ruby's Block feature at allInstead, Lazy is primarily about affirming that an expression will not be evaluated until it is neccessary to do so. In other words, that you could for example pass a complicated string expression to a function which MAY or MAY NOT output that string somewhere. Lazy evaluation promises you that the string won't get processed unless that function DOES output it.That noted, of course, they do behave essentially as delegates (and internally ARE delegates I believe) and so the given expression MAY be evaluated multiple times. One would have to note the documentation for the function in question before relying on or protecting against any side effects.I guess this has been discussed before, but I'm still curious - why are they separate? Is it because there is no syntax for parameter passing or does it cause extra overhead to support full features of delegates when only a small subset is mostly needed?Second, the new anonymous delegate syntax already gives us more-or-less what you want except for two missing items: a delegate body containing nothing but an expression should get an implicit 'return ... ;' wrapped around it, yielding capability. { | a, b | a + b } is actually (a,b){ a + b }Ah, thanks. It was a bit hidden in the docs but now I found it. This feature really rocks.I'm also not positive if type inferance would handle this case or not, so it may more correctly be: (int a, int b){ a + b }This one works.
Sep 04 2006