Mutating methods

2004-03-10 Thread Juerd
Perlists,

In Perl 5, lc, lcfirst, quotemeta, uc and ucfirst don't mutate.
chomp and chop do mutate.

I imagine these will all be methods in Perl 6:

$foo.lc
$foo.quotemeta
$foo.chomp

I'd like a mutating version of lc, and a non-mutating version of chomp.
With some nice syntax, if possible.

If there isn't already such a thing in the making, I hereby suggest to
re-introduce C<.=>, to mean more or less the same as in Perl 5, but with
Perl 6's version of the C<.> operator.

In other words: C<$foo.lc> would not mutate and C<$foo.=lc> would.

$foo += 5  ===>  $foo = $foo + 5
$foo.=lc   ===>  $foo = $foo.lc

Makes sense to me.

Especially for C it would be nice for something like this:

@foo.sort  # returns sorted copy

versus

@foo.=sort  # sorts inline

I think this syntax reads better than Ruby's exclamation point
(foo.method!), because of the analogy with other mutating operators.

Please excuse me if this or something like this has already been taken
care of - I've searched for messages about it, but haven't found
anything.


Regards,

Juerd


Re: Mutating methods

2004-03-10 Thread Luke Palmer
Juerd writes:
> Perlists,
> 
> In Perl 5, lc, lcfirst, quotemeta, uc and ucfirst don't mutate.
> chomp and chop do mutate.
> 
> I imagine these will all be methods in Perl 6:
> 
> $foo.lc
> $foo.quotemeta
> $foo.chomp
> 
> I'd like a mutating version of lc, and a non-mutating version of chomp.
> With some nice syntax, if possible.
> 
> If there isn't already such a thing in the making, I hereby suggest to
> re-introduce C<.=>, to mean more or less the same as in Perl 5, but with
> Perl 6's version of the C<.> operator.

I believe this has been discussed before, and that people generally
liked it.  Maybe Larry even did (I seem to recall him saying something
positive about it -- but don't think he did just because I said so :-).
It seems likely that this will go in, though.

I'm in the mood for an exercise, so, here's how you implement it.

Let's say we have the Perl grammar:

grammar Perl 
{
# ...
has %.assignment_ops is protected;
rule assignment_expression {
 
$op:= (%.assignment_ops.keys())
$value := <%.assignment_ops{$op}{rule}>
{ 
$0 := %.assignment_ops{$op}{transform}($0)
if %.assignment_ops{$op}{transform}
}
}

rule method_call {
 <'.'> 
}
}

Or something.  I'm just pulling that out of my ear.

Then we'll derive our own grammar with the C<.=> operator in, and plunk
it into Perl's parser.

grammar DotEqualsPerl is Perl
{
submethod BUILD() {
.assignment_ops{'.='} = {
rule => //,
transform => {

Perl::assignment_expression.new(
lhs => .{assignment_lhs}, 
rhs => Perl::method_call.new(
term => .{assignment_lhs},
method => .{value},
)
)

},
};
}
}

Finally, hooking it into Perl.

use grammar DotEqualsPerl;

Again, this is quite presumptuous about the workings of the Perl::*
classes.  The Perl grammar will have to be extremely well documented.

The reason we couldn't just decalre it with C is because its
right hand side is not a usual expression.  That is:

$foo + bar;

Won't parse unless C is a declared sub, whereas:

$foo.bar;

Will always parse.

Luke


Re: Mutating methods

2004-03-10 Thread Brent \"Dax\" Royal-Gordon
Luke Palmer wrote:
The reason we couldn't just decalre it with C is because its
right hand side is not a usual expression.
Isn't that what macros are for?

macro infix:.= ($lhs, $rhs) is parsed(//) {
return Perl::assignment_expression.new(
lhs => $lhs,
rhs => Perl::method_call.new(
term   => $lhs,
method => $rhs,
)
);
}
TMTOWTDI, I suppose...

--
Brent "Dax" Royal-Gordon <[EMAIL PROTECTED]>
Perl and Parrot hacker
Oceania has always been at war with Eastasia.


Re: Mutating methods

2004-03-10 Thread Larry Wall
On Wed, Mar 10, 2004 at 05:39:33PM +0100, Juerd wrote:
: Perlists,
: 
: In Perl 5, lc, lcfirst, quotemeta, uc and ucfirst don't mutate.
: chomp and chop do mutate.
: 
: I imagine these will all be methods in Perl 6:
: 
: $foo.lc
: $foo.quotemeta
: $foo.chomp
: 
: I'd like a mutating version of lc, and a non-mutating version of chomp.
: With some nice syntax, if possible.
: 
: If there isn't already such a thing in the making, I hereby suggest to
: re-introduce C<.=>, to mean more or less the same as in Perl 5, but with
: Perl 6's version of the C<.> operator.

Except that C<.> isn't really a binary operator...

On the other hand, draft -1 of A12 has a conjectural

my Dog $dog .= new()

in it, and that's even further out there, since the .new on the right
would in fact be called on a $dog that is undefined!

: In other words: C<$foo.lc> would not mutate and C<$foo.=lc> would.
: 
: $foo += 5  ===>  $foo = $foo + 5
: $foo.=lc   ===>  $foo = $foo.lc
: 
: Makes sense to me.

Yes, but the fact that you had to change the spacing bothers me.

: Especially for C it would be nice for something like this:
: 
: @foo.sort  # returns sorted copy
: 
: versus
: 
: @foo.=sort  # sorts inline
: 
: I think this syntax reads better than Ruby's exclamation point
: (foo.method!), because of the analogy with other mutating operators.

Well, I'd like to reserve postfix:! for factorial in any event.  :-)

The basic problem with .= shows up when you do put the spaces in:

@foo .= sort()

That makes it look as though sort is a subroutine, and it's not.
That's a direct result of the fact that C<.> is not really a binary
operator.  Rather, it's a kind of "operator sigil" that introduces
a unary postfix operator.  Method calls are really unary postfix
operators that happen to be able to take extra arguments.

And because the op= syntax is really built for binary operators, it
doesn't totally work for unary operators.  Take another unary postfix
operator, for instance, an array subscript:

@array[$x]

you can't just up and say

@array[=$x]

to mean

@array = @array[$x]

to turn it into a mutating operator, because the [$x] wants to
function as a unit, and the = breaks that up.  Similarly, ".sort"
wants to function as a unit, but the = breaks that up, visually and
semantically.

However, having said all that, it turns out that A12 will also introduce
other "dot" variants:

$obj.?method# call method if exists, or return undef (0 or 1)
$obj.*method# call all base class methods of that name (0 or more)
$obj.+method# call all base class methods of that name (1 or more)

So a .=method syntax is not so farfetched.  It analogies to +=, but it's
really still just a prefix to a unary postfix operator, like the other
dot variants.  The interesting question with all of these "dots" is
where spaces are allowed or disallowed.  One could make a case that
people will want to write

my Car $obj .= new()

rather than being forced to write

my Car $obj .=new()

It could even be argued that, in the case of this particular operator,
the = is functioning as part of the name, as the ! does in Ruby.  So
if (hypothetically) we allow a space after the ordinary dot

@array . sort

then we could also allow things like:

@array . =sort
$obj   . *initialize
$obj   . ?maybe

But I dislike

$variable . meth()

for the same reason I dislike

$variable .= meth()

because it makes meth look like a subroutine call when it isn't.  Regardless
of how fancy they get, method calls are still postfix operators.  So I'm
inclined to say that the space is only optional before the dot, and you have
to say

@array .sort
@array .=sort
$obj   .*initialize
$obj   .?maybe

But that still makes

my Cat $tom .=new()

pretty ugly.  Unfortunately we can't just use topicalization to say

my Cat $tom = .new()

because most people won't expect simple assignment to break their
current topic.

So another option is to replace = with something that I set the
topic for the right side.  If we used .= for that, then you'd have
to write

@array .= .sort
my Cat $tom .= .new()

Doubtless the first would get shortened to

@array.=.sort

That does admit to constructs like

$foo .= .*bar

which would assign $foo a list of all the return values of $foo.*bar, or

$foo .= .?maybe

which would presumably replace $foo with an undefined value if
it couldn't find $foo.maybe.  Those don't seem terribly useful as
mutators though.  They'd be much clearer written out long.

Another approach would be to have some kind of "microtopic" that
represented the left side of an ordinary assignment.  Suppose for
the sake of argument that the microtopic is ^.  Then you could write

@array = ^.sort;

and a constructor would be

my Kanga $roo = ^.new()

But that introduces a new concept that doesn't really generalize well.
So forget that.

Yet another approach is to

Re: Mutating methods

2004-03-10 Thread Larry Wall
On Wed, Mar 10, 2004 at 11:19:52AM -0800, Brent Dax Royal-Gordon wrote:
: Luke Palmer wrote:
: >The reason we couldn't just decalre it with C is because its
: >right hand side is not a usual expression.
: 
: Isn't that what macros are for?
: 
: macro infix:.= ($lhs, $rhs) is parsed(//) {

Methods are really postfix operators, so that would probably be
something more like:

macro postfix:.= ($lhs, $parsetree)
is parsed(/?  /) {

That's presuming we allow whitespace after the . and .= ops.

(Also, these days you have to say  to collect the results into $0.)

Larry


Re: Mutating methods

2004-03-10 Thread Luke Palmer
Larry Wall writes:
> On Wed, Mar 10, 2004 at 11:19:52AM -0800, Brent Dax Royal-Gordon wrote:
> : Luke Palmer wrote:
> : >The reason we couldn't just decalre it with C is because its
> : >right hand side is not a usual expression.
> : 
> : Isn't that what macros are for?
> : 
> : macro infix:.= ($lhs, $rhs) is parsed(//) {
> 
> Methods are really postfix operators, so that would probably be
> something more like:
> 
> macro postfix:.= ($lhs, $parsetree)
>   is parsed(/?  /) {
> 
> That's presuming we allow whitespace after the . and .= ops.
> 
> (Also, these days you have to say  to collect the results into $0.)

Hooray!  That was something I had been worried about.

But C doesn't seem to fit visually.  What's "questionable" about
that?

I can think of a couple that I like better:

<^foo>
<*foo>

<^foo> is my favorite at the moment (even though <*foo> is more
visually pleasing), because it looks like it's transferring the
information ^up^ in the parse tree.

Luke


Re: Mutating methods

2004-03-10 Thread Damian Conway
Luke Palmer wrote:

Hooray!  That was something I had been worried about.

But C doesn't seem to fit visually.  What's "questionable" about
that?
Nothing questionable, but
everything hypothetical:
 captures to the
$?foo  hypothetical variable
Damian


Re: Mutating methods

2004-03-10 Thread Larry Wall
On Wed, Mar 10, 2004 at 12:42:00PM -0700, Luke Palmer wrote:
: > (Also, these days you have to say  to collect the results into $0.)
: 
: Hooray!  That was something I had been worried about.
: 
: But C doesn't seem to fit visually.  What's "questionable" about
: that?

It's questionable insofar as it's hypothetical.  It maps to $?foo,
which is the name of the (current value of the) capture within any
interior closure:

/ { say "Guessing $?foo for the moment..."  } /

: I can think of a couple that I like better:
: 
: <^foo>
: <*foo>
: 
: <^foo> is my favorite at the moment (even though <*foo> is more
: visually pleasing), because it looks like it's transferring the
: information ^up^ in the parse tree.

But $^foo and $*foo mean very different things from hypotheticals.

And in a real sense $?foo is passing guessed information *down*
the match.  The guesses only turn out "right" if you get all the way
to the bottom successfully.  (That's from the point of view that
you recurse deeper to check anything to the right in a regex, even
when syntactically it's shallower.)

Larry


Re: Mutating methods

2004-03-10 Thread Luke Palmer
Larry Wall writes:
> On Wed, Mar 10, 2004 at 12:42:00PM -0700, Luke Palmer wrote:
> : I can think of a couple that I like better:
> : 
> : <^foo>
> : <*foo>
> : 
> : <^foo> is my favorite at the moment (even though <*foo> is more
> : visually pleasing), because it looks like it's transferring the
> : information ^up^ in the parse tree.
> 
> But $^foo and $*foo mean very different things from hypotheticals.
> 
> And in a real sense $?foo is passing guessed information *down*
> the match.  The guesses only turn out "right" if you get all the way
> to the bottom successfully.  (That's from the point of view that
> you recurse deeper to check anything to the right in a regex, even
> when syntactically it's shallower.)

Hmm... that makes sense.

It doesn't feel right, though.  After all, we don't say:

($minutes, $seconds) = m/ (? \d\d ) : (? \d\d ) /;

Even though they only stay matched if they get to the end without
backtracking.  Capturing (this is really just a clever notation for
captures) is usually about communicating information I of the
match: to the parent rule, to the the calling scope.

As you showed in your reply about C<.=>:

macro postfix:.= ($lhs, $parsetree)
is parsed(/?  /) 
{ ... }

There's nothing about C that makes me think that these are being
stored.

I understand the association with C<$?foo>.  But most of the time, when
I'm writing a grammar, I'm catching these rules in order to stick them
in the parse tree, not to do tests on them later on in the rule.  The
very essence of rules is hypotheticality, where nothing is permanent
until it gets to the end.  I don't think we need a special marker that
says "these do that, too."

Luke


Re: Mutating methods

2004-03-10 Thread Damian Conway
Luke Palmer wrote:

I understand the association with C<$?foo>.  But most of the time, when
I'm writing a grammar, I'm catching these rules in order to stick them
in the parse tree, not to do tests on them later on in the rule.  The
very essence of rules is hypotheticality, where nothing is permanent
until it gets to the end.  I don't think we need a special marker that
says "these do that, too."
We need the marker to distinguish between hypothetical captures to internal 
variables:

	/ $?foo:=(abc) $?bar:=(def) /

and non-hypothetical captures to external variable:

	/ $foo:=(abc) $bar:=(def) /

And since subrules that capture always capture to hypotheticals, we need the 
same marker there.

Damian



Re: Mutating methods

2004-03-10 Thread Brent \"Dax\" Royal-Gordon
Damian Conway wrote:
/ $foo:=(abc) $bar:=(def) /
Am I misreading, or are you suggesting that $foo may contain 'abc' after 
running this example, even if the match wasn't successful?

--
Brent "Dax" Royal-Gordon <[EMAIL PROTECTED]>
Perl and Parrot hacker
Oceania has always been at war with Eastasia.


Re: Mutating methods

2004-03-10 Thread Damian Conway
Brent "Dax" Royal-Gordon wrote:

/ $foo:=(abc) $bar:=(def) /
Am I misreading, or are you suggesting that $foo may contain 'abc' after 
running this example, even if the match wasn't successful?
No. I re-checked with Larry this morning and he confirmed that all bindings in 
rules only "stick" if the rule as a whole succeeds.

What I was trying (obviously rather ineptly ;-) to point out is that we have 
to be able to differentiate between the the match object's own internal 
hypothetical variables ($?foo, $?bar, @?baz) and any 
external-but-temporarily-hypothesized variables ($foo, $bar, @baz).

The syntax we've chosen to do that requires the use of "?" as a secondary 
sigil on internal variables. So, since named subrules that capture always 
capture to internal variables, it's natural and consistent to use "?" to 
indicate capturing subrules as well.

Damian


RE: Mutating methods

2004-03-10 Thread matt
I was thinking along the lines of...

String $foo = "hello";
$foo.scramble!
print "$foo\n";
$foo = "hello"
print $foo.scramble ~ "\n";
print $foo;

OUTPUT (or close):
elhlo
hloel
hello

Also, along these same things.. is there a way to apply a method to all
variables/objects of a certain type (e.g. String, Num, etc)?  Taking the
above example.. being able to write a method called "Scramble" that can be
called as a method from any String type.



Re: Mutating methods

2004-03-10 Thread Larry Wall
On Wed, Mar 10, 2004 at 10:46:05PM -0500, matt wrote:
: I was thinking along the lines of...
: 
: String $foo = "hello";
: $foo.scramble!

That would be $foo.=scramble in the current scheme of things.

: print "$foo\n";
: $foo = "hello"
: print $foo.scramble ~ "\n";
: print $foo;
: 
: OUTPUT (or close):
: elhlo
: hloel
: hello
: 
: Also, along these same things.. is there a way to apply a method to all
: variables/objects of a certain type (e.g. String, Num, etc)?  Taking the
: above example.. being able to write a method called "Scramble" that can be
: called as a method from any String type.

Two ways, actually.  You can 'reopen" the String class and add the method:

class String is extended {
method scramble () returns String {...}
}

or if you consider that underhanded, you can define a multi-sub:

multi sub *scramble (String $s) returns String {...}

If you call that as a method, and there is no ordinary scramble method,
it will "fail soft" to looking for a scramble multimethod, and end up
calling your definition.  Or you can just call it directly as a function:

scramble("hello")

Larry


RE: Mutating methods

2004-03-10 Thread Austin Hastings


> -Original Message-
> From: Damian Conway [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, 10 March, 2004 09:48 PM
> To: [EMAIL PROTECTED]
> Subject: Re: Mutating methods
>
>
> Brent "Dax" Royal-Gordon wrote:
>
> >> / $foo:=(abc) $bar:=(def) /
> >
> > Am I misreading, or are you suggesting that $foo may contain
> 'abc' after
> > running this example, even if the match wasn't successful?
>
> No. I re-checked with Larry this morning and he confirmed that
> all bindings in
> rules only "stick" if the rule as a whole succeeds.
>
> What I was trying (obviously rather ineptly ;-) to point out is
> that we have
> to be able to differentiate between the the match object's own internal
> hypothetical variables ($?foo, $?bar, @?baz) and any
> external-but-temporarily-hypothesized variables ($foo, $bar, @baz).
>
> The syntax we've chosen to do that requires the use of "?" as a secondary
> sigil on internal variables. So, since named subrules that capture always
> capture to internal variables, it's natural and consistent to use "?" to
> indicate capturing subrules as well.

Isn't this backwards?

That is, from the above I get the impression that $?foo is TRANSIENT, while
capturing to $foo will (eventually) be PERMANENT.

So  is just a shorthand way of saying

   $?foo := 

right?

Is hypo-space a flat entity, or do hypothetical scopes nest? If so, do we
have to use repeated ?'s, or will just one suffice?

That is:

   rule bar {...}
   rule baz {...}
   rule foo {...bar...baz...}

   if /  ...  ... { $?foo.?baz ... $?baz } .../
OR
   if /  ...  ... { $?foo.baz ... $?baz } .../
OR
   if /  ...  ... { $?baz ... $?otherbaz } .../


=Austin



Re: Mutating methods

2004-03-10 Thread Larry Wall
On Thu, Mar 11, 2004 at 01:09:59AM -0500, Austin Hastings wrote:
: 
: 
: > -Original Message-
: > From: Damian Conway [mailto:[EMAIL PROTECTED]
: > Sent: Wednesday, 10 March, 2004 09:48 PM
: > To: [EMAIL PROTECTED]
: > Subject: Re: Mutating methods
: >
: >
: > Brent "Dax" Royal-Gordon wrote:
: >
: > >> / $foo:=(abc) $bar:=(def) /
: > >
: > > Am I misreading, or are you suggesting that $foo may contain
: > 'abc' after
: > > running this example, even if the match wasn't successful?
: >
: > No. I re-checked with Larry this morning and he confirmed that
: > all bindings in
: > rules only "stick" if the rule as a whole succeeds.
: >
: > What I was trying (obviously rather ineptly ;-) to point out is
: > that we have
: > to be able to differentiate between the the match object's own internal
: > hypothetical variables ($?foo, $?bar, @?baz) and any
: > external-but-temporarily-hypothesized variables ($foo, $bar, @baz).
: >
: > The syntax we've chosen to do that requires the use of "?" as a secondary
: > sigil on internal variables. So, since named subrules that capture always
: > capture to internal variables, it's natural and consistent to use "?" to
: > indicate capturing subrules as well.
: 
: Isn't this backwards?
: 
: That is, from the above I get the impression that $?foo is TRANSIENT, while
: capturing to $foo will (eventually) be PERMANENT.

$?foo is exactly as transient as the $0 in which it resides.  So it
really depends on how long $0 lives outside the regex.  In the case
of a returned parse tree it could live a very long time.

: So  is just a shorthand way of saying
: 
:$?foo := 
: 
: right?

Yes.  The ? is actually serving as a scope marker telling Perl not
to scan outside of the current regex for a variable of that name.
If you consider each rule to be its own package, it's kind of an "our"
declaration within the rule.

: Is hypo-space a flat entity, or do hypothetical scopes nest?

Um, the namespace inside a particular rule is flat, just as the
namespace inside a package is flat.  That doesn't mean that your code
won't visit those variables in whatever order it jolly well pleases.
Dynamically speaking, every assertion in a regex is recursively matched "inside"
the results of previous successful assertions, regardless of the
lexical structure of the rule.  You're often in situations where dynamically
you're going down recursively, while in terms of where you are in the
match, you're going out of brackets or parens.  It has to be that way,
or you could never backtrack into a set of brackets or parents.

But once a subrule is matched, all its ? names are bundled up into
a hash in the single "$0"-ish object that becomes aliased (at least
temporarily) to the $?foo in the outer rule.  The keys of that hash are
flat for all the names in the particular rule, though of course some
of the values may be nested $0 results from subrules.  So effectively
you end up with a hash of hash of hash of hash  representing the
entire syntax tree.  But any given rule can't produce more than one
level of hash (without doing something freaky like rewriting your
hash entries inside a closure).

: If so, do we
: have to use repeated ?'s, or will just one suffice?
: 
: That is:
: 
:rule bar {...}
:rule baz {...}
:rule foo {...bar...baz...}
: 
:if /  ...  ... { $?foo.?baz ... $?baz } .../
: OR
:if /  ...  ... { $?foo.baz ... $?baz } .../
: OR
:if /  ...  ... { $?baz ... $?otherbaz } .../

Well, you don't need "?" to go down the syntax tree, since each $0
can behave as a hash.  You don't subscript hashes using "." either.
You subscript hashes with {...} historically, or these days, «...»,
when you want constant subscripts.  So what you're looking for is
something like:

if /  ...  ... { $?foo{'baz'} ... $?baz } .../

or

if /  ...  ... { $?foo«baz» ... $?baz } .../

or even:

if /  ...  ... { $0«foo»«baz» ... $0«baz» } .../

Oh, and since the current $0 is actually the topic of any closure,
you can also probably say

if /  ...  ... { .«foo»«baz» ... .«baz» } .../

as an analog to

if /  ...  ... { .{'foo'}{'baz'} ... .{'baz'} } .../

That's presuming we keep the rule that scalars don't have to include
the sigils.  For an array you'd still have to say:

if / @?things:=[ () ,? ]+ { ... [EMAIL PROTECTED] ... } /

or

if / @?things:=[ () ,? ]+ { ... [EMAIL PROTECTED] ... } /

But then it's usually easier just to say

if / @?things:=[ () ,? ]+ { ... @?things ... } /

which means exactly the same thing.

Larry