Re: RFC 76 (v1) Builtin: reduce
Lightning flashed, thunder crashed and "Ed Mills" [EMAIL PROTECTED] whispe red: | So we establish a var $something=n where n is the array origin. You mean something like $[, which we've had for many, many years. And which for many, many years we've discouraged the use of? $[ The index of the first element in an array, and of the first character in a substring. Default is 0, but you could theoretically set it to 1 to make Perl behave more like awk (or Fortran) when subscripting and when evaluating the index() and substr() functions. (Mnemonic: [ begins subscripts.) As of release 5 of Perl, assignment to `$[' is treated as a compiler directive, and cannot influence the behavior of any other file. Its use is highly discouraged. Please, let's not. It was more confusing than it was worth the first time. -spp
Re: RFC 76 (v1) Builtin: reduce
Damian Conway wrote: But ^1, ^2, etc. have *nothing* to do with $1, $2, except analogically. And I'm removing that analogy from the next version of the RFC! ;-) They have *everything* to do with $_[0], $_[1], $_[2], etc. I realize this, but I don't think most people will see it that way. I see the analogy part much more clearly. Having ^1 and $1 be the same makes a lot more sense than having $1 and ^0 both be the start. Why? Consistency is key. With arrays, people understand that [0] is the first element because they're dealing with a computer. But with regexps (and HOFN), we're now into stuff that's good for humans. And the "First" element should be "^1", just like for regexps. Unless you want to start telling people that the "Zeroeth" element is "^0". But having the "First" element be "0" makes *no* sense. Not for humans. It never has. In fact, every kind of indexing in Perl -- *except* $1, $2, etc. -- starts at zero. Fixing $0's semantics would be far more consistent than breaking ^0. That's fine too - if we want to do this, let's! Honestly. I say: 1. Make $ARGV[0] have the program name 2. Make $0 be the first regexp match But I see two problems with this: 1. Now "for (@ARGV) breaks" 2. The "first" argument is now "0" again Please! Make the "first" be ^1. It's more consistent and makes more sense for us humans. We're not "breaking ^0" either - it doesn't exist yet. Rather, we're fixing it before the bug hits the customer. I guarantee you this will be a common mistake, I've done tons of work in real-life user-interface testing. Users see *simple* analogies, not deep ones ("^1 like $1, the first one") If I ask you to count to ten, which number do you start with? -Nate
Re: RFC 76 (v1) Builtin: reduce
Making 0 the first element makes as much sense as 1- just a convention. However there is precedence for letting the user decide. Does anyone else remember )ORIGIN 1 ? So we establish a var $something=n where n is the array origin. I don't think I'd ever use it personally, having been a c "kinder", but I don't presume to thinkk like everyone else and others may be more strongly fixated on another origin. From: Nathan Wiger [EMAIL PROTECTED] To: [EMAIL PROTECTED] CC: [EMAIL PROTECTED], Glenn Linderman [EMAIL PROTECTED] Subject: Re: RFC 76 (v1) Builtin: reduce Date: Sun, 27 Aug 2000 19:02:25 -0700 Damian Conway wrote: But ^1, ^2, etc. have *nothing* to do with $1, $2, except analogically. And I'm removing that analogy from the next version of the RFC! ;-) They have *everything* to do with $_[0], $_[1], $_[2], etc. I realize this, but I don't think most people will see it that way. I see the analogy part much more clearly. Having ^1 and $1 be the same makes a lot more sense than having $1 and ^0 both be the start. Why? Consistency is key. With arrays, people understand that [0] is the first element because they're dealing with a computer. But with regexps (and HOFN), we're now into stuff that's good for humans. And the "First" element should be "^1", just like for regexps. Unless you want to start telling people that the "Zeroeth" element is "^0". But having the "First" element be "0" makes *no* sense. Not for humans. It never has. In fact, every kind of indexing in Perl -- *except* $1, $2, etc. -- starts at zero. Fixing $0's semantics would be far more consistent than breaking ^0. That's fine too - if we want to do this, let's! Honestly. I say: 1. Make $ARGV[0] have the program name 2. Make $0 be the first regexp match But I see two problems with this: 1. Now "for (@ARGV) breaks" 2. The "first" argument is now "0" again Please! Make the "first" be ^1. It's more consistent and makes more sense for us humans. We're not "breaking ^0" either - it doesn't exist yet. Rather, we're fixing it before the bug hits the customer. I guarantee you this will be a common mistake, I've done tons of work in real-life user-interface testing. Users see *simple* analogies, not deep ones ("^1 like $1, the first one") If I ask you to count to ten, which number do you start with? -Nate _ Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com. Share information about yourself, create your own public profile at http://profiles.msn.com.
Re: RFC 76 (v1) Builtin: reduce
Bart Lateur wrote: On Thu, 17 Aug 2000 07:44:03 +1000, Jeremy Howard wrote: $a and $b were done for speed: quicker to set up those global variables than to pass values through the stack. The solution is to pass args in as $_[0] and $_[1]. sort { $_[0] = $_[1] } @list is very ugly. I *like* the syntax of sort { $a = $b } @list My original post actually said that the reason for this is that you can then write: sort { ^0 = ^1 } @list; ...which is pretty Perlish.
Re: RFC 76 (v1) Builtin: reduce
Still, sort { $_[0] = $_[1] } @list is very ugly. Hence: sort ^a = ^b, @list; Damian
Re: RFC 76 (v1) Builtin: reduce
Array and placeholder indices both start at *zero*! Array and placeholder indices both start at *zero*! Array and placeholder indices both start at *zero*! Array and placeholder indices both start at *zero*! - Original Message - From: "Damian Conway" [EMAIL PROTECTED] To: "Jarkko Hietaniemi" [EMAIL PROTECTED]; "Larry Wall" [EMAIL PROTECTED]; "Jeremy Howard" [EMAIL PROTECTED] Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED] Sent: Saturday, August 19, 2000 3:22 PM Subject: Re: RFC 76 (v1) Builtin: reduce Except that Perl 6 people will know all about numbered parameters, so they will write: @out = sort ^2 cmp ^1, @in; and it will work just as they expect! As long as they expect it to fail miserably! :-( Now, go home and write it out 100 times: "Array and placeholder indices both start at *zero*!" Damian
Re: RFC 76 (v1) Builtin: reduce
Now, go home and write it out 100 times: "Array and placeholder indices both start at *zero*!" Array and placeholder indices both start at *zero*! Array and placeholder indices both start at *zero*! Array and placeholder indices both start at *zero*! Array and placeholder indices both start at *zero*! Cunning devil. Base 2! Damian
Re: RFC 76 (v1) Builtin: reduce
I think this does the right thing too: @out = sort ^0 cmp ^a, @in; Since numbered placeholders have higher priority than named, it should create the function sub ($, $a) { $_[0] cmp $_[1] } When the curry is evaluated, the a: parameter is bound to $_[1] and the b: parameter fills in $_[0]. Yes. If this code is used instead: @out = sort ^1 cmp ^a, @in; Then a different function would be generated: sub ($a, $) { $_[1] cmp $_[0] } But the code still works. Yes. That's kind of interesting -- the numbered placeholders define the ordering for the parameters passed anonymously, while the named placeholders define ordering for the parameters passed by keyword. I keep feeling like there's something here to trip on, but I can't find it. Well, this: @out = sort ^a cmp ^0, @in; fails very badly (but could generate a "parameter $b not used in call to curried expression" warning under Cuse strict 'parameters'). Also: @out = sort ^z cmp ^a, @in; is counterintuitive (but would also generate a warning) And both: @out = sort ^l cmp ^0, @in; and @out = sort ^1 cmp ^O, @in; are very nasty in a sans serif font :-) P.S. What the heck kind of sort is that?! O(N**3) random permutation sort? Yup. Don't you just love it?! :-)
Re: RFC 76 (v1) Builtin: reduce
Larry pointed out: Yes, but has anyone pointed out that @out = sort ^b cmp ^a, @in; won't do what people will certainly think it ought to? It *will*, if Csort *names* the two values it passes to the comparator! E.g.: sub sort (^comparator, @list) { for (1..@list**3) { my ($i, $j) = (rand(@list), rand(@list)); @list[$i,$j] = @list[$j,$i] unless $comparator-(a: $list[$i], b: $list[$j]); } return @list; } (And now you know why I never fill in the IMPLEMENTATION section ;-) Damian
Re: RFC 76 (v1) Builtin: reduce
Larry Wall wrote: Jarkko Hietaniemi writes: : (Yes, there is a small aesthetic edge in using $a vs $_[0], but I still : consider the $ and $b to be warts.) : : And anyhow, this will work just fine (see RFC 23): : :$sum = reduce ^a + ^b, @numbers; : : I have been amply reminded of this, thanks :-) (Too little time : to spend on RFCs...) Yes, but has anyone pointed out that @out = sort ^b cmp ^a, @in; won't do what people will certainly think it ought to? Except that Perl 6 people will know all about numbered parameters, so they will write: @out = sort ^2 cmp ^1, @in; and it will work just as they expect! (See RFC 23 for information about how numbered, named, and anonymous placeholders get filled in).
Re: RFC 76 (v1) Builtin: reduce
Clever, and really obscure; wouldn't this then require that _everyone_ that writes a curried expression for the sort sub use ^a ^b, and that everyone writing a non-curried sort sub name their parameters a and b? I guess that wouldn't necessarily be bad, but it would be restrictive. Damian Conway wrote: Larry pointed out: Yes, but has anyone pointed out that @out = sort ^b cmp ^a, @in; won't do what people will certainly think it ought to? It *will*, if Csort *names* the two values it passes to the comparator! E.g.: sub sort (^comparator, @list) { for (1..@list**3) { my ($i, $j) = (rand(@list), rand(@list)); @list[$i,$j] = @list[$j,$i] unless $comparator-(a: $list[$i], b: $list[$j]); } return @list; } (And now you know why I never fill in the IMPLEMENTATION section ;-) Damian -- Glenn = There are two kinds of people, those who finish what they start, and so on... -- Robert Byrne ___ Why pay for something you could get for free? NetZero provides FREE Internet Access and Email http://www.netzero.net/download/index.html
Re: RFC 76 (v1) Builtin: reduce
Except that Perl 6 people will know all about numbered parameters, so they will write: @out = sort ^2 cmp ^1, @in; and it will work just as they expect! As long as they expect it to fail miserably! :-( Now, go home and write it out 100 times: "Array and placeholder indices both start at *zero*!" Damian
Re: RFC 76 (v1) Builtin: reduce
Damian Conway wrote: Clever, and really obscure; "Invisible", rather than "obscure", I would say. DWIMity of the first order. :-) wouldn't this then require that _everyone_ that writes a curried expression for the sort sub use ^a ^b, and that everyone writing a non-curried sort sub name their parameters a and b? No, that's the lovely part. If you use positional placeholders or the anonymous placeholder, the resulting curried function has *unnamed* parameters, so the *order* of the arguments passed by Csort is all that matters. So that's what I missed, that you expect named actual parameters to be legally passable to subs with unnamed formal parameters. I would consider that inappropriate, needing at least a warning. If people want to use named parameters with a sub with unnamed formal parameters, they should curry a wrapper. So all of these work as expected (as a consequence of the standard semantics of named parameters): @sorted = sort ^b = ^a, @list;# reverse sort @sorted = sort ^1 = ^0, @list;# reverse sort I note your use of ^0 and ^1 where I and another poster both used ^1 ^2. I wonder how many people will have to learn about ^0 if you implement it as a positional placeholder. Note that regexp produces $1, $2 ..., not $0. And people really do count from 1, until they've been indoctinated that computer arrays start at 0. But placeholders are not an array. @sorted = sort ^_ = ^_, @list;# normal sort @sorted = sort {$_[1] = $_[0]}, @list;# reverse sort @sorted = sort sub{$_[1] = $_[0]}, @list; # reverse sort The only case that traps the unwary is: @sorted = sort ^y = ^x, @list;# normal sort! But I don't think Larry was worried about that -- just about the inevitable resonances with the late unlamented $a and $b. Damian -- Glenn = There are two kinds of people, those who finish what they start, and so on... -- Robert Byrne _NetZero Free Internet Access and Email__ http://www.netzero.net/download/index.html
Re: RFC 76 (v1) Builtin: reduce
So that's what I missed, that you expect named actual parameters to be legally passable to subs with unnamed formal parameters. I would consider that inappropriate, needing at least a warning. Perhaps under: use strict 'parameters'; If people want to use named parameters with a sub with unnamed formal parameters, they should curry a wrapper. Which Csort could, of course, also do (if it was decided that bully-boy, fascist named parameters were the more appropriate default ;-). I note your use of ^0 and ^1 where I and another poster both used ^1 ^2. I wonder how many people will have to learn about ^0 if you implement it as a positional placeholder. Note that regexp produces $1, $2 ..., not $0. And people really do count from 1, until they've been indoctinated that computer arrays start at 0. But placeholders are not an array. No indeed. They are short-hand for indexing operations into an array (@_). And array indices *do* start from zero. In contexts like this (and others such as Cgrep) the omission of ^0 from a comparator would surely evoke a diagnostic. Damian
Re: RFC 76 (v1) Builtin: reduce
Nathan Torkington [EMAIL PROTECTED] writes: Piers Cawley writes: The $a and $b of the sort comparator were A Bad Idea to begin with. Ditto. Can we ditch these in Perl 6? Don't see why $_[0] and $_[1] can't be used, or even a more standard $1 and $2. Either one makes it more obvious what's being operated on. $1 $2 could be somewhat dangerous in a sub that might have regexen in it... $1 and $2 are a poor choice because of regexps. $a and $b were done for speed: quicker to set up those global variables than to pass values through the stack. The documentation for perl5's sort function says that passing as arguments is considerably slower. I don't think you can handwave and say "oh, that's an implementation detail". I think it's an implementation detail that's bloody hard to fix, especially for things like code references passed to sort: sort $some_ref @unordered Perl can't do anything at compile-time to tell sort where lexicals in the sort sub are. Then it doesn't have to. But if the sub is explicitly specified (maybe according to the easy-closure RFCs) then it *can* do it efficiently. In most cases I've seen, when a complex order criterion is used sort gets passed Csort {complex_criterion($a,$b)} @list, so we're saving little. Document that if you're "too clever" then you lose speed (for a suitable value of "too clever"). But at least make the simple cases easy. So I don't have a solution, I just have more detail on the problem. -- Ariel "Glad I'm on -language and not on -internals" Scolnicov
Re: RFC 76 (v1) Builtin: reduce
Nathan Wiger [EMAIL PROTECTED] writes: Jarkko Hietaniemi wrote: The $a and $b of the sort comparator were A Bad Idea to begin with. Ditto. Can we ditch these in Perl 6? Don't see why $_[0] and $_[1] can't be used, or even a more standard $1 and $2. Either one makes it more obvious what's being operated on. $1 $2 could be somewhat dangerous in a sub that might have regexen in it...
Re: RFC 76 (v1) Builtin: reduce
Piers Cawley writes: The $a and $b of the sort comparator were A Bad Idea to begin with. Ditto. Can we ditch these in Perl 6? Don't see why $_[0] and $_[1] can't be used, or even a more standard $1 and $2. Either one makes it more obvious what's being operated on. $1 $2 could be somewhat dangerous in a sub that might have regexen in it... $1 and $2 are a poor choice because of regexps. $a and $b were done for speed: quicker to set up those global variables than to pass values through the stack. The documentation for perl5's sort function says that passing as arguments is considerably slower. I don't think you can handwave and say "oh, that's an implementation detail". I think it's an implementation detail that's bloody hard to fix, especially for things like code references passed to sort: sort $some_ref @unordered Perl can't do anything at compile-time to tell sort where lexicals in the sort sub are. So I don't have a solution, I just have more detail on the problem. Nat
Re: RFC 76 (v1) Builtin: reduce
Nathan Torkington wrote: Piers Cawley writes: The $a and $b of the sort comparator were A Bad Idea to begin with. Ditto. Can we ditch these in Perl 6? Don't see why $_[0] and $_[1] can't be used, or even a more standard $1 and $2. Either one makes it more obvious what's being operated on. $1 $2 could be somewhat dangerous in a sub that might have regexen in it... $1 and $2 are a poor choice because of regexps. $a and $b were done for speed: quicker to set up those global variables than to pass values through the stack. The documentation for perl5's sort function says that passing as arguments is considerably slower. I don't think you can handwave and say "oh, that's an implementation detail". I think it's an implementation detail that's bloody hard to fix, especially for things like code references passed to sort: sort $some_ref @unordered Perl can't do anything at compile-time to tell sort where lexicals in the sort sub are. So I don't have a solution, I just have more detail on the problem. The solution is to pass args in as $_[0] and $_[1]. Using higher-order function notation allows these args to be named however you like: sort ^left cmp ^right, @list; sort ^1 cmp ^2, @list; sort ^_ cmp ^_, @list;
Re: RFC 76 (v1) Builtin: reduce
Following the lead of the sort operator, it would be a little simpler to see reduce expressions use $a and $b instead of $_[0], $_[1]. E.g. Summation: $sum = reduce{$a + $b} 0, @numbers; $sum = reduce sub{$a + $b},0, @numbers; Production: $prod = reduce{$a * $b}1, @numbers; $prod = reduce sub{$a * $b}, 1, @numbers; Following grep, map, sort, reduce should be able to accept all these forms - currently the form seems to be like sort than grep and map. reduce $a + $b, @list # grep, map reduce{$a + $b} @list # grep, map, sort reducesum2 @list # sort reduce sub{$a + $b}, @list # sort Adam Krolnik Verification Mgr. LSI Logic Corp. Plano TX. 75074
Re: RFC 76 (v1) Builtin: reduce
On Tue, Aug 15, 2000 at 11:31:50AM -0500, Adam Krolnik wrote: Following the lead of the sort operator, it would be a little simpler to see reduce expressions use $a and $b instead of $_[0], $_[1]. The $a and $b of the sort comparator were A Bad Idea to begin with. There's nothing wrong with using the standard @_. The $a and $b just introduce yet another special case, which among other things makes it very hard to warn about dubious uses of users' variables named $a or $b. (Yes, there is a small aesthetic edge in using $a vs $_[0], but I still consider the $ and $b to be warts.) -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
Re: RFC 76 (v1) Builtin: reduce
Jarkko Hietaniemi wrote: The $a and $b of the sort comparator were A Bad Idea to begin with. Ditto. Can we ditch these in Perl 6? Don't see why $_[0] and $_[1] can't be used, or even a more standard $1 and $2. Either one makes it more obvious what's being operated on. It also fixes the "'use strict' ignores $a and $b problem" mentioned repeatedly on p5p. -Nate
Re: RFC 76 (v1) Builtin: reduce
Jarkko Hietaniemi wrote: On Tue, Aug 15, 2000 at 11:31:50AM -0500, Adam Krolnik wrote: Following the lead of the sort operator, it would be a little simpler to see reduce expressions use $a and $b instead of $_[0], $_[1]. The $a and $b of the sort comparator were A Bad Idea to begin with. There's nothing wrong with using the standard @_. The $a and $b just introduce yet another special case, which among other things makes it very hard to warn about dubious uses of users' variables named $a or $b. (Yes, there is a small aesthetic edge in using $a vs $_[0], but I still consider the $ and $b to be warts.) And anyhow, this will work just fine (see RFC 23): $sum = reduce ^a + ^b, @numbers;
Re: RFC 76 (v1) Builtin: reduce
(Yes, there is a small aesthetic edge in using $a vs $_[0], but I still consider the $ and $b to be warts.) And anyhow, this will work just fine (see RFC 23): $sum = reduce ^a + ^b, @numbers; I have been amply reminded of this, thanks :-) (Too little time to spend on RFCs...) -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
Re: RFC 76 (v1) Builtin: reduce
On 11 Aug 2000 09:30:03 +0300, Ariel Scolnicov wrote (and quoted): reduce avg $identity, @list This was my first point regarding Creduce -- not all functions have an identity element. One should note that in general (reduce avg $x,@list) != (reduce sum 0,@list)/@list for Iany value of $x; your reduction is Inot the right way to compute an average (I don't know if it was meant to be or not, but it got me). If you can tell me why you wish to perform this reduction, you should also be able to figure out an identity element. You're computing (($list[0]+$list[1])/2 + $list[2])/2 + ... for some reason. I have some reservations about this reduce() thing. Plain and simple incorporating it into the core language would introduce the chance for lots of buggy programs, like the example Arial gave. In fact, I think that *most* programs that use reduce() would be buggy. But there is more still. On a more theoretical plane, what does reduce { $_[0] OP $_[1] } $x, $y, $z; represent? Is it the programmer's idea of this? $x OP $y OP $z But, is that: ($x OP $y) OP $z or $x OP ($y OP $z) We are used to thinking of associative operators, like "+" and "*", where it makes no difference. A simple replacement by "-" is already a counter example. The "average" example above, is too. (An "operator" and a "function" are basically the same thing with a different notation.) I think that *virtually all* programs that people would write using reduce(), would fall into this category. Besides, in functions like map() and grep(), execution order shouldn't matter. I think that *still* the processing order of the arguments isn't officially stated as "always from left to right" (as with the coma operator), even though highly respected Perl hackers like Abigail (see comp.lang.perl.misc) strongly depend on it. So, what's it going to be here? I think that if your code depends on execution order, you shouldn't be using this functional programming paradigm. I think we don't really need reduce(). There are well working, relatively simple, and *far more transparent* alternatives, at least, for Perl. We do have OP= operators, after all. For example: $total = 0; map { $total += $_ } @list; # if you insist... return $total; How is this so bad, compared to: reduce { $_[0] + $_[1] } @list Is the latter shorter? Hardly. Would it be faster? I doubt it. Is it more transparent to see what it does, or is supposed to do? NOT AT ALL. -- Bart.
Re: RFC 76 (v1) Builtin: reduce
On Thu, Aug 10, 2000 at 07:22:21PM -0400, Chaim Frenkel wrote: Okay, then for reduce avg $identity, @list What should $identity be? I would like to see what avg would be, given that each time it would be passed the previous result (or the first element) and the next element. So without using an external variable to keep count of how many elements had been processed so far it could not be done. So you would probably do it like (reduce __+__ 0, @list) / @list. This will ensure that the sum is defined. However this is probably just a bad exanple of why not to require an identity element. A better example might be trying to perform join, with reduce eg reduce __.','.__ $identity, @list Which would not work for any value of $identity unless you did reduce __.','.__ shift @list, @list which is probably a good example why not to require an identity element. Graham. "AS" == Ariel Scolnicov [EMAIL PROTECTED] writes: AS Think of the first element of the list as different from the rest -- AS it is the initial value to reduce from (for + and *, you'll usually AS pick an appropriate identity element). By writing AS @sum = reduce __+__ 0, @numbers AS you deal elegantly with both cases. AS NOTE: I find this trick very elegant. I wish it were my trick, AS instead of Damian's... -- Chaim Frenkel Nonlinear Knowledge, Inc. [EMAIL PROTECTED] +1-718-236-0183
Re: RFC 76 (v1) Builtin: reduce
Damian Conway wrote: More and more I lean towards a scalar-only reduce. Yep! Simpler semantics and you can always ref a L(OL(OL(OL...etc.))) if you need multidimensionals. Combined with highlander variables, and there ceases to be a problem. -- John Porter
Re: RFC 76 (v1) Builtin: reduce
John Porter [EMAIL PROTECTED] writes: Simpler semantics and you can always ref a L(OL(OL(OL...etc.))) if you need multidimensionals. Combined with highlander variables, and there ceases to be a problem. Will you stop with the highlander variables? -- Piers
Re: RFC 76 (v1) Builtin: reduce
Bart Lateur wrote: I have some reservations about this reduce() thing. Plain and simple incorporating it into the core language would introduce the chance for lots of buggy programs, like the example Arial gave. In fact, I think that *most* programs that use reduce() would be buggy. Whenever people try to use language features with which they are but passingly familiar (or grossly unfamiliar), buggy programs result. Again, your argument could also be applied to OO -- but perl isn't dropping OO any time soon. We are used to thinking of associative operators, like "+" and "*", where [operator order] makes no difference. Besides, in functions like map() and grep(), execution order shouldn't matter. I think that *still* the processing order of the arguments isn't officially stated as "always from left to right" ... So, what's it going to be here? The answer to this objection is simply to declare an official order of execution. Left-to-right. I think that if your code depends on execution order, you shouldn't be using this functional programming paradigm. Wrong. Functional programming is in some sense merely procedural programming but without side-effects. There's no golden rule of FP saying execution order is irrelevant; and I don't see how there could be. Maybe you're getting it confused with declarative programming... I think we don't really need reduce(). Some people thought perl would have been better off without OO, too. Should Larry of listened to them? Or should he have listened to the significantly larger number of people (including himself) who though OO would be a good addition to perl? There are well working, relatively simple, and *far more transparent* alternatives, at least, for Perl. So, you're saying recursion should be eliminated from perl. I don't think that's gonna fly. $total = 0; map { $total += $_ } @list; # if you insist... return $total; How is this so bad, compared to: reduce { $_[0] + $_[1] } @list Is the latter shorter? Hardly. Huh? It's significantly shorter. It's one statement vs. three, and requires no temporary variables. Would it be faster? I doubt it. What do you base that on? The fact that the reduce() version would involve so many more costly perl OPs? -- John Porter
Re: RFC 76 (v1) Builtin: reduce
On Fri, Aug 11, 2000 at 10:51:45AM -0400, John Porter wrote: Damian Conway wrote: More and more I lean towards a scalar-only reduce. Yep! Have you stollen my brain :) Graham.
Re: RFC 76 (v1) Builtin: reduce
A better example might be trying to perform join, with reduce eg reduce __.','.__ $identity, @list Which would not work for any value of $identity unless you did reduce __.','.__ shift @list, @list which is probably a good example why not to require an identity element. Just to clarify: the proposal does not (and will not) *require* an identity element. prototype('CORE::reduce') == '@'. Damian
Re: RFC 76 (v1) Builtin: reduce
Perl6 RFC Librarian [EMAIL PROTECTED] (but actually it was Damian Conway) writes: If the original list has no elements, Creduce immediately returns Cundef. I like everything except this part. Reducing an empty list should be an error. Returning undef (or anything else, really) breaks the algebraic equivalence that f((reduce \f, LIST), $x) eq (reduce \F, LIST, $x) Since this is the single most important property of reduce (indeed, it is the *only* property of reduce), I don't see what we get by breaking it. Also, the RFC should specify that the function is always evaluated in a scalar context (for things to make sense). -- Ariel Scolnicov|"GCAAGAATTGAACTGTAG"| [EMAIL PROTECTED] Compugen Ltd. |Tel: +972-2-6795059 (Jerusalem) \ We recycle all our Hz 72 Pinhas Rosen St.|Tel: +972-3-7658514 (Main office)`- Tel-Aviv 69512, ISRAEL |Fax: +972-3-7658555http://3w.compugen.co.il/~ariels
Re: RFC 76 (v1) Builtin: reduce
I don't see it. 1 == f((reduce +, undef), 1) == reduce +, undef, 1 undef isn't an empty list, it's a one element list. Consider the other "common" reduction: sub f { $_[0] * $_[1] } Now: f((reduce \f, ()), 1) == 0 # f(undef,1) - f(0,1) - 0 But reduce \f, (), 1 == 1 # list flattens to (1), # single element immediately returned I really would like to be able to pass around an empty list and get a _reasonable_ answer. Having to check the list for emptyness before passing it in just seems dirty. One doesn't have to do this for anyother looping operator in the language. for (@empty) {} grep {} @empty map {} @empty None of which *combines* its (possibly non-existent) values together. AS Also, the RFC should specify that the function is always evaluated in AS a scalar context (for things to make sense). Why? reduce should be able to reduce a set of matrices to a matrix. Or actually any aggregate (plural whatzit). I think this is too limiting. Depending upon the context reduce should return undef, an empty list, or other empty plural whatzit. H. I need to see more debate on this before I decide what to propose in the next version of the RFC. Damian
Re: RFC 76 (v1) Builtin: reduce
Chaim Frenkel [EMAIL PROTECTED] writes: "AS" == Ariel Scolnicov [EMAIL PROTECTED] writes: If the original list has no elements, Creduce immediately returns Cundef. AS I like everything except this part. Reducing an empty list should be AS an error. AS Returning undef (or anything else, really) breaks the algebraic AS equivalence that AS f((reduce \f, LIST), $x) eq (reduce \F, LIST, $x) I don't see it. 1 == f((reduce +, undef), 1) == reduce +, undef, 1 You're confusing "f()" and "+" here, and (on the LHS) "undef" with "()". What you're claiming is that f(undef, 1) eq 1 for any function f(). While this is true (in Perl) for C__+__, it's not even true for C__*__. And of course there's nothing you can do about user-specified functions f(). I really would like to be able to pass around an empty list and get a _reasonable_ answer. Having to check the list for emptyness before passing it in just seems dirty. One doesn't have to do this for anyother looping operator in the language. for (@empty) {} grep {} @empty map {} @empty etc. Think of the first element of the list as different from the rest -- it is the initial value to reduce from (for + and *, you'll usually pick an appropriate identity element). By writing @sum = reduce __+__ 0, @numbers you deal elegantly with both cases. NOTE: I find this trick very elegant. I wish it were my trick, instead of Damian's... [...] -- Ariel Scolnicov|"GCAAGAATTGAACTGTAG"| [EMAIL PROTECTED] Compugen Ltd. |Tel: +972-2-6795059 (Jerusalem) \ We recycle all our Hz 72 Pinhas Rosen St.|Tel: +972-3-7658514 (Main office)`- Tel-Aviv 69512, ISRAEL |Fax: +972-3-7658555http://3w.compugen.co.il/~ariels
Re: RFC 76 (v1) Builtin: reduce
By writing @sum = reduce __+__ 0, @numbers you deal elegantly with both cases. NOTE: I find this trick very elegant. I wish it were my trick, instead of Damian's... Damian wishes it were Damian's, but is sure it's at least a few hundred years old :-) Damian
Re: RFC 76 (v1) Builtin: reduce
Couldn't reduce return a list just through concatenating its elements? For instance: @a = (1,3,2,4,3,6,4,8); @sum = reduce( (^total, ^x+^y ), @a ); # (4,6,9,12) Currying placeholders are scalars, so you want: @sum = @{reduce (@^total, ^x+^y ), [], @a }; More and more I lean towards a scalar-only reduce. Simpler semantics and you can always ref a L(OL(OL(OL...etc.))) if you need multidimensionals. Damian
Re: RFC 76 (v1) Builtin: reduce
Chaim Frenkel wrote: Okay, then for reduce avg $identity, @list What should $identity be? What's wrong with: $average = reduce (^last+^this, @^list) / scalar @^list; print $average-([1,3,5]); # Prints '3' You don't need to explicitly add a '0' to the front of the summed list. Although I guess for a geometric average you have to be more careful: $geo_average = reduce (defined(^last)?^last:1 * ^this, @^list) ** (1/scalar @^list); print $geo_average-([1,2,4]); # Prints '2'
Re: RFC 76 (v1) Builtin: reduce
Damian Conway wrote: Currying placeholders are scalars Is that a general truth? It wasn't obvious from RFC 23... If you rev it, perhaps you could make that clearer. Looking back, the defining example did give a list of (;) in the prototype. I suppose it would be pretty complex to infer the type from the expression, unless the placeholder syntax were extended to ^$_, ^@_, ^%_, and similar for named and positional placeholders... Seems like if we get matrix ops (via other RFCs) that we might want to curry them? Here I was thinking a placeholder was a whatzitz whatzitz; of unknown cardinality. Is it, or not? -- Glenn = There are two kinds of people, those who finish what they start, and so on... -- Robert Byrne _NetZero Free Internet Access and Email__ http://www.netzero.net/download/index.html
Re: RFC 76 (v1) Builtin: reduce
Currying placeholders are scalars Is that a general truth? Yes. It proceeds from the fact that $_[0], $_[1], ect are scalars. It wasn't obvious from RFC 23... If you rev it, perhaps you could make that clearer. Will do. Looking back, the defining example did give a list of (;) in the prototype. I suppose it would be pretty complex to infer the type from the expression, unless the placeholder syntax were extended to ^$_, ^@_, ^%_, and similar for named and positional placeholders... Seems like if we get matrix ops (via other RFCs) that we might want to curry them? That's why I think we ought to strict with array refs for multidimensional data. Here I was thinking a placeholder was a whatzitz whatzitz; of unknown cardinality. Is it, or not? Not. It's always a slot for a scalar. Damian
Re: RFC 76 (v1) Builtin: reduce
Please consider the possiblity of tristate logic (RFC TBD.) ala, SQL. Assuming a "use tristate", undef + number = undef This might require that the reduce function be able to ignore undefs. Either always under the tristate pragma. Or on a case by case basis. Also you haven't specified if the arguments to reduce are evaluated lazily. chaim "PRL" == Perl6 RFC Librarian [EMAIL PROTECTED] writes: PRL The first call to the reduction subroutine will be passed the first N PRL elements of the list, and subsequent calls will be passed the result of PRL the previous call and the next N-1 elements in the list, until no more PRL elements remain in the list. If fewer than N-1 elements remain on the PRL final call, all the remaining elemetns are passed. PRL If the original list has no elements, Creduce immediately returns Cundef. PRL If the original list has a single element, that element is immediately returned PRL (without every calling the reduction subroutine). PRL Otherwise, the result of the final reduction call is the result returned PRL by Creduce. PRL If the reduction subroutine is ever terminated by a call to Clast, PRL the enclosing Creduce immediately returns the last reduction value PRL (i.e. Cundef on the first reduction call, $_[0] otherwise) -- Chaim FrenkelNonlinear Knowledge, Inc. [EMAIL PROTECTED] +1-718-236-0183
Re: RFC 76 (v1) Builtin: reduce
On 09 Aug 2000 13:49:24 -0400, Chaim Frenkel wrote: Assuming a "use tristate", undef + number = undef This might require that the reduce function be able to ignore undefs. Either always under the tristate pragma. Or on a case by case basis. grep defined, LIST -- Bart.
Re: RFC 76 (v1) Builtin: reduce
"DC" == Damian Conway [EMAIL PROTECTED] writes: DC I'm not sure how this would affect the proposal. If an item in the DC list being reduced is undef, it appears in the reduction DC subroutines arg list as undef. The reduction subroutine can then DC handle it (or not) as it chooses. DC For example, to short-circuit if the reduction ever becomes undef: DC $sum = { defined $_[0] or last; $_[0]+$_[1] } 0, @numbers; Actually, it would be easier to do in reduce, the undefs should simply be ignored. Otherwise having the user code it, becomes { defined $_[0] defined $_[1] ? $_[0] + $_[1] : defined $[0] ? $_[0] : $_[1] } Pretty ugly. And for the N case, it gets even uglier. So reduce should be able to supply the next N-1 defined() values. chaim -- Chaim FrenkelNonlinear Knowledge, Inc. [EMAIL PROTECTED] +1-718-236-0183
Re: RFC 76 (v1) Builtin: reduce
Actually, it would be easier to do in reduce, the undefs should simply be ignored. Otherwise having the user code it, becomes { defined $_[0] defined $_[1] ? $_[0] + $_[1] : defined $[0] ? $_[0] : $_[1] } Pretty ugly. And for the N case, it gets even uglier. So reduce should be able to supply the next N-1 defined() values. $def_sum = reduce { $_[0]+$_[1] } grep {defined} @numbers; Damian
Re: RFC 76 (v1) Builtin: reduce
"Chaim" == Chaim Frenkel [EMAIL PROTECTED] writes: DC For example, to short-circuit if the reduction ever becomes undef: DC $sum = { defined $_[0] or last; $_[0]+$_[1] } 0, @numbers; Chaim Actually, it would be easier to do in reduce, the undefs should Chaim simply be ignored. If I understand you correctly, I want to disagree with you. What if the "reduce" was to count the number of undefs? $count = reduce { $a + not defined $b } 0, @some_list; Do not discard undef from the source list. -- 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 (v1) Builtin: reduce
Builtin: reduce There are some things unspecified. Specifically 'special' reduce variables. You've got: $sum = reduce {$_[0]+$_[1]} 0, @numbers; $sum = reduce ^_+^_,0, @numbers; $min = reduce ^x = ^y ? ^x : ^y, @numbers I see $_[foo], ^_, and ^somename. I understand how we get to $_[foo], and I can intuit what ^_ means (though it should be specified, I think), but what about ^name? All covered in the higher order functions RFC. Did I not include a reference to that? Oops, no I didn't. Apologies. Damian