2 views

Skip to first unread message

Apr 12, 2005, 11:58:40 PM4/12/05

to perl6-l...@perl.org

Hey folks,

I wanted to delurk and address an issue that may need clarification in

regards to hyper operators.

Quoting S03:

> If one argument is insufficiently dimensioned, Perl "upgrades" it:

> (3,8,2,9,3,8) >>-<< 1; # (2,7,1,8,2,7)

Now in this example case, it's pretty clear that the scalar 1 gets

turned into a list of 1s with the length of the lhs. What about the

case of a larger-dimensioned or single-dimensioned array?

Example:

(1,2,3,4,5) >>+<< (1,2)

Is this equivalent to:

a) (1,2,3,4,5) >>+<< (1,2,undef,undef,undef) (undef padding)

b) (1,2,3,4,5) >>+<< (1,2,1,2,1) (repetition)

c) (1,2,3,4,5) >>+<< (1,2,2,2,2) (stretching)

d) (1,2) >>+<< (1,2) (truncation)

e) something else, ie, warnings about mismatched dimension, die(),

segfault, kill -9 1 (whatever your sadism level is).

Additionally, I was wondering if there was a difference between:

(3,8,2,9,3,8) >>-<< 1

and

(3,8,2,9,3,8) >>-<< (1)

I suppose the answer to that depends on the answer to the above

question.

If the answer is the a) case as above and undef resolves to 0

numerically, then we run into another issue to consider. In the case

of addition and subtraction, 0 is the identity element, and so:

(1,2,3,4,5) >>+<< (1,2) yields (2,4,3,4,5).

But the intuitiveness goes away with multiplication, and completely

blows up with division:

(1,2,3,4,5) >>*<< (1,2) yields (1,4,0,0,0), probably not what we wanted.

(1,2,3,4,5) >>/<< (1,2) yields (1,1,NaN,NaN,NaN), and probably die()s

with division by zero errors.

If in the addition and subtraction cases we want to preserve the

identity cases for the slots not accounted for, undef is fine because

it resolves to 0; to provide the same features for multiplication and

division, the identity element would have to be 1. But that would

suppose that the potential hyper-operators would know what their

appropriate identity elements were (and that such a thing is meaningful

to them).

Additionally, if there is a difference between the automatic scalar

promotion and list promotion, we could run into errors where people

would expect an expression to be a scalar which would be promoted in

the documented fashion, but would really be promoted in one of a)-e),

breaking what they expected:

(1..5) >>+<< ($a-$b) # list context for the expression? Promotes like

what?

(1..5) >>+<< +($a-$b) # forced scalar context -- promotes like

documented.

(1..5) >>+<< (1) # promotes like what?

Thoughts?

David Christensen

Apr 13, 2005, 3:06:54 AM4/13/05

to David Christensen, perl6-l...@perl.org

David Christensen <d...@dwci.net> wrote:

> Example:

> (1,2,3,4,5) >>+<< (1,2)

>

> Is this equivalent to:

>

> a) (1,2,3,4,5) >>+<< (1,2,undef,undef,undef) (undef padding)

> b) (1,2,3,4,5) >>+<< (1,2,1,2,1) (repetition)

> c) (1,2,3,4,5) >>+<< (1,2,2,2,2) (stretching)

> d) (1,2) >>+<< (1,2) (truncation)

> e) something else, ie, warnings about mismatched dimension, die(),

> segfault, kill -9 1 (whatever your sadism level is).

> Example:

> (1,2,3,4,5) >>+<< (1,2)

>

> Is this equivalent to:

>

> a) (1,2,3,4,5) >>+<< (1,2,undef,undef,undef) (undef padding)

> b) (1,2,3,4,5) >>+<< (1,2,1,2,1) (repetition)

> c) (1,2,3,4,5) >>+<< (1,2,2,2,2) (stretching)

> d) (1,2) >>+<< (1,2) (truncation)

> e) something else, ie, warnings about mismatched dimension, die(),

> segfault, kill -9 1 (whatever your sadism level is).

IIRC, it's f) (1,2,3,4,5) >>+<< (1,2,$identity,$identity,$identity),

where $identity's value is determined by a table something like this:

infix:<+> 0

infix:<-> 0

infix:<~> ''

infix:<*> 1

infix:</> 1

infix:<%> mumble

infix:<x> 1

I could be wrong, though; I can't find any support for it in the design docs.

--

Brent 'Dax' Royal-Gordon <br...@brentdax.com>

Perl and Parrot hacker

"I used to have a life, but I liked mail-reading so much better."

Apr 13, 2005, 11:38:16 AM4/13/05

to perl6-l...@perl.org

Brent 'Dax' Royal-Gordon wrote:

> IIRC, it's f) (1,2,3,4,5) >>+<< (1,2,$identity,$identity,$identity),

> where $identity's value is determined by a table something like this:

> IIRC, it's f) (1,2,3,4,5) >>+<< (1,2,$identity,$identity,$identity),

> where $identity's value is determined by a table something like this:

In the case of &infix_circumfix_meta_operator:{'»','«'}:(List,List:&op)

there's no "upgrade"---to use the S03 term. A simple "apply &op where

the lists overlap and keep the rest of the longer one" suffices.

That is (1,2,3,4,5) >>+<< (1,2) becomes (1+1, 2+2, 3, 4, 5). For

&infix_circumfix_meta_operator:{'»','«'}:(List,Scalar:&op) the upgrade

works by applying the operator with the scalar to all entries:

(1,2,3,4,5) >>+<< 1 becomes (1+1, 2+1, 3+1, 4+1, 5+1).

What I ask myself is wether (1,2,3) »+ 1 should be a syntax error or just

a different form to express the :(List,Scalar:&) case. BTW, I know that

&infix_prefix_meta_operator:{'»'} isn't mentioned in A12.

> I could be wrong, though; I can't find any support for it in the design docs.

Indeed, "upgrade" is a bit fuzzy ;)

--

TSa (Thomas Sandlaß)

Apr 14, 2005, 1:38:04 PM4/14/05

to perl6-l...@perl.org

On Thu, Apr 14, 2005 at 11:08:21AM -0600, John Williams wrote:

: Good point. Another one is: how does the meta_operator determine the

: "identity value" for user-defined operators?

:

: (1,2,3,4,5) >>my_infix_op<< (3,2,4)

:

: Maybe we should say that the excess length is simply copied unchanged.

: But some might argue that not calling the op for each element would be

: cheating somehow. That's not my position, but I cannot think how to

: refute it right now, if you want the side-effects.

: Good point. Another one is: how does the meta_operator determine the

: "identity value" for user-defined operators?

:

: (1,2,3,4,5) >>my_infix_op<< (3,2,4)

:

: Maybe we should say that the excess length is simply copied unchanged.

: But some might argue that not calling the op for each element would be

: cheating somehow. That's not my position, but I cannot think how to

: refute it right now, if you want the side-effects.

One naive possibility is to supply one identity value per precedence level.

Then you could get 0 for addition and 1 for multiplication. Doesn't

really work though, given there are so many different kinds of addition

and multiplication lumped together. Arguably the identity value for %

is Inf.

Another approach to get the side effects would be to assume that

whatever "meta" code is actually calling the scalar operator is

smart enough to coerce ordinary undefs into "undef but identity"

or some such that each individual operator would know how to deal

with rather than generating an exception/undef.

: > What I ask myself is wether (1,2,3) »+ 1 should be a syntax error or just

: > a different form to express the :(List,Scalar:&) case. BTW, I know that

: > &infix_prefix_meta_operator:{'»'} isn't mentioned in A12.

: >

: > > I could be wrong, though; I can't find any support for it in the design docs.

We decided that binary ops should always just have »« on both sides,

since it's essentially just a single "dwim this" bit of information.

Basically, »« is just a flagrant value of "1".

: "Replicate dimensions" is specified in the first version of A3.

:

: The length issue was resolved on the mailing lists.

: Could someone add the ruling to S3 to answer this FAQ?

:

: I believe the fine points fall out like this:

:

: @a >>+<< 1 # replicate

: @a >>+<< (1) # replicate: (1) is still scalar

: @a >>+<< [1] # extend: [1] is an array (and will auto-deref)

Yes. Parens in scalar context do not automagically produce a list.

Comma is another matter, so

@a >>+<< (1,)

turns out to be the same as

@a >>+<< [1]

since there is no scalar comma operator in Perl 6.

All that being said, it's almost certainly the case that (1) is

a mistake. and should perhaps produce a warning: "Useless use of

parentheses" or some such. Not that we frown on useless use of

parentheses in general, since they're often clarifying precedence.

But nobody should be confused about the precedence of a simple term.

Larry

Apr 14, 2005, 1:08:21 PM4/14/05

to Thomas Sandlaß, perl6-l...@perl.org

I found where Damain explains the rule as basically "replicate dimensions,

extend lengths", using an "identity value" when extending the length.

<http://www.mail-archive.com/perl6-l...@perl.org/msg08304.html>

extend lengths", using an "identity value" when extending the length.

<http://www.mail-archive.com/perl6-l...@perl.org/msg08304.html>

On Wed, 13 Apr 2005, Thomas Sandlaß wrote:

> Brent 'Dax' Royal-Gordon wrote:

> > IIRC, it's f) (1,2,3,4,5) >>+<< (1,2,$identity,$identity,$identity),

> > where $identity's value is determined by a table something like this:

>

> In the case of &infix_circumfix_meta_operator:{'»','«'}:(List,List:&op)

> there's no "upgrade"---to use the S03 term. A simple "apply &op where

> the lists overlap and keep the rest of the longer one" suffices.

> That is (1,2,3,4,5) >>+<< (1,2) becomes (1+1, 2+2, 3, 4, 5). For

> &infix_circumfix_meta_operator:{'»','«'}:(List,Scalar:&op) the upgrade

> works by applying the operator with the scalar to all entries:

> (1,2,3,4,5) >>+<< 1 becomes (1+1, 2+1, 3+1, 4+1, 5+1).

Good point. Another one is: how does the meta_operator determine the

"identity value" for user-defined operators?

(1,2,3,4,5) >>my_infix_op<< (3,2,4)

Maybe we should say that the excess length is simply copied unchanged.

But some might argue that not calling the op for each element would be

cheating somehow. That's not my position, but I cannot think how to

refute it right now, if you want the side-effects.

> What I ask myself is wether (1,2,3) »+ 1 should be a syntax error or just

> a different form to express the :(List,Scalar:&) case. BTW, I know that

> &infix_prefix_meta_operator:{'»'} isn't mentioned in A12.

>

> > I could be wrong, though; I can't find any support for it in the design docs.

"Replicate dimensions" is specified in the first version of A3.

The length issue was resolved on the mailing lists.

Could someone add the ruling to S3 to answer this FAQ?

I believe the fine points fall out like this:

@a >>+<< 1 # replicate

@a >>+<< (1) # replicate: (1) is still scalar

@a >>+<< [1] # extend: [1] is an array (and will auto-deref)

~ John Williams

Apr 15, 2005, 5:10:33 AM4/15/05

to perl6-l...@perl.org

John Williams wrote:

> Good point. Another one is: how does the meta_operator determine the

> "identity value" for user-defined operators?

> Good point. Another one is: how does the meta_operator determine the

> "identity value" for user-defined operators?

Does it have to? The definition of the identity value---BTW, I like

the term "neutral value" better because identity also is a relation

between two values---is that $x my_infix_op $neutral == $x.

So the generic implementation that copies surplus elements is correct

with respect to the resulting value. You shouldn't expect the operator

beeing called as many times as there are elements in the bigger data

structure, though. It's called only for positions where both structures

have actual values. But that is the same as short-circuiting && and ||.

And somewhat the reverse of authreading from junctive values.

> I believe the fine points fall out like this:

>

> @a >>+<< 1 # replicate

> @a >>+<< (1) # replicate: (1) is still scalar

> @a >>+<< [1] # extend: [1] is an array (and will auto-deref)

I think they fall out naturally from typing and dispatch. But note

that the » « operator has three args. I haven't made the &op a dispatch

selector. If the my_infix_op from above needs to handle neutral elements

by itself just tell the dispatcher by defining

&infix_circumfix_meta_operator:{'»','«'}:(List,List,&my_infix_op:) and

construct the neutral elements when one of the list runs out of elements.

I hope the syntax I used does what I want to express. Note that in

:(List,List,&my_infix_op:) the first two elements are types while

&my_infix_op is a sub value. In that sense my &op was actually wrong

but it was nice for wording my sentence. So the generic name should read

&infix_circumfix_meta_operator:{'»','«'}:(List,List:Code) or perhaps

&infix_circumfix_meta_operator:{'»','«'}:(List,List:&) if & is considered

as the code sigil. Hmm, then we could also have :(@,@:&) meaning the

same type spec?

BTW, starting from these type specs I come (back) to the suggestion of using

» « for hypering function calls and/or their arguments. Has that been decided?

I'm not sure if specialisation on values is covered by the :() syntax.

E.g. one could implement &infix:<*>:(0,Any) to return 0 without evaluating

the Any term at all! But this needs either lazy evaluation in the functional

paradigma or code morphing 'x() * y()' to '(($t = x()) != 0) ?? $t * y() :: 0'

or some such. On assembler level this morphing reduces to an additional

check of a register for zero. But I'm not sure if the type system and the

optimizer will be *that* strong in the near future ;)

Regards

--

TSa (Thomas Sandlaß)

Apr 16, 2005, 9:15:50 PM4/16/05

to perl6-l...@perl.org

Thomas Sandlaß wrote:

> John Williams wrote:

>

>> Good point. Another one is: how does the meta_operator determine the

>> "identity value" for user-defined operators?

>

>

> Does it have to? The definition of the identity value---BTW, I like

> the term "neutral value" better because identity also is a relation

> between two values---is that $x my_infix_op $neutral == $x.

> John Williams wrote:

>

>> Good point. Another one is: how does the meta_operator determine the

>> "identity value" for user-defined operators?

>

>

> Does it have to? The definition of the identity value---BTW, I like

> the term "neutral value" better because identity also is a relation

> between two values---is that $x my_infix_op $neutral == $x.

One set of cases that doesn't seem to have come up in discussion:

(1, 3, 2) >>-<< (83, 84, 81, 80, 85)

Should this give

(-82, -81, -79, -80, -85)

as it would by hallucinating 0 (neither a left-identity nor left-neutral

element for subtraction strictly, but at least a natural left pivot

element), or

(-82, -81, -79, 80, 85)

as by hallucinating $neutral - $x == $x? This latter $neutral in fact

doesn't exist among ordinary numbers, and I would call it algebraically

unnatural: for all (other) $n,

$n - ($a + $b) == ($n - $a) - $b

or, as you increase $a by $b, $n - $a decreases by $b (a sort of

contravariance), but

$neutral - ($a + $b) == $a + $b == ($neutral - $a) + $b

! This violates algebraic relations I would prefer to rely on, both in

my own reasoning and that of the compiler and other program-handling

programs.

Best regards

Roger

Apr 18, 2005, 10:11:38 AM4/18/05

to perl6-l...@perl.org

Roger Hale wrote:

> One set of cases that doesn't seem to have come up in discussion:

>

> (1, 3, 2) >>-<< (83, 84, 81, 80, 85)

>

> Should this give

>

> (-82, -81, -79, -80, -85)

> One set of cases that doesn't seem to have come up in discussion:

>

> (1, 3, 2) >>-<< (83, 84, 81, 80, 85)

>

> Should this give

>

> (-82, -81, -79, -80, -85)

From an arithmetic point of view it should be exactly that. The

implementation might need to morph the code though, see below.

> as by hallucinating $neutral - $x == $x? This latter $neutral in fact

> doesn't exist among ordinary numbers, and I would call it algebraically

> unnatural: for all (other) $n,

>

> $n - ($a + $b) == ($n - $a) - $b

>

> or, as you increase $a by $b, $n - $a decreases by $b (a sort of

> contravariance), but

>

> $neutral - ($a + $b) == $a + $b == ($neutral - $a) + $b

>

> ! This violates algebraic relations I would prefer to rely on, both in

> my own reasoning and that of the compiler and other program-handling

> programs.

Me too! The thing is that the field of the real numbers is build on the

operators + and * which are associative and commutative. The neutral

elements are 0 and 1 respectively. The non-associative operators - and /

are defined in terms of the inverse elements. Thus $a - $b == $a + (-$b)

and $a / $b == $a * (1/$b) if $b != 0. We could also bring in $b**-1 as

another way to find the multiplicative inverse. But that just pulls in

yet another operator and the question which axioms apply to it and how

it is hyperated.

For user-defined numerical types---that is ones that provide +, *, -, /,

**, etc---I would hope that these axioms hold. Actually I hope that

there is a set of roles that define the standard numerics and enforce

sanity as far as that is possible via the class composition mechanics.

So coming back to your example, operator »-« would call -« on the RHS

and call »+« with the result. But I've no idea to which extent operator

» « is a special runtime operator versus a term re-writing at compile

time.

--

TSa (Thomas Sandlaß)

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu