Re: Continuations
On Wed, 06 Nov 2002 10:38:45 +1100, Damian Conway wrote: > Luke Palmer wrote: > > I just need a little clarification about yield(). > > C is exactly like a C, except that when you > call the subroutine next time, it resumes from after the C. > > > how do you tell the difference between a > > recursive call and fetching the next element? How would you maintain > > two iterators into the same array? > > The re-entry point isn't stored in the subroutine itself. It's stored > (indexed by optree node) in the current subroutine call frame. Which, > of course, is preserved when recursive iterator invocations recursively > yield. So to get the same yield context, each call to the coroutine has to be from the same calling frame. If you want to get several values from the same coroutine, but from different calling contexts, can you avoid the need to wrap it in a closure? sub iterate(@foo){ yield $_ for @foo; undef; } # There's probably some perl5/6 confusion here sub consume(@bar){ my $next = sub{ iterate(@bar); }; while $_ = $next() { do_stuff($_,$next); } } sub do_stuff($val,$next){ ... if $val ~~ something_or_other() { my $quux = $next(); ... } } -- Peter Haworth [EMAIL PROTECTED] "...I find myself wondering if Larry Ellison and Tim Curry were separated at birth...hmm..." -- Tom Good
Re: Superpositions and laziness
Damian Conway <[EMAIL PROTECTED]> writes: > Luke Palmer wrote: > > >> sub a_pure_func(Num $n) returns Num { >> class is Num { >> method FETCH { $n * $n } }.new } >> Yes? No? > > Not quite. > > > > sub a_pure_func(Num $n) returns Num { > > class is Num { > > has Num $cache; > > method FETCH { $cache //= $n * $n } } } > > > Still not quite. > > You don't want a C method (which won't be called unless the > object somehow becomes the implementation of a tied variable). > > What you want are conversion-to-(num|str|bool) methods: > >sub a_pure_func(Num $n) returns Num { >class is Num { >has Num $cache; >sub value { $n * $n } >method operator:+ ($self:) { +($cache //= value ) } >method operator:~ ($self:) { ~($cache //= value ) } >method operator:? ($self:) { ?($cache //= value ) } >}.new >} So, we'd have 'is lazy' do something like the following to the declared sub? sub make_lazy(&func) { my $new_func = { &func.returns.make_deferred_object( &func, *@_ } }; $new_func.signature(&func.signature); return $new_func; } And then, say: class Object { method make_deferred_object($class is Class : &func, *@args) { class is $class { has $class $cache; sub value { &func(*@args) } method operator:+ { +($cache //= value) } method operator:~ { ~($cache //= value) } method operator:? { ?($cache //= value) } }.new } } Which is somewhat dependent on being able to do C. If that's not possible then I'd hope you could do something like: given my $anon_class = Class.new { my $cache; .isa($class); .add_sub'value' => { &func(*@args) } .add_method 'operator:+' => {...} .add_method 'operator:~' => {...} .add_method 'operator:?' => {...} return .new; } Hang on, couldn't you rewrite things to not use the cache? class is $class { sub value { &func(*@args) } method operator:+ ($self is rw:) { +($self = value) } method operator:~ ($self is rw:) { ~($self = value) } method operator:? ($self is rw:) { ?($self = value) } }.new I don't know if I hope that works or hope it fails miserably. Also note that, if you were feeling sufficiently lazy with numbers, you could define the set of binary operators for your deferred numbers: method operator:+ ($self: Num $other) is lazy { +($self) + $other } method operator:* ($self: Num $other) is lazy { +($self) * $other } method operator:/ ($self: Num $other) is lazy { +($self) / $other } method operator:- ($self: Num $other) is lazy { +($self) - $other } Or would that just be evil, Bad And Wrong? -- Piers "It is a truth universally acknowledged that a language in possession of a rich syntax must be in need of a rewrite." -- Jane Austen?
Re: Superpositions and laziness
Michael Lazzaro <[EMAIL PROTECTED]> writes: > On Friday, November 8, 2002, at 07:03 AM, Adam D. Lopresto wrote: >> I still prefer "cached", which sounds less lingo-ish than "memoized" >> but reads >> better than "same" ("Same as what?"). > > Insert obligatory reference to Eiffel here, which IIR uses the word > "once": > > sub square ( Num $n ) is same { ... } > sub square ( Num $n ) is pure { ... } > sub square ( Num $n ) is once { ... } > sub square ( Num $n ) is cached { ... } > sub square ( Num $n ) is memoized { ... } Having said I prefer 'pure', on further consideration I like cached, but I think there's still a place for 'pure', but probably not as a core property. -- Piers "It is a truth universally acknowledged that a language in possession of a rich syntax must be in need of a rewrite." -- Jane Austen?
Re: Superpositions and laziness
[ I've added some of Damian's text back into Michael's message to save replying to two separate messages. ] On Mon, Nov 11, 2002 at 09:44:37AM -0800, Michael Lazzaro wrote: > On Monday, November 11, 2002, at 02:19 AM, Damian Conway wrote: > > I can certainly see your point, but to me this is disquieteningly > > reminiscent of the horror that is C in C++ methods. Because, Yes, there are those overtones. You can never retrofit purity. > > if you're serious about C meaning "pure" in the mathematical > > sense, then C subs can't access globals or C, can't > > have C parameters, and call non-C subroutines. Yes, unless "pure" really means "pure enough". > > One of the reasons I like C is because it does specify > > exactly the way the subroutine is to behave (i.e. be called the > > first time, and not called every subsequent time the same arguments > > are supplied). So I can do nasty^H^H^H^H^Hhandy things like giving > > the sub side-effects, in the sure knowledge that they won't be > > invoked more than once. I think I agree that if you want to give perl a hint about how to optimise your program, and you want to specify that the results of calling a function should be cached, then "cached" seems the best way to do that. > > With C I can never be sure what optimizations the compiler is > > or isn't going to make, or even whether those optimzations will be > > the same from platform to platform [*]. So I can never be sure what > > the precise behaviour of my sub will be. :-( I would say that would be the whole point of "pure". If you declare a function to be "pure" (and you're telling the truth), then when and how often that function is called should have no bearing on the output of the program, except maybe for when it appears. The function could be cached, optimised away, farmed out to one of the 63 processors you're not using or be optimised in any number of helpful ways. Having said all that, I'm not overly wedded to the idea. It seems useful, but so does actually specifying "cached". I'm not convinced that either has to be a part of the core language to be useful. In fact, I only poked my head up because I knew the answer to Nick's question :-) > Amen. The more abstract or metaphorical the name, the more difficult > it is to be really sure of what it does. Of the choices, "cached" > seems by far the most self-explanatory. If we used "pure", we'd have > to teach people what "pure" means, which would be much harder than > teaching them what "cached" means. A "pure" function may be run zero, one or more times every time you call it. And every time you don't. ;-) [ I notice that Piers has just said about the same as me in one sentence. ] -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
Re: Superpositions and laziness
Paul Johnson <[EMAIL PROTECTED]> writes: > [ I notice that Piers has just said about the same as me in one sentence. ] Ah, but I get lots of practice boiling stuff down when I'm writing the summaries. Though the current one is still giving me headaches -- I'm about halfway through perl6-language and I've not even started on perl6-documentation. -- Piers "It is a truth universally acknowledged that a language in possession of a rich syntax must be in need of a rewrite." -- Jane Austen?