[% setvar title Generalize %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/

TITLE

Generalize =~ to a special "apply-to" assignment operator

VERSION

   Maintainer: Nathan Wiger <nate@wiger.org>
   Date: 29 Aug 2000
   Last-Modified: 16 Sep 2000
   Mailing List: perl6-language-regex@perl.org
   Number: 170
   Version: 2
   Status: Frozen

ABSTRACT

Currently, =~ is only available for use in specific builtin pattern matches. This is too bad, because it's really a neat operator.

This RFC proposes a simple way to make it more general-purpose.

NOTES ON FREEZE

Probably the only way this could be implemented is if RFC 164 was also implemented, freeing =~ for use as a more general-purpose operator. Indeed, a main point of this RFC is to provide a means for a backwards-compatible syntax for regex's.

Unlink RFC 164, most people I heard from liked this. Some criticized it as being too sugary, since this:

   $string =~ quotemeta;    # $string = quotemeta $string;

Is not as clear as the original. However, there is fairly similar precedent in:

   $x += 5;                 # $x = $x + 5;

And to me it seems to be quite clear that quotemeta is acting on $string in the above example, even when you take into account =~'s current binding meaning (perhaps more so, in fact).

DESCRIPTION

First off, this assumes RFC 164. Second, it requires you drop any knowledge of how =~ currently works. Finally, it runs directly counter to RFC 139, which proposes another application for =~.

This RFC proposes a simple use for =~ as a generic "apply-to" operator. When used, any values on the left side of the expression are implicitly passed to the end of the right-side expression. What this means is that an expression such as this:

   $value = dostuff($arg1, $arg2, $value);

Could now be rewritten as:

   $value =~ dostuff($arg1, $arg2);

And $value would be implicitly transferred over to the right side as the last argument. It's simple, but it makes what is being operated on quite obvious.

This enables us to rewrite the following constructs:

   $string = quotemeta($string);
   @array = reverse @array;
   ($name) = split /\s+/, $name;
   @vals = sort { $a <=> $b } @vals;
   @file = grep !/^#/, @file;

   $string = s/\s+/SPACE/, $string;    # RFC 164
   $matches = m/\w+/, $string;         # RFC 164
   @strs = s/foo/bar/gi, @strs;        # RFC 164

As the shorter and more readable:

   $string =~ quotemeta;
   @array =~ reverse;
   ($name) =~ split /\s+/;
   @vals =~ sort { $a <=> $b };
   @file =~ grep /!^#/;

   $string =~ s/\s+/SPACE/;            # looks familiar
   $string =~ m/\w+/;                  # this too [1]
   @strs =~ s/foo/bar/gi;              # cool extension

It's a simple solution, true, but it has a good amount of flexibility and brevity. It could also be the case that multiple values could be called and returned, so that:

   ($name, $email) = special_parsing($name, $email);

Becomes:

   ($name, $email) =~ special_parsing;

Again, it's simple, but seems to have useful applications. One nice thing is that in many (most?) situations it appears to be working very much like =~ currently works with regex's (from a user perspective).

Finally, note this can only work with functions and function-like constructs. An attempt to do something like this:

   $x =~ 5 +;

Should definitely remain a syntax error.

Possible addition of ~= operator

A symmetric operator, ~=, was proposed informally on the list which would left-pad the argument list:

    $stuff =~ dojunk(@args);   # $stuff = dojunk(@args, $stuff);
    $stuff ~= dojunk(@args);   # $stuff = dojunk($stuff, @args);

but the consensus that I received was about 50/50: half liked it, half thought it was too confusing. Even though we don't have a bitnot= operator currently, creating something that looks like one but acts completely differently is probably not a good idea.

If something like this was included, it would probably be best to go with another operator, like =^:

    $stuff =~ dojunk(@args);   # $stuff = dojunk(@args, $stuff);
    $stuff =^ dojunk(@args);   # $stuff = dojunk($stuff, @args);

But that's awfully close to ^=. Hmmm. Regardless, this operator is unlikely to be used nearly as widely since Perl functions usually take the argument to act on in the last position.

IMPLEMENTATION

Simplistic (hopefully). Should just involve stacking values onto a function's argument list.

MIGRATION

This introduces new functionality, which allows backwards compatibility for regular expressions. As such, it should require no special translation of code. This RFC assumes RFC 164 will be adopted (which it may not be) for changes to regular expressions.

NOTES

[1] That m// one doesn't quite work right, but that's a special case that I would suggest should be caught by some other part of the grammar to maintain backwards compatability (like bare //).

REFERENCES

RFC 164: Replace =~, !~, m//, s///, and tr/// with match(), subst(), and trade()

RFC 139: Allow Calling Any Function With A Syntax Like s///

Bart Lateur's suggestion of using the term "apply-to": www.mail-archive.com