reduce metaoperator on an empty list

28 views
Skip to first unread message

Matt Fowles

unread,
May 18, 2005, 8:57:42 PM5/18/05
to Perl6 Language List
All~

What does the reduce metaoperator do with an empty list?

my @a;
[+] @a; # 0? exception?
[*] @a; # 1? exception?
[<] @a; # false?
[||] @a; # false?
[&&] @a; # true?

Also if it magically supplies some correct like the above, how does it
know what that value is?

Thanks,
Matt
--
"Computer Science is merely the post-Turing Decline of Formal Systems Theory."
-???

Rod Adams

unread,
May 18, 2005, 9:12:53 PM5/18/05
to Perl6 Language List
Matt Fowles wrote:

>All~
>
>What does the reduce metaoperator do with an empty list?
>
>my @a;
>[+] @a; # 0? exception?
>[*] @a; # 1? exception?
>[<] @a; # false?
>[||] @a; # false?
>[&&] @a; # true?
>
>Also if it magically supplies some correct like the above, how does it
>know what that value is?
>
>

My general thoughts has been that:

[op] @list

behaves something like:

eval join(op, @list)

so feeding it an empty list would return undef, regardless of op.
Similarly, if @list is just one element, it returns that element.

-- Rod Adams

Mark A. Biggar

unread,
May 18, 2005, 9:26:19 PM5/18/05
to Matt Fowles, Perl6 Language List
Matt Fowles wrote:
> All~
>
> What does the reduce metaoperator do with an empty list?
>
> my @a;
> [+] @a; # 0? exception?
> [*] @a; # 1? exception?
> [<] @a; # false?
> [||] @a; # false?
> [&&] @a; # true?
>
> Also if it magically supplies some correct like the above, how does it
> know what that value is?

The usual definition of reduce in most languages that support it, is
that reduce over the empty list produces the Identity value for the
operation. So for the above ops the answers are: 0, 1, depends, false,
true. For chained ops like '<' it depends on whether x<y<z return x or
z on being true. if x then -inf else if z then +inf (don't ask if it
returns y). Note that some ops (like '%') don't have an identity value
and therefore [%] over the empty list is the equivalent to a divide by 0
and probably throws an exception or at least returns undef. Now this is
a problem for user defined operations, so reduce of a user defined op
over the empty list is either an exception, return undef or we need a
trait that can be specified for an infix op that specifies what to
return for reduce over the empty list. The compiler shouldn't bother to
check if what you specified is really the Identity value for op, but I'd
consider it a bug if it isn't.


--
ma...@biggar.org
mark.a...@comcast.net

Stuart Cook

unread,
May 18, 2005, 9:27:48 PM5/18/05
to Matt Fowles, Perl6 Language List
On 5/19/05, Matt Fowles <uber...@gmail.com> wrote:
> All~
>
> What does the reduce metaoperator do with an empty list?
>

/me puts on his lambda hat

In Haskell, there is a distinction between foldl and foldl1 (similar
remarks apply to foldr/foldr1[1]):

The former (foldl) requires you to give an explicit 'left unit'[2],
which is implicitly added to the left of the list being reduced. This
means that folding an empty list will just give you the unit.

i.e.
foldl (+) 0 [a,b,c] = ((0+a)+b)+c
foldl (+) 0 [] = 0

The latter (foldl1) doesn't use a unit value, but this means that you
can't fold empty lists.

i.e.
foldl1 (+) [a,b,c] = (a+b)+c
foldl1 (+) [] = ***error***


/me puts camel hat back on

This suggests that []-reducing an empty list should probably (IMO) do
one of the following:

* Fail, since it's an ill-defined operation without an explicit unit
* Try to find a suitable unit value (see below), and fail if it doesn't find one

You /could/ try to do something 'sensible' and return 0 or undef, but
this seems likely to result in more confusion.

Another alternative is to give the user the option of specifying such
a unit when using the reduction meta-operator, but this seems to work
against the whole point of [+] (which is brevity). If you want to
specify your own unit, use '&reduce'.

> my @a;
> [+] @a; # 0? exception?
> [*] @a; # 1? exception?
> [<] @a; # false?
> [||] @a; # false?
> [&&] @a; # true?
>
> Also if it magically supplies some correct like the above, how does it
> know what that value is?
>

Perhaps the operator could have some kind of 'unit' trait? (Or perhaps
'left_unit' and 'right_unit'?)


Stuart

[1] Just remember that unlike foldr/foldl, which are explicitly
right/left associative, [+] is 'DWIM-associative', reflecting the
associativity of the underlying operator.

[2] e.g. 0 is the left (and right) unit of + because 0 + x == x (and x + 0 == 0)

Stuart Cook

unread,
May 18, 2005, 10:25:07 PM5/18/05
to Perl6 Language List
To summarise what I think everyone is saying, []-reducing an empty
list yields either:

1) undef (which may or may not contain an exception), or
2) some unit/identity value that is a trait of the operator,

depending on whether or not people think (2) is actually a good idea.

The usual none(@Larry) disclaimer applies, of course...


Stuart

Rob Kinyon

unread,
May 18, 2005, 10:55:37 PM5/18/05
to Stuart Cook, Perl6 Language List
On 5/18/05, Stuart Cook <sco...@gmail.com> wrote:
> To summarise what I think everyone is saying, []-reducing an empty
> list yields either:
>
> 1) undef (which may or may not contain an exception), or
> 2) some unit/identity value that is a trait of the operator,
>
> depending on whether or not people think (2) is actually a good idea.

I would think that the Principle of Least Surprise points to (1),
given that the standard explanation of the [+]@x is eval join( '+', @x
) ...

Rob

Mark A. Biggar

unread,
May 18, 2005, 11:29:43 PM5/18/05
to Stuart Cook, Perl6 Language List

Well the only case where it probably really matters is [+] where you
really want the result to be 0. Of course +undef == 0, so maybe
returning undef might be okay. I'm thinking about the case:

[+] grep &some_condition, @a

where you really want the total to be 0, even if the result of the grep
is empty.

A case can also be made for (assuming @a = ();) that

[*}@a == 1
[~]@a eq '' (also covered by ~undef)
[?&]@a ~~ true
[?|]@a ~~ false (also covered by ?undef)
[?^]@a ~~ false (also covered by ?undef)
[+&]@a == MAXINT (whatever that is)
[+|]@a == 0 (also covered by +undef)
[+^]@a == 0 (also covered by +undef)

chained ops are wierd

[<]@a ~~ false
[>]@a ~~ false
[<=]@a ~~ true
[>=]@a ~~ true

Other ops have theoritical values that I don't know if we can handle:

[~&]@a should be an infinitely long bitstring of 1's
[~|]@a should be an infinitely long bitstring of 0's

Again, given that that the really important case [+] is covered by
+undef == 0, maybe just always returning undef is good enough.

--
ma...@biggar.org
mark.a...@comcast.net

Rod Adams

unread,
May 18, 2005, 11:08:29 PM5/18/05
to Perl6 Language List
Rob Kinyon wrote:

$rod == none(@Larry), and therefore just because I think it should be
that way, doesn't mean it is that way.

But the "eval join" way of looking at it does seem to be consistent with
what I've seen discussed previously, and would provide a useful way to
remember the effects of edge cases.

-- Rod Adams

Stuart Cook

unread,
May 19, 2005, 2:16:20 AM5/19/05
to Brad Bowman, Matt Fowles, Perl6 Language List
On 5/19/05, Brad Bowman <li...@bereft.net> wrote:
> Can't the appropriate identity just be prepended?

>
> > > my @a;
> > > [+] @a; # 0? exception?
> [+] (0, @a);

>
> > > [*] @a; # 1? exception?
> [*] (1, @a);
>
> > > [<] @a; # false?
> [<] (-Inf, @a); # ???

Wow, that's actually pretty elegant, and it has the benefit of
explicitly TELLING the reader what you intended to do.

Another option (depending on your situation) is to use 'err' to
replace the resultant 'undef' with a value of your choosing, i.e.

[*] @coefficients err 1;
[+] @scores err 0;
[&&] @preconditions err 1;

etc. (assuming I got the precedence right)

I think all these rather nice workarounds, combined with the hairiness
and complexity of trying to come up with default answers, make a
really strong case for undef/fail being the right choice here.


Stuart

Michele Dondi

unread,
May 19, 2005, 4:50:16 AM5/19/05
to Matt Fowles, Perl6 Language List
On Wed, 18 May 2005, Matt Fowles wrote:

> All~
>
> What does the reduce metaoperator do with an empty list?

Interesting. Mathematically an empty sum is zero and an empty product is
one. Maybe each operator {c,s}hould have an associated method returning
its neutral element for [] to use it on empty lists, so that it would
probably return undef on empty lists.


Just my 2 Eurocents,
Michele
--
It was part of the dissatisfaction thing. I never claimed I was a
nice person.
- David Kastrup in comp.text.tex, "Re: verbatiminput double spacing"

Michele Dondi

unread,
May 19, 2005, 4:54:50 AM5/19/05
to Rob Kinyon, Stuart Cook, Perl6 Language List
On Wed, 18 May 2005, Rob Kinyon wrote:

>> 1) undef (which may or may not contain an exception), or
>> 2) some unit/identity value that is a trait of the operator,
>>
>> depending on whether or not people think (2) is actually a good idea.
>
> I would think that the Principle of Least Surprise points to (1),

I don't think so. I, for one, would expect [+]; to return zero and [*]; to
return 1. But that's only because I {trust,expect} perl(6) to be smart
enough to DWIM.


Michele
--
\renewcommand\labelitemi{\textcolor{yellow}{\textbullet}}
would change the colour of the first-level bullet, and improve the
document so's i can't see the bullets.
- Robin Fairbairns in comp.text.tex

Edward Cherlin

unread,
May 19, 2005, 5:50:29 AM5/19/05
to Perl6 Language List
On Wednesday 18 May 2005 17:57, Matt Fowles wrote:
> All~
>
> What does the reduce metaoperator do with an empty list?

Here is the last answer from Ken Iverson, who invented reduce in
the 1950s, and died recently.
file:///usr/share/j504/system/extras/help/dictionary/intro28.htm
Identity Functions and Neutral

The monads 0&+ and 1&* are identity functions, and 0 and 1 are
said to be identity elements or neutrals of the dyads + and *
respectively. Insertion on an empty list yields the neutral of
the dyad inserted. For example:

+/ i.0 +/'' +/0{. 2 3 5
0 0 0

*/i.0 */'' */0{. 2 3 5
1 1 1

> my @a;
> [+] @a; # 0? exception?
> [*] @a; # 1? exception?
> [<] @a; # false?
> [||] @a; # false?
> [&&] @a; # true?
>
> Also if it magically supplies some correct like the above, how
> does it know what that value is?
>
> Thanks,
> Matt

The page
file:///usr/share/j504/system/extras/help/dictionary/d420.htm
gives examples, unfortunately not easily readable ones.

"If y has no items (that is, 0=#y), the result of u/y is the
neutral or identity element of the function u. A neutral of a
function u is a value e such that x u e ↔ x or e u x ↔ x, for
every x in the domain (or some significant sub-domain such as
boolean) of u . This definition of insertion over an argument
having zero items extends partitioning identities of the form
u/y ↔ (u/k{.y) u (u/k}.y) to the cases k e. 0,#y .

"The identity function of u is a function ifu such that ifu y ↔
u/y if 0=#y ."

[The following table is greatly simplified by listing identity
elements rather than identity functions. Some are only left
identities, and some only right identities.]

Identity element For

0 < > + - +. ~: | (2 4 5 6 b.)
1 = <: >: * % *. %: ^ ! (1 9 11 13 b.)
_ <.
__ >.
'' ,
[and a few more that I will not explain here]

Glossary
J Description
+. or
~: objects are identical
| remainder, defined so that 0|N is N
b. Boolean functions from table
<: less than or equal, restricted to Booleans here
(1<:0 is 0, 1<:1 is 1)
>: greater than or equal, restricted to Booleans here
* times, restricted to Booleans here
% divide
*. and
%: root
^ exponential
! combinations
<. minimum
>. maximum
'' empty vector, list of length 0
, catenate, join lists
_ infinity
__ negative infinity

So (_ <. N) is N, as is (__ >. N).
All of these functions are defined in detail but quite tersely in
the J Dictionary, indexed on the page
file:///usr/share/j504/system/extras/help/dictionary/vocabul.htm
For examuple, the Boolean function b. is defined on the page
file:///usr/share/j504/system/extras/help/dictionary/dbdotn.htm

--
Edward Cherlin
Generalist & activist--Linux, languages, literacy and more
"A knot! Oh, do let me help to undo it!"
--Alice in Wonderland
http://cherlin.blogspot.com

C. Scott Ananian

unread,
May 19, 2005, 10:21:17 AM5/19/05
to Rob Kinyon, Stuart Cook, Perl6 Language List
On Wed, 18 May 2005, Rob Kinyon wrote:

I'd say the principle of least surprise points to (1); in the sense that
$sum = [+] @x; would Just Work, etc.

I also have a vague sense that the 'identity' value for an operator might
also be useful in other places in the compiler (enabling optimizations,
etc). Providing it as a trait means that these 'other things' could work
even with user-defined operators. (And leaving the trait undefined gives
you the behavior (1), if that's what you want.)
--scott

Albanian LICOZY shotgun CABOUNCE plastique Sigint Justice fissionable
LITEMPO KGB KUCAGE LIONIZER ESCOBILLA North Korea CLOWER genetic NRA
( http://cscott.net/ )

Sam Vilain

unread,
May 19, 2005, 10:51:56 PM5/19/05
to Edward Cherlin, Perl6 Language List
Edward Cherlin wrote:
> Here is the last answer from Ken Iverson, who invented reduce in
> the 1950s, and died recently.
> file:///usr/share/j504/system/extras/help/dictionary/intro28.htm
[snip]

Thanks for bringing in a little history to the discussion. Those links
are all local to your system; do you have internet reachable versions of them?

Cheers,
Sam.

Andrew Rodland

unread,
May 19, 2005, 11:42:52 PM5/19/05
to perl6-l...@perl.org
These seem to be the original sources:

http://www.jsoftware.com/books/help/dictionary/intro28.htm
http://www.jsoftware.com/books/help/dictionary/d420.htm

and so on. Front page is at
http://www.jsoftware.com/books/help/dictionary/title.htm . I still haven't
figured out what "J" is though.

Sam Vilain

unread,
May 19, 2005, 11:09:08 PM5/19/05
to Stuart Cook, Matt Fowles, Perl6 Language List
Stuart Cook wrote:
> In Haskell, there is a distinction between foldl and foldl1 (similar
> remarks apply to foldr/foldr1[1]):
> The former (foldl) requires you to give an explicit 'left unit'[2],
> which is implicitly added to the left of the list being reduced. This
> means that folding an empty list will just give you the unit.
> i.e.
> foldl (+) 0 [a,b,c] = ((0+a)+b)+c
> foldl (+) 0 [] = 0
> The latter (foldl1) doesn't use a unit value, but this means that you
> can't fold empty lists.
> i.e.
> foldl1 (+) [a,b,c] = (a+b)+c
> foldl1 (+) [] = ***error***

sure. Maybe the identity values could be supplied by making the reduce operator
for them a curried version of reduce, where reduce requires a list with at least
one element (or DIES :))

eg, something similar to; (sorry for the psuedo-perl6, corrections welcome :))

sub prefix:<[+]> (*@args) ::= &reduce.assuming(func => &infix:<+>, first => 0);
sub prefix:<[*]> (*@args) ::= &reduce.assuming(func => &infix:<*>, first => 1);

This would mean that unless the operator specifically defines a curried reduce
version of itself, then the [] version of it on an empty list will be a hard run-time
error.

Then again, maybe an identity trait is more elegant and covers the varied ways
that multiple operators combine inside reduce..

> You /could/ try to do something 'sensible' and return 0 or undef, but
> this seems likely to result in more confusion.

Personally I think returning an undef for this kind of situation would be as wrong
as returning undef for 0/0.

Sam.

Randal L. Schwartz

unread,
May 20, 2005, 9:19:50 AM5/20/05
to perl6-l...@perl.org
>>>>> "Randal" == Randal L Schwartz <mer...@stonehenge.com> writes:

Randal> For example, if I wanted the identity hash (where all values are 1,
Randal> but keys are original list elements), I could do:

Randal> my %hash = @somelist.inject({}, { $^a{$^b} = 1; $^a });

And yes, I know I can spell this as:

my %hash = ({}, @somelist).reduce({ $^a{$^b} = 1; $^a });

But it puts things all in the wrong place for me. :)

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<mer...@stonehenge.com> <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!

Randal L. Schwartz

unread,
May 20, 2005, 9:09:55 AM5/20/05
to perl6-l...@perl.org
>>>>> "Mark" == Mark A Biggar <ma...@biggar.org> writes:

Mark> The usual definition of reduce in most languages that support it, is
Mark> that reduce over the empty list produces the Identity value for the
Mark> operation.

In Smalltalk, the equivalent of "reduce" is "inject:into:", so a
"sum" reduce looks like:

sum := aList inject: 0 into: [:previous :this | previous + this]

Now the advantage here is that if aList is empty, we get back the inject
value. Thus, the behavior is always well-defined.

The Perl reduce operator treats the first element of the list as the
"inject" value above. However, if the first element is missing,
the most Perlish thing I can think of is having it return undef,
because it's like you've specified an undef inject value.

I'd also argue that we could provide .inject_into, to make Smalltalkers
happy to always spell out the initial value and codeblock, instead
of relying on the first element of the list for the initial value.

For example, if I wanted the identity hash (where all values are 1,

but keys are original list elements), I could do:

my %hash = @somelist.inject({}, { $^a{$^b} = 1; $^a });

That'd be Way Cool. Once you get your head around inject, you never
want to go back to reduce. :)

John Macdonald

unread,
May 20, 2005, 10:18:49 AM5/20/05
to Randal L. Schwartz, perl6-l...@perl.org
On Fri, May 20, 2005 at 06:09:55AM -0700, Randal L. Schwartz wrote:
> >>>>> "Mark" == Mark A Biggar <ma...@biggar.org> writes:
>
> Mark> The usual definition of reduce in most languages that support it, is
> Mark> that reduce over the empty list produces the Identity value for the
> Mark> operation.
>
> In Smalltalk, the equivalent of "reduce" is "inject:into:", so a
> "sum" reduce looks like:
>
> sum := aList inject: 0 into: [:previous :this | previous + this]
>
> Now the advantage here is that if aList is empty, we get back the inject
> value. Thus, the behavior is always well-defined.
>
> The Perl reduce operator treats the first element of the list as the
> "inject" value above. However, if the first element is missing,
> the most Perlish thing I can think of is having it return undef,
> because it's like you've specified an undef inject value.

I think we should provide built-in operators with an attribute
called "identity". Reduce, when given an empty list, would
check if the operator has a defined identity attribute. If so,
it is returned as the result of the reduction. If the opereator
has no identity attribute, reduce throws an exception for an
empty list.

Is there a built-in operator that doesn't have a meaningful
identity value? I first thought of exponentiation, but it has
an identity value of 1 - you just have to realize that since
it is a right associative operator, the identity has to be
applied from the right.

I suspect that if people ever get into writing code that works
on operators instead of data, there would be additional uses
found for the identity attribute (and there may be additional
operator attributes that make sense there too, although none
come immediately to mind). MJD will soon have to start working
on the second edition of Higher Order Perl.

--

Mark A. Biggar

unread,
May 20, 2005, 12:07:31 PM5/20/05
to John Macdonald, Randal L. Schwartz, perl6-l...@perl.org
John Macdonald wrote:

> Is there a built-in operator that doesn't have a meaningful
> identity value? I first thought of exponentiation, but it has
> an identity value of 1 - you just have to realize that since
> it is a right associative operator, the identity has to be
> applied from the right.

Well the identity of % is +inf (also right side only). The identities
for ~| and ~^ are infinitely long bitstrings of 0's, while that for ~&
is a similarly long bitstring of 1's. The chained comparison ops are
weird as depending of which why you define the associativity (and thus
which side's value you return when true) you get either a left side only
or right side only Identity. E.g. if X<Y is left associative and
returns Y when true then it has a left side identity of -inf, etc. But
as I'm not sure if the chained ops are actually going to be defined
defined in terms of the associativity of the binary op (the way false
results propagates through messes things up), so that argument may not work.


--
ma...@biggar.org
mark.a...@comcast.net

Edward Cherlin

unread,
May 20, 2005, 4:29:20 PM5/20/05
to Sam Vilain, Perl6 Language List
On Thursday 19 May 2005 19:51, Sam Vilain wrote:
> Edward Cherlin wrote:
> > Here is the last answer from Ken Iverson, who invented
> > reduce in the 1950s, and died recently.
> > file:///usr/share/j504/system/extras/help/dictionary/intro28
> >.htm

http://www.jsoftware.com/books/help/dictionary/intro28.htm

Sorry. It's exactly the same material the provide with their
software, so I got confused.

> [snip]
>
> Thanks for bringing in a little history to the discussion.
> Those links are all local to your system; do you have internet
> reachable versions of them?
>
> Cheers,
> Sam.

--

Mark A Biggar

unread,
May 20, 2005, 6:14:26 PM5/20/05
to TSa (Thomas Sandlaß), perl6-l...@perl.org

> Mark A. Biggar wrote:
> > Well the identity of % is +inf (also right side only).
>
> I read $n % any( $n..Inf ) == $n. The point is there's no
> unique right identity and thus (Num,%) disqualifies for a
> Monoid. BTW, the above is a nice example where a junction
> needn't be preserved :)

If as usual the definition of a right identity value e is that a op e = a for all a,
then only +inf works. Besdies you example should have been;
$n % any (($n+1)..Inf), $n % $n = 0.

> > E.g. if X<Y is left associative and returns Y when true then ...
>
> Sorry, is it the case that $x = $y < $z might put something else
> but 0 or 1 into $x depending on the order relation between $y and $z?

Which is one reason why I siad that it might not make sense to define the chaining ops in terms of the associtivity of the binary ops, But as we are interested in what [<] over the empty list shoud return , the identity (left or right) of '<' is unimportant as I think that should return false as there is nothing to be less then anything else. Note that defaulting to undef therefore works in that case.

--
Mark Biggar
ma...@biggar.org
mark.a...@comcast.net
mbi...@paypal.com


Matt Fowles

unread,
May 21, 2005, 12:45:59 AM5/21/05
to mark.a...@comcast.net, TSa (Thomas Sandlaß), perl6-l...@perl.org
Mark~

On the contrary a mathematician would say that the empty list is
monotonically increasing (vacuously) and the answer should be true.

Edward Cherlin

unread,
May 22, 2005, 1:41:00 AM5/22/05
to Perl6 Language List
On Friday 20 May 2005 07:18, John Macdonald wrote:
> Is there a built-in operator that doesn't have a meaningful
> identity value?

Certainly.

> I first thought of exponentiation, but it has
> an identity value of 1 - you just have to realize that since
> it is a right associative operator, the identity has to be
> applied from the right.
>
> I suspect that if people ever get into writing code that works
> on operators instead of data, there would be additional uses
> found for the identity attribute (and there may be additional
> operator attributes that make sense there too, although none
> come immediately to mind).

APL and J programmers have lots of examples.

Edward Cherlin

unread,
May 22, 2005, 1:34:14 AM5/22/05
to Perl6 Language List

It's an enhanced APL without the funny characters.

Edward Cherlin

unread,
May 22, 2005, 1:43:27 AM5/22/05
to Perl6 Language List
On Friday 20 May 2005 08:11, "TSa (Thomas Sandlaß)" wrote:
> John Macdonald wrote:
> > ... (and there may be additional

> > operator attributes that make sense there too, although none
> > come immediately to mind).
>
> Well, I wonder why people neglect the fact that the
> neutral/identity element is not a property of the operator
> alone?! Besides the associativity and commutativity of the
> operator the inverse element---or the left and right
> one---with respect to the underlying representation come at
> least to my mind :)

Yes, a number of operators have an inverse on Boolean 0 and 1
only.

> This would give an "axiomatic" type system:
>
> class Num does Group[Num,+,0] {...}
> class Num does Field[Num,+,0,*,1] {...}
> class Str does Monoid[Str,~,''] {...}
>
> class Complex does Field[Array[2] of Num,+,[0,0],*,[1,0]]
> {...}
>
> class 3DVector does VectorSpace[Array[3] of Num,+,[0,0,0]]
> {...}
>
> And it provides valuable information to the optimizer.

Mark A Biggar

unread,
May 23, 2005, 4:54:19 PM5/23/05
to TSa (Thomas Sandlaß), p6l

There are actuall two usefull definition for %. The first which Ada calls 'mod' always returns a value 0<=X<N and yes it has no working value that is an identity. The other which Ada calls 'rem' defined as follows:

Signed integer division and remainder are defined by the relation:

A = (A/B)*B + (A rem B)

where (A rem B) has the sign of A and an absolute value less than the absolute value of B. Signed integer division satisfies the identity:

(-A)/B = -(A/B) = A/(-B)

It does have a right side identity of +INF.


> HaloO Mark,
>
> please don't regard the following as obtrusive.


>
> you wrote:
> > If as usual the definition of a right identity value e is that a op e = a for
> all a,
> > then only +inf works. Besdies you example should have been;
>

> Or actually $n % any( abs($n)+1 .. Inf ) to really exclude 0
> from the junction.


>
> > $n % any (($n+1)..Inf), $n % $n = 0.
>

> That depends on the definition of % and the sign of $n.
> With the euclidean definition 0 <= ($n % $N == $n % -$N) < abs($N)
> and for $n < 0 there's no identity at all. The identity element
> has to be an element of the set, which +Inf isn't. It's a type.
>
> BTW, is % defined as truncation in Perl6?
> That would be a bit unfortunate. Simple but not well thought out.
> --
> TSa (Thomas Sandlaß)
>

John Macdonald

unread,
May 24, 2005, 9:46:32 AM5/24/05
to mark.a...@comcast.net, TSa (Thomas Sandlaß), perl6-l...@perl.org

The identity operand is -inf for < and <=, and +inf for >
and >=. A chained relation < (>, <=, >=) is then taken to
mean monotonically increasing (decreasing, non-decreasing,
non-increasing), and an empty list, like a one element list,
is always in order.

--

Larry Wall

unread,
May 31, 2005, 3:21:47 PM5/31/05
to p6l
On Mon, May 23, 2005 at 08:54:19PM +0000, mark.a...@comcast.net wrote:
:
: There are actuall two usefull definition for %. The first which Ada calls 'mod' always returns a value 0<=X<N and yes it has no working value that is an identity. The other which Ada calls 'rem' defined as follows:

:
: Signed integer division and remainder are defined by the relation:
:
: A = (A/B)*B + (A rem B)
:
: where (A rem B) has the sign of A and an absolute value less than the absolute value of B. Signed integer division satisfies the identity:
:
: (-A)/B = -(A/B) = A/(-B)
:
: It does have a right side identity of +INF.

I think % should behave as Perl 5 has it, especially insofar as it
coerces to integer. That doesn't mean we can't have "mod" and/or
"rem" variants that have other semantics. Infix operators are pretty
much in their own namespace anyway, so they won't clobber sub names.

Larry

Damian Conway

unread,
May 31, 2005, 8:44:47 PM5/31/05
to perl6-l...@perl.org
All this discussion of "identity" defaults for reductions has been very
interesting and enlightening.

But it seems to me that the simplest "correct" behaviour for reductions is:

2+ args: interpolate specified operator
1 arg: return that arg
0 args: fail (i.e. thrown or unthrown exception depending on use fatal)

Then, as Brad previously reminded us all, to cover the possibility of empty
arg lists, you just prepend the desired identity value:

$sum = [+] 0, @values;
$prod = [*] 1, @values;
$prob = [*] 0, @probs;

or else, as Stuart observed, postpend them as a default:

$sum = ([+] @values err 0);
$prod = ([*] @values err 1);
$prob = ([*] @probs err 0);


Damian

Dave Whipp

unread,
May 31, 2005, 8:55:17 PM5/31/05
to perl6-l...@perl.org
Damian Conway wrote:

> 0 args: fail (i.e. thrown or unthrown exception depending on use
> fatal)

...


>
> $sum = ([+] @values err 0);
> $prod = ([*] @values err 1);
> $prob = ([*] @probs err 0);

Just wanted to check, if I've said "use fatal": will that "err 0" DWIM,
or will the fatalness win? Would I need to write

Damian Conway

unread,
May 31, 2005, 9:00:06 PM5/31/05
to Dave Whipp, perl6-l...@perl.org
Dave Whipp wrote:

> Damian Conway wrote:
>
>> 0 args: fail (i.e. thrown or unthrown exception depending on use
>> fatal)
>
> ...
>
>>
>> $sum = ([+] @values err 0);
>> $prod = ([*] @values err 1);
>> $prob = ([*] @probs err 0);
>
>
> Just wanted to check, if I've said "use fatal": will that "err 0" DWIM,

That depends what you mean. ;-)
Under "use fatal" you'll get an exception if you don't provide any args.


> or will the fatalness win?

The fatalness will win.


> Would I need to write

Yes. :-)

And what you'd need to write would be:

$sum = (try{ [+] @values } err 0);

Damian

Dave Whipp

unread,
May 31, 2005, 9:16:53 PM5/31/05
to perl6-l...@perl.org, Damian Conway
Damian Conway wrote:
> And what you'd need to write would be:
>
> $sum = (try{ [+] @values } err 0);

The "err ..." idiom seems too useful to have it break in this case.
Afterall, the purpose of "err 0" is to tell the stupid computer that I
know what to do with the empty-array scenario.

Feels like fine grained control over fatalness is needed (and not just
per-function). For example "use fatal :void_context_only" would be nice,
but wouldn't help in this case. This needs "use fatal :void_or_assign".

Damian Conway

unread,
May 31, 2005, 9:28:00 PM5/31/05
to perl6-l...@perl.org
Dave Whipp wrote:

What it probably needs is: "use fatal :untested"

That is, die unless the failed result is in a boolean or "definedean" context.

This might even be a more reasonably dwimmy default, with 'use fatal :always'
being required to get "always throw the exception".

Damian

Rod Adams

unread,
May 31, 2005, 9:29:53 PM5/31/05
to perl6-l...@perl.org
Dave Whipp wrote:

Seems to me that C<err> should have an implied C<try{...}> on it's lhs.
Unless we spell that C<error>.

-- Rod Adams

Juerd

unread,
May 31, 2005, 10:26:24 PM5/31/05
to Damian Conway, perl6-l...@perl.org
Damian Conway skribis 2005-06-01 10:44 (+1000):

> 2+ args: interpolate specified operator
> 1 arg: return that arg
> 0 args: fail (i.e. thrown or unthrown exception depending on use fatal)

Following this logic, does join(" ", @foo) with +@foo being 0 fail too?

I dislike this, and would prefer [op] with no elements to simply return
whatever () returns: an empty list in list context, undef in scalar
context.


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Joe Gottman

unread,
May 31, 2005, 11:19:35 PM5/31/05