Re: RFC 76 (v2) Builtin: reduce
Graham Barr wrote: But what does it do if the block is a curried function of three arguments, but the list only contains two ? Return a curried function of one argument, of course. At least, that's what it *should* do... -- John Porter
Re: RFC 76 (v2) Builtin: reduce
iain truskett wrote: Return a specified value (such as 'undef'). It would allow for more elegant code, I think. The universe is old enough to cope by itself. When I first read this, I thought it said: The universe is old enough to copy itself. !-) -- John Porter
Re: RFC 76 (v2) Builtin: reduce
Nathan Wiger wrote: Since undef() has established semantics, I don't think these should change. I believe taking from RDBMS and adding null() which has the correct NULL semantics is the way it should go. You realize, I hope, that there is no end of different "special non-value" semantics. Perl had one, now you're proposing a second. RDBMS gurus have as many as 29. One step down that path is a bad precedent. undef is sufficient. Let there be operators for implementing the various semantics, NOT new special non-value values. -- John Porter We're building the house of the future together.
Re: RFC 76 (v2) Builtin: reduce
John Porter wrote: Nathan Wiger wrote: Since undef() has established semantics, I don't think these should change. I believe taking from RDBMS and adding null() which has the correct NULL semantics is the way it should go. You realize, I hope, that there is no end of different "special non-value" semantics. Perl had one, now you're proposing a second. RDBMS gurus have as many as 29. One step down that path is a bad precedent. undef is sufficient. Let there be operators for implementing the various semantics, NOT new special non-value values. 29 different, but complete, sets of operators would be required, and you would be restricted to using only one of the "special non-value" values at a time. RDBMS gurus need at least some of their 29 to coexist. Not a solution. -- Glenn = Even if you're on the right track, you'll get run over if you just sit there. -- Will Rogers _NetZero Free Internet Access and Email__ http://www.netzero.net/download/index.html
Re: RFC 76 (v2) Builtin: reduce
Glenn Linderman wrote: Not a solution. Frankly, you haven't demonstrated that there's a problem. -- John Porter
RFC 76 (v2) Builtin: reduce
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Builtin: reduce =head1 VERSION Maintainer: Damian Conway [EMAIL PROTECTED] Date: 10 Aug 2000 Last Modified: 19 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 76 Version: 2 Status: Frozen =head1 ABSTRACT This RFC proposes a builtin Creduce function, modelled after Graham Barr's Creduce subroutine from builtin.pm =head1 DESCRIPTION A new builtin -- Creduce -- is proposed. This function would take an block, subroutine reference, or curried function (hereafter referred to as Ithe reduction subroutine), and call it repeatedly to reduce the remaining arguments (hereafter, referred to as Cthe list). If the reduction subroutine has a prototype, that prototype determines how many items are reduced at a time. If the reduction subroutine is a block or has no prototype, two items are reduced each time. The first call to the reduction subroutine will be passed the first N elements of the list, and subsequent calls will be passed the result of the previous call and the next N-1 elements in the list, until no more elements remain in the list. If fewer than N-1 elements remain on the final call, all the remaining elements are passed. All calls to the reduction subroutine are made in a scalar context. In all cases, the elements of the list are lazily evaluated. That is, any element of the list that is not a literal value is only evaluated when that element is passed to (and actually used by) the reduction subroutine. If the original list has no elements, Creduce immediately throws an exception. If the original list has a single element, that element is immediately returned (without ever calling the reduction subroutine). Otherwise, in a scalar context, the result of the final reduction call is the result returned by Creduce. In a list context, a list of all the interim values, plus the final value, would be returned. If the reduction subroutine is ever terminated by a call to Clast, the enclosing Creduce immediately returns the last reduction value -- or list of partial values -- to that point. If the Clast occurs during the first reduction, an exception is thrown. =head1 EXAMPLES Summation: $sum = reduce {$_[0]+$_[1]} 0, @numbers; $sum = reduce sub{$_[0]+$_[1]}, 0, @numbers; $sum = reduce ^_+^_,0, @numbers; Note that the first element of the list -- zero in this case, 1 in the next example -- represents the default value if the list is empty. Production: $prod = reduce {$_[0]*$_[1]} 1, @numbers; $prod = reduce sub{$_[0]*$_[1]}, 1, @numbers; $prod = reduce ^_*^_,1, @numbers; Minimization: $min = reduce ^x = ^y ? ^x : ^y, @numbers $min = reduce ^x le ^y ? ^x : ^y, @strings Minimization to zero: $min = reduce any(^x,^y)0 last || ^x^y ^x || ^y, @numbers Collection: @triples = @{ reduce sub($;$$$){ [@{shift},[@_] }, [], @singles }; Separation: $sorted = reduce { push @{$_[0][$_[1]%2]}, $_[1]; $_[0] } [[],[]], @numbers; Accumulative sequence generation: @increase = reduce ^value + ^delta, $original, @bonuses; @growth = reduce ^value * ^rate, $principal, @annual_interest_rates; =head1 IMPLEMENTATION Extend Graham's builtin, I'd imagine. =head1 REFERENCES builtin.pm RFC: Higher Order Functions
Re: RFC 76 (v2) Builtin: reduce
On Tue, Sep 19, 2000 at 07:29:56PM -, Perl6 RFC Librarian wrote: =head1 TITLE Builtin: reduce ... Collection: @triples = @{ reduce sub($;$$$){ [@{shift},[@_] }, [], @singles }; You've a typo there, it should be: @triples = @{ reduce sub($;$$$){ [@{shift},[@_]] }, [], @singles }; Separation: $sorted = reduce { push @{$_[0][$_[1]%2]}, $_[1]; $_[0] } [[],[]], @numbers; I don't understand this one. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: RFC 76 (v2) Builtin: reduce
On Tue, Sep 19, 2000 at 07:29:56PM -, Perl6 RFC Librarian wrote: This RFC proposes a builtin Creduce function, modelled after Graham Barr's Creduce subroutine from builtin.pm Please refer to List::Util rather than builtin.pm the module name was changed as many did not like the name builting, as it was not. Graham. In all cases, the elements of the list are lazily evaluated. That is, any element of the list that is not a literal value is only evaluated when that element is passed to (and actually used by) the reduction subroutine. Should lists be lazy by default ? I would suggest that is a separate language issue then reduce and reduce should follow what all other list operators do. If the original list has no elements, Creduce immediately throws an exception. What do you mean by exception, die ? No other builtin dies like that at runtime. Perhaps a return of undef would be more like other operators. If the original list has a single element, that element is immediately returned (without ever calling the reduction subroutine). Otherwise, in a scalar context, the result of the final reduction call is the result returned by Creduce. In a list context, a list of all the interim values, plus the final value, would be returned. Um, if it is returning a list then it is not reducing, is it ? If the reduction subroutine is ever terminated by a call to Clast, the enclosing Creduce immediately returns the last reduction value -- or list of partial values -- to that point. If the Clast occurs during the first reduction, an exception is thrown. Again, no other builting currently throws an exception. If throwing an exception is to become the norm then that should be a separate RFC suggesting that builtins throw exceptions, but reduce should do what others do. Graham.
Re: RFC 76 (v2) Builtin: reduce
* Jonathan Scott Duff ([EMAIL PROTECTED]) [20 Sep 2000 07:15]: On Tue, Sep 19, 2000 at 07:29:56PM -, Perl6 RFC Librarian wrote: =head1 TITLE Builtin: reduce [...] Separation: $sorted = reduce { push @{$_[0][$_[1]%2]}, $_[1]; $_[0] } [[],[]], @numbers; I don't understand this one. $sorted = reduce { push @{ ^0 [ ^1 % 2 ] }, ^1; ^0 }, [[],[]], @numbers; Hence: given an array of two arrays, put odd numbers (i.e. x % 2 == 1) in the second array, and even numbers (i.e. x % 2 == 0) in the first one (the zeroth array). Then return the new (filled out) pair of arrays for the next number. I like it. -- iain truskett, aka Koschei.http://eh.org/~koschei/ You know you are addicted to coffee if... 16 Instant coffee takes too long.
Re: RFC 76 (v2) Builtin: reduce
On Wed, Sep 20, 2000 at 07:31:35AM +1100, iain truskett wrote: * Jonathan Scott Duff ([EMAIL PROTECTED]) [20 Sep 2000 07:15]: On Tue, Sep 19, 2000 at 07:29:56PM -, Perl6 RFC Librarian wrote: =head1 TITLE Builtin: reduce [...] Separation: $sorted = reduce { push @{$_[0][$_[1]%2]}, $_[1]; $_[0] } [[],[]], @numbers; I don't understand this one. $sorted = reduce { push @{ ^0 [ ^1 % 2 ] }, ^1; ^0 }, [[],[]], @numbers; I guess I'm confused with the syntax. Shouldn't there be an - in there? $sorted = reduce { push @{ ^0-[^1%2] }, ^1; ^0 }, [[],[]], @numbers; -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: RFC 76 (v2) Builtin: reduce
On Wed, Sep 20, 2000 at 08:22:38AM +1100, iain truskett wrote: I'd believe so. I think I mentally assumed that Damian was grabbing a syntax trick from another RFC. Heh, I think the exact same thing is what confused me :-) I must say that the ^0, ^1 style notation really makes some expressions much more legible. Indeed. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: RFC 76 (v2) Builtin: reduce
This RFC proposes a builtin Creduce function, modelled after Graham Barr's Creduce subroutine from builtin.pm Please refer to List::Util rather than builtin.pm Noted. Thanks. the module name was changed as many did not like the name builting, as it was not. Bah. I liked it -- I always thought of it as "proactive nominative determinism" ;-) In all cases, the elements of the list are lazily evaluated. That is, any element of the list that is not a literal value is only evaluated when that element is passed to (and actually used by) the reduction subroutine. Should lists be lazy by default ? I would suggest that is a separate language issue then reduce and reduce should follow what all other list operators do. The difference is that I propose that Creduce be able to short-circuit. Other list operators don't, and the proposal they they be allowed to seems to have drowned in its own complexities :-( Perhaps I'll remove that bit and leave it in the hands of the Master Designer. If the original list has no elements, Creduce immediately throws an exception. What do you mean by exception, die ? Yes. No other builtin dies like that at runtime. Perhaps a return of undef would be more like other operators. That was my original proposal, but it was howled down by the mathematical elite, who vigorously insisted that it would break the fundamental mathematical properties of the entire Cosmos, leading to catastrophic rifts in the timespace continuum. Or something like that. Eventually, I gave in. If the original list has a single element, that element is immediately returned (without ever calling the reduction subroutine). Otherwise, in a scalar context, the result of the final reduction call is the result returned by Creduce. In a list context, a list of all the interim values, plus the final value, would be returned. Um, if it is returning a list then it is not reducing, is it ? Sure it is: cumulatively. If the reduction subroutine is ever terminated by a call to Clast, the enclosing Creduce immediately returns the last reduction value -- or list of partial values -- to that point. If the Clast occurs during the first reduction, an exception is thrown. Again, no other builting currently throws an exception. If throwing an exception is to become the norm then that should be a separate RFC suggesting that builtins throw exceptions, but reduce should do what others do. Even at the risk of Destroying the Entire Universe??? What do others think? Damian
Re: RFC 76 (v2) Builtin: reduce
On Wed, Sep 20, 2000 at 08:35:20AM +1100, Damian Conway wrote: No other builtin dies like that at runtime. Perhaps a return of undef would be more like other operators. That was my original proposal, but it was howled down by the mathematical elite, who vigorously insisted that it would break the fundamental mathematical properties of the entire Cosmos, leading to catastrophic rifts in the timespace continuum. Or something like that. Eventually, I gave in. Well mathematitions need to learn that not everything works in a mathematical way. Some things are just chaotic by nature. If the reduction subroutine is ever terminated by a call to Clast, the enclosing Creduce immediately returns the last reduction value -- or list of partial values -- to that point. If the Clast occurs during the first reduction, an exception is thrown. Again, no other builting currently throws an exception. If throwing an exception is to become the norm then that should be a separate RFC suggesting that builtins throw exceptions, but reduce should do what others do. Even at the risk of Destroying the Entire Universe??? What do others think? Ask me again tomorrow, I might change my mind :) Graham.
Re: RFC 76 (v2) Builtin: reduce
Even at the risk of Destroying the Entire Universe??? What do others think? I dunno, seems awfully extreme. Returning undef and testing with "|| die" seems sufficient to me... $sum = reduce {$_[0]+$_[1]} 0, @numbers || die "Chaos!!"; Note with the || that way, it'll die immediately if @numbers is empty, even before destroying the universe. If a person isn't checking values, they deserve what they get, IMO... -Nate
Re: RFC 76 (v2) Builtin: reduce
$sum = reduce {$_[0]+$_[1]} 0, @numbers || die "Chaos!!"; Note with the || that way, it'll die immediately if @numbers is empty, even before destroying the universe. Yes, but why are you passing the size of the array in there? --tom
Re: RFC 76 (v2) Builtin: reduce
Tom Christiansen wrote: $sum = reduce {$_[0]+$_[1]} 0, @numbers || die "Chaos!!"; Note with the || that way, it'll die immediately if @numbers is empty, even before destroying the universe. Yes, but why are you passing the size of the array in there? 'Cause I'm an idiot, apparently... $sum = reduce {$_[0]+$_[1]} 0, @numbers or die "Chaos!!"; That's better, assuming reduce() returns undef. I'm gonna stop writing examples in emails because I always screw them up... -Nate
Re: RFC 76 (v2) Builtin: reduce
$sum = reduce {$_[0]+$_[1]} 0, @numbers || die "Chaos!!"; Note with the || that way, it'll die immediately if @numbers is empty, even before destroying the universe. Yes, but why are you passing the size of the array in there? :-) And even if you wrote: $sum = reduce(^_+^_, @numbers) || die "Chaos!!"; you're still going to over-react to a zero-sum sequence. You need: defined($sum = reduce ^_+^_, @numbers) || die "Chaos!!"; Damian
Re: RFC 76 (v2) Builtin: reduce
Why not just check @numbers? --tom
Re: RFC 76 (v2) Builtin: reduce
Tom suggested: Why not just check @numbers? Hear, hear: $sum = @numbers ? reduce ^_+^_, @numbers : 0; Moreover, I suspect that the usual idiom will be: $result = reduce $reducer, $default, @list; That is: $sum = reduce ^_+^_, 0, @numbers; in which case the "empty list" exception never raises (ahem) its ugly head. I think the consensus is still that reducing an empty list shall throw an exception. Damian
Re: RFC 76 (v2) Builtin: reduce
"Perl6" == Perl6 RFC Librarian [EMAIL PROTECTED] writes: Perl6 If the reduction subroutine has a prototype, that prototype Perl6 determines how many items are reduced at a time. If the reduction subroutine Perl6 is a block or has no prototype, two items are reduced each time. ... is inconsistent with ... Perl6 If the original list has no elements, Creduce immediately throws an Perl6 exception. If the original list has a single element, that element is Perl6 immediately returned (without ever calling the reduction subroutine). Can we resolve this? That second paragraph doesn't take into account what happens when I give 3 elements to a 7-element-at-a-time reduction formula. -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 [EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/ Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
Re: RFC 76 (v2) Builtin: reduce
On Tue, Sep 19, 2000 at 04:06:00PM -0600, Tom Christiansen wrote: Why not just check @numbers? Well if the 'use trisate' pragma ever arises (did anyone RFC that ?) $a = 1; $b = undef; $c = $a + $b; $c is undef, not 1. Graham.
Re: RFC 76 (v2) Builtin: reduce
Graham Barr wrote: On Tue, Sep 19, 2000 at 04:06:00PM -0600, Tom Christiansen wrote: Why not just check @numbers? Well if the 'use trisate' pragma ever arises (did anyone RFC that ?) Following Glenn's lead, I'm in the process of RFC'ing a new null() keyword and value that will do this: $a = 1; $b = null; $c = $a + $b; $c is null, not 1. Since undef() has established semantics, I don't think these should change. I believe taking from RDBMS and adding null() which has the correct NULL semantics is the way it should go. One thing I'll add is the posibility to decide whether you want your variables initialized to undef() or null(): use initialize 'null'; Or something like that. Easy integration of DBI here we come... (hopefully) :-) -Nate
Re: RFC 76 (v2) Builtin: reduce
At 04:57 PM 9/19/00 -0700, Nathan Wiger wrote: Following Glenn's lead, I'm in the process of RFC'ing a new null() keyword and value that will do this: $a = 1; $b = null; $c = $a + $b; $c is null, not 1. Since undef() has established semantics, I don't think these should change. I believe taking from RDBMS and adding null() which has the correct NULL semantics is the way it should go. One thing I'll add is the posibility to decide whether you want your variables initialized to undef() or null(): use initialize 'null'; Or something like that. Easy integration of DBI here we come... (hopefully) :-) What DBI integration does this facilitate? SQL uses NULL to denote a missing table entry. It's outside the domains of numbers, strings, BLOBs, CLOBs, and everything else RDBMSes use. So is undef in Perl. The two appear made for each other. I've got DBI modules that translate NULL to undef and vice versa and everything works fine. Why do you want to be able to reproduce the NULL propagating in SQL expressions in Perl? I cannot think of a use. I can think of plenty of confusion caused by a 'null' keyword, which is why I thank Larry et al daily that they didn't put one in Perl. Who else is tired of conversations like "... the null string - and by that I mean an empty string, not a string containing the NUL character, although of course an empty string actually is terminated by the NUL character, but you don't put it in..." -- Peter Scott Pacific Systems Design Technologies
Re: RFC 76 (v2) Builtin: reduce
Following Glenn's lead, I'm in the process of RFC'ing a new null() keyword and value As though one were not already drowning in a surfeit of subtly dissimilar false values. --tom
Re: RFC 76 (v2) Builtin: reduce
$sum = @numbers ? reduce ^_+^_, @numbers : 0; Although we're back to the pain of what happens when @numbers is really fn(). This is unsatisfactorily nonidempotent (aliapotent? :-) $sum = fn() ? reduce ^_+^_, fn() : 0; It would seem likely that most would trade space for time and avoid the second call to fn() with: my @values = fn(); $sum = @values ? reduce ^_+^_, @values : 0; In any case, the preferred option should be to provide a default value: $sum = reduce ^_+^_, 0, @values; which is always cleaner *and* shorter. :-) Damian
Re: RFC 76 (v2) Builtin: reduce
In any case, the preferred option should be to provide a default value: $sum = reduce ^_+^_, 0, @values; which is always cleaner *and* shorter. :-) Ummm...Maybe I'm missing something, but how does reduce() know the difference between $sum = reduce ^_+^_, 0, @values; unshift @values, 0; $sum = reduce ^_+^_, @values; $sum = reduce ^_+^_, 0, 1, 2, 3, 4, 5; Is this just a prototyping issue? And if so, any reason not to make 0 the default value by default? I'm still uneasy about the throwing exception thing, in case you can't tell... -Nate
Re: RFC 76 (v2) Builtin: reduce
Ummm...Maybe I'm missing something, but how does reduce() know the difference between $sum = reduce ^_+^_, 0, @values; unshift @values, 0; $sum = reduce ^_+^_, @values; You know, I really find it much more legible to consistently write these sorts of thing with braces around their code block, just as @x = map { $_ * 3 }, 4, 5; is infinitely better than @x = map $_ * 3, 4, 5; --tom
Re: RFC 76 (v2) Builtin: reduce
On Tue, Sep 19, 2000 at 08:14:24PM -0600, Tom Christiansen wrote: Following Glenn's lead, I'm in the process of RFC'ing a new null() keyword and value As though one were not already drowning in a surfeit of subtly dissimilar false values. Hear, hear. Three-valued logic is enough. Make it four-valued, and my head is going to explode. - Damien