What are the consequences of this in language design? Well, it means not
every new piece of functionality requires a new operator. Instead, consider
a method. Its an actual word.
Stemming the tide of new grammar and operators heads off another
problem, typos becoming meaningful. The more operators you have, the more
chance that this sort of thing:
if $num1 === $num2 {
...
will be hard to find. Was it a typo or did they really mean to do a shallow
object comparison?
Instead of introducing new built-in functions they can be done as methods.
This reduces core namespace pollution. Think of the core like a big CPAN
module. Every built-in is like an exported function. Every word used as a
built-in is one that noone else can safely use for something else in their
own code.
If you want a tactile grasp of the "Everything is an object" concept, try
some Ruby.
Many pieces of edge functionality which are useful but would have been
rejected because they don't really warrent a new built-in or operator can be
put in as methods. For example, in Ruby you can alter the default value of
a hash like so:
h = {"foo" => 42};
h.default = "wibble";
# Prints 'wibble' rather than undef.
print h["bar"];
Isn't that neat? Not important enough to warrent a new built-in, but
something nice to have in your toolbox.
How many times have you done this in perl:
print grep defined, @array;
in Ruby, its just this:
print array.compact
I find myself doing this alot:
$string =~ s/^\s+//;
$string =~ s/\s+$//;
in Ruby:
string.strip!
Ruby can add neat little features without long deliberations about the
impact on language growth and backwards compatibilty because they have the
ability to add methods to core types.
A flip through the Ruby builtin methods is nice for building up some envy. :)
http://www.rubycentral.com/book/builtins.html
Sometimes you do need to use an operator or built-in. Usually to make data
transformations flow nicely:
@foo = join "\n", map { ... } grep { ... } sort @bar;
the concept can be reversed:
@foo = @bar.sort.grep(...).map(...).join("\n");
but is that Perlish?
Or you will commonly use the operator on expressions rather than variables.
1 + 2 == 3
would suck as:
(1 + 2).eq 3
There's lots of reasons to use an operator or built-in instead of a method,
but remember to make the consideration first. Don't go grammar happy.
In closing: Consider a method rather than a built-in or operator.
Everything is an object. Tattoo it on your forehead today.
--
Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One
Do you actually think about what you are saying or is it an improvisational
game of Mad Libs that you play in your head?
If you want a tactile grasp of Perl 6, try some Ruby. But I'll be saying
a lot more on that later...
> A flip through the Ruby builtin methods is nice for building up some envy. :)
> http://www.rubycentral.com/book/builtins.html
I vaguely object to calling them builtins, as I've objected to similar
concepts in Perl 6. They aren't *built in* to the language - you could
add another method and the parser wouldn't give a damn - they are
methods of the standard libraries that ship with Ruby. This
distinction is important, despite what Damian would have you believe.
In the same way, the specification of C-as-a-language, its syntax and
operators and the stuff that makes it look, act and feel like C, is
agnostic of the C standard library. (Even though "ANSI C" specifies
both, they are seperable.) This seperability is something I'd like
to see thought about a lot more in Perl 6.
> There's lots of reasons to use an operator or built-in instead of a method,
> but remember to make the consideration first. Don't go grammar happy.
Yes, yes, yes. This is what I've been trying to say for a while.
--
"If that makes any sense to you, you have a big problem."
-- C. Durance, Computer Science 234
The problem with this worldview is that you end up with horrible
asymmetries suh as:
> 1 + 2 == 3
>
> would suck as:
>
> (1 + 2).eq 3
There is a difference between verbs and noun. Sometimes you don't want
to associate a verb with an object: you want to associate it with the
subject:
"the cat sat on the mat"
is that
the_mat.sat_on(the_cat)
or
the_cat.sat_on(the_mat)
or
sat_on(the_cat, the_mat)
All of those seem to loose the preposition. Are sat_on and sat_beside
really completely independent things? Under perl's grammar: yes. Seems
to me that identifiers have a complex fusional word-structure, which is
opaque to the grammar of the language. The more structure you can
expose into the parse tree, the more powerful will be manipulations on
that tree.
Perl6 allows there different worldviews, but we need to make sure that
verbs are as entensible as nouns. Multimethods are wonderful things.
Don't add something as a method if it makes more sense as a
multi-method. Don't use an asymmetric method syntax for a
symmetric concept.
To say "everything is an object: extend by adding methods" elevates
Nouns over Verbs. And it completely ignores all the other parts of
the language. Sometimes people seem to think that the only alternative
is to add built-ins: but this really shouldn't be the case -- not in a
language as powerful as Perl6.
Dave.
Verbs are almost always associated with their subject in OO languages,
so I don't see where you're coming from.
> "the cat sat on the mat"
> is that
> the_mat.sat_on(the_cat)
Nope.
> or
> the_cat.sat_on(the_mat)
This one. If you called
$cat->sit_on($mat);
in Perl 5, who would you expect to be sitting on what?
> All of those seem to loose the preposition. Are sat_on and sat_beside
> really completely independent things?
$x.sat_beside($y);
$y.sat_beside($x);
Hey, it's just like English, but with more punctuation! And we know how
well people deal with punctuation!
> Under perl's grammar: yes.
Well, no, as I've just demonstrated.
--
It's a testament to the versatility of the human mind that we're so able
to compensate for our own incompetence.
- Darrell Furhiman
I agree 98% with your argument (especially re: grammar extensions), and
it was very well explained. The 02% is this:
First, universal operators and universal methods both pollute the
useful (programmer) namespace to nearly the same extent. It's just one
pollution is alphanumeric, the other is punctuational. For example,
'.eq' and '==' are (abstractly) just multimethods upon their
invocant/arguments, tho one has a funny-charactered name. Either way,
you're defining something that everyone has to remember, and that
people can't use for their own purposes.
Second, one person's trivial feature is another person's dream come
true. C<given>, for example, or vectorops. So the object-based
argument can be used to support or crush pretty much *anything*,
depending solely on POV. Or put any feature in or out of the "builtin"
list, for that matter. It's only our opinions, we can't really justify
them except through our own experiences.
So I don't think we have an alternative to just plain arguing over each
such proposal as it arrives, which we *hope* will produce the overall
correct results as a sheer accident of demographics.
MikeL
(I don't *really* think '===' is critically important, though as an
obviously symmetric binary operation it has some minor charm. I tend
to use the concept somewhat frequently, but others don't, so it
probably doesn't pass the bar.)
> Verbs are almost always associated with their subject in OO languages,
> so I don't see where you're coming from.
Actually, the important part of it was the 3rd option (the multimethod):
sometimes the association is symmetrical. I was pointing out that the
concept -> OO mapping is very lossy.
> > All of those seem to loose the preposition. Are sat_on and sat_beside
> > really completely independent things?
> > Under perl's grammar: yes.
> Well, no, as I've just demonstrated.
I must have missed it in your post. I saw no Perl grammar that sees the
commonality between .sit_on and .sit_beside. Perl thinks of them as two
independent methods (The programmer can choose to implement them
with some commonality). We seem happy to structure objects (using
attributes, etc.), but verbs remain flat and uninteresting: just arbitrary
names.
As a result of this lack of expressiveness in the grammar, we find ourselves
saying that if a concept doesn't fit the "everything is an object"
worldview,
then it needs to be a built-in. I'm not saying that I have an alternative:
just
explaining why we keep proposing built-ins instead of using the methods
on objects.
Dave.
Most of the methods are not universal. For example:
$foo.compress
would be in the String class, not Object (or whatever we're calling the
equivalent of UNIVERSAL today), and only inherited by those objects which
wish to masquerade as strings.
%hash.default
is in the Hash class.
The sameas example:
$obj.sameas $obj2
would be in the Object class and would pollute. Using Ruby as a rough
guide, there aren't many of those.
http://www.rubycentral.com/book/ref_c_object.html
--
Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One
One disease, long life. No disease, short life.
> On Wed, Dec 11, 2002 at 04:56:03PM -0800, Michael Lazzaro wrote:
>> First, universal operators and universal methods both pollute the
>> useful (programmer) namespace to nearly the same extent.
>
> Most of the methods are not universal. For example:
>
> $foo.compress
>
> would be in the String class, not Object (or whatever we're calling the
Right, I just wanted to clarify. Because deciding between, say:
$foo.sameas($bar); # universal method
$foo === $bar; # universal operator
would be a false savings. If a method _is_ universal, especially if
it's symmetric, it might be an OK candidate for a builtin or operator.
And if it isn't universal, I can see (almost) no justification for
wasting an op on it, no matter how common it is.
(Again, though, C<$foo.id == $bar.id> is OK by me.)
MikeL
Bingo. And things like "purge" only apply to arrays and lists, hence...
--
"MSDOS didn't get as bad as it is overnight -- it took over ten years
of careful development."
(By dmeg...@aix1.uottawa.ca)
Welllll... yes and no. You can make the same argument for operators
upon scalars, for example, since 'scalar' is arguably no more universal
than 'array'. And we could easily use that argument to remove *all*
builtins, period:
print $i; # ILLEGAL; use $STDOUT.print($i) or $i.print (?)
reverse @a; # ILLEGAL; use @a.reverse;
map {...} @a; # ILLEGAL; use @a.map({...});
sort {...} @a; #
keys %h; # ...etc...
in which case right-to-left pipes go away entirely, if we want them to.
But if we decide to allow _some_ array-based builtins (or even if we
just make them all methods of Array and Hash) then deciding _which_
ones to include falls under the YMMV argument -- we have to guess. So
purge or C<part> is valid to at least *consider* for inclusion.
My point was that in lang design it's possible to make a convincing but
purely philosophical argument for or against anything (postmodernism?),
and as such it will never be possible to declare hard-and-fast rules
for what should or should not be a builtin. We just have to fight it
out on a case-by-case basis.
MikeL
(And yes, I'm aware that (1 <= N <= 5) of those are going away already.)
MikeL
Now you're getting the idea.
--
Feed me on TOASTIES! There's no HALL for PHILOSOPHERS ON FRIDAYS.
- Henry Braun is Oxford Zippy
> david...@fast-chip.com (Dave Whipp) writes:
>> There is a difference between verbs and noun. Sometimes you don't want
>> to associate a verb with an object: you want to associate it with the
>> subject:
>
> Verbs are almost always associated with their subject in OO languages,
> so I don't see where you're coming from.
>
>> "the cat sat on the mat"
>> is that
>> the_mat.sat_on(the_cat)
>
> Nope.
>
>> or
>> the_cat.sat_on(the_mat)
>
> This one. If you called
> $cat->sit_on($mat);
> in Perl 5, who would you expect to be sitting on what?
C<< $cat.sat_on($the_mat) >> is surely a predicate, returning true or false
depending on whether the cat is on the mat or not. But unless I can
write it as C<< $cat.sat_on?($the_mat) >> then I'd be very cross with
anyone who didn't call the method C<< is_sat_on >>.
--
Piers
"It is a truth universally acknowledged that a language in
possession of a rich syntax must be in need of a rewrite."
-- Jane Austen?
> We seem happy to structure objects (using
> attributes, etc.), but verbs remain flat and uninteresting: just
> arbitrary names.
>
> As a result of this lack of expressiveness in the grammar, we find
> ourselves saying that if a concept doesn't fit the "everything
> is an object" worldview, then it needs to be a built-in.
This is a good point.
I think that to a certain extent, this can be handled with properties.
It's just that we haven't gotten used to thinking this way, yet.
Already we've borrowed the Spanish ser/estar model (is/but) to
differentiate between permanent and transient characteristics.
(Then I unpacked my adjectives... He was a hairy bear. He was a scary
bear...)
Prepositions are kind-of-there with properties, and with the
specially-named-blocks (first, last, etc.) for order-prepositions.
The cat sat on the TV.
The cat sat near the TV.
The cat sat beside the TV.
The @#$@#$ cat sat in front of the TV.
Currently, that's going to be
$cat.sit($TV);
$cat.sit($TV but 'near');
$cat.sit($TV but 'beside');
and:
$cat = $cat but '@#$@#$';
$cat.sit($TV but 'in front of');
Some adverbial work has been put into blocks-as-arguments, as with sort
(sort these *ascendingly*). But in general, adverbs aren't obviously
there, yet.
(Lolly Lolly Lolly, get your adverbs here!
Quickly quickly quickly, get your adverbs here!
Slowly surely really, learn your adverbs here!)
Another use of adverbs is as intensifiers.
$x = 'useless' but 'necessary';
$y = but very 'necessary'; # How do you say this, really?
$z = but very very 'necessary';
If there were some (automatic) mechanism that ordered objects according
to their necessity (like the new part() built-in!!), the intensifiers
should affect the order:
sub do_stuff(@honeydew)
{
my (@a, @b, @c) = part
{
when necessary ;
default ;
when optional is reversed; #? syntax
} @honeydew;
do_list(@a);
do_list(@b);
do_list(@c);
}
Ideally, the @a list and the @c list should honor the intensifiers and
be ordered such that the very-very necessary come before the very
necessary come before the necessary come before the not-very ...
Likewise, adverbs as verb modifiers provides a way to avoid having
several functions with similar behaviors.
C<sort> does this with a block: cool. But adverbs like securely,
surely, quickly, and dynamically don't necessarily translate well to
blocks, and they don't set context.
Perhaps we need adverbial scope?
# From LWP
# Pass request to the user agent and get a response back
my $res = $ua->request($req) securely;
... somewhere in the bowels of LWP6? ...
my $pcl = "http";
when securely { $pcl = "https" };
Thus anyone could "suggest" behavior, and it may-or-may-not be acted
upon in the subsequent code. But the overall activity (the verb, which
is to say the subs/methods) gets done, regardless.
Ideas?
=Austin
Yes. But Java sucks. Me no like make Perl like Java.
I would still like to be able to do things in Perl6 like:
@out = sort map {...} grep { ... } @in; # [1]
Even though that technically means having sort, map, grep as builtins.
We can make that
@out = @in.grep({...}).map({...}).sort; # [2]
if we want to grind our OO axe, but I find that syntax disappointing.
I like that the idea is important enough in Perl to have it's own
grammar, but I realize the problem of namespace pollution involved in
having a bunch of builtins called grep, map, whatever.
The only encompassing solution would seem to be to find a grammar rule
by which map,grep,etc are unambiguously methods of Array, but can still
be called in a fashion similar to [1]. That would, I suspect, satisfy
everyone.
MikeL
Or, better yet:
@out = sort map grep @in: { ... }: { ... }:;
Hi Mister Maintainence Programmer :-P
Luke
Right. And that's what my clever-parsing-of-blocks idea was working towards:
making the syntax palatable for the most common forms.
--
ADVERSITY:
That Which Does Not Kill Me Postpones the Inevitable
> I would still like to be able to do things in Perl6 like:
>
> @out = sort map {...} grep { ... } @in; # [1]
>
> The only encompassing solution would seem to be to find a grammar rule
> by which map,grep,etc are unambiguously methods of Array, but can
> still be called in a fashion similar to [1]. That would, I suspect,
> satisfy everyone.
What if the thing being C<sort>ed (or whatever) is not an array but a
list?
@out = sort $scalar, @array, result_of_calling_function($param);
Would the list have to be stored in an array before it could be sorted?
That doesn't sound very nice ...
@out = [$scalar, @array, result_of_calling_function($param)].sort;
I think I'm in favour of things that operate on an arbitrary lists
remaining functions rather than becoming methods.
Smylers
I would hope Perl would be smart enough to allow this:
@out = ($scalar, @array, result_of_calling_function($param)).sort
which Ruby does:
$ ruby -wle 'out = ["foo", "bar"].sort; print out.join " "'
bar foo
but as I said, I find the Lisp flow style worth keeping.
@out = join "\n", map {...} grep {...} sort {...} @foo
--
Michael G. Schwern <sch...@pobox.com> http://www.pobox.com/~schwern/
Perl Quality Assurance <per...@perl.org> Kwalitee Is Job One
Pancakes is the better part of valor.
http://www.goats.com/archive/971202.html
I hope and expect that there is sufficient magic to treat a list as an
Array wherever necessary, such that Array method calls should be
allowed on any literal or C<return>ed list.
( $scalar, @array, foo() ).sort {...}; # [1]
my @a = ( $scalar, @array, foo() ); # [2]
@a.sort {...};
If we kept the current map syntax, the same should be true:
sort {...} $scalar, @array, foo(); # [1]
my @a = ( $scalar, @array, foo() ); # [2]
sort {...} @a;
Or if we can come up with a reverse-dot syntax that treats C<sort> as a
method of Array, and not a reserved keyword:
sort { ... } <- $scalar, @array, foo(); # [1]
my @a = ( $scalar, @array, foo() ); # [2]
sort {...} <- @a;
In each case, [1] should be marginally more efficient than [2], because
it's doing less.
Same magic for hashes, too. And maybe even for references upon
arrays/hashes:
(1,2,3,4,5).reverse; # returns (5,4,3,2,1)
[1,2,3,4,5].reverse; # returns [5,4,3,2,1]
But note:
@a.reverse;
@a .= reverse; # these two might mean different things?
my @a = (1,2,3,4,5);
@a.reverse; # OK
my $a = [1,2,3,4,5];
$a.reverse; # but this might be problematic
That last line would be OK only if the C<Ref> type either didn't have
any methods of it's own (unlikely), or if C<Ref> knew to look in the
methods of the referred-to obj if the method was not part of C<Ref>
itself.
MikeL
It does, under the rule that says a comma list in a scalar context
assumes [...]. (The dot provides the scalar context to the comma
list--the outer list context is only meaningful to the sort.)
: which Ruby does:
:
: $ ruby -wle 'out = ["foo", "bar"].sort; print out.join " "'
: bar foo
:
: but as I said, I find the Lisp flow style worth keeping.
:
: @out = join "\n", map {...} grep {...} sort {...} @foo
That too. But you don't have to think of them as built-ins, except
insofar as any subroutine defined in * is a built-in. It's possible
the only real built-in is *sub. And maybe *rx.
Larry
Actually, N might be 0. The : may not always be required on single arg
methods in indirect object syntax. That is, if there's no sub matching
keys %h
it'll fall back to looking for
keys %h:
I have horrors of seeing programs full of things like
close $FH:;
Larry
Foul! I suspect this is a fight over definitions, not beliefs. Damian
is usually pretty much on the mark with his beliefs.
: In the same way, the specification of C-as-a-language, its syntax and
: operators and the stuff that makes it look, act and feel like C, is
: agnostic of the C standard library. (Even though "ANSI C" specifies
: both, they are seperable.) This seperability is something I'd like
: to see thought about a lot more in Perl 6.
:
: > There's lots of reasons to use an operator or built-in instead of a method,
: > but remember to make the consideration first. Don't go grammar happy.
:
: Yes, yes, yes. This is what I've been trying to say for a while.
Don't get discouraged--I've been saying it for a good long time now, and
people still don't hear it, regardless of which side they're on...
About the only things that have to be truly built-in to Perl 6 are
lambda and the regex engine. Everything else is negotiable. (I'm
counting method dispatch under "lambda", of course... :-)
Larry
> We can make that
>
> @out = @in.grep({...}).map({...}).sort; # [2]
>
> if we want to grind our OO axe, but I find that syntax disappointing.
> I like that the idea is important enough in Perl to have it's own
> grammar, but I realize the problem of namespace pollution involved in
> having a bunch of builtins called grep, map, whatever.
>
> The only encompassing solution would seem to be to find a grammar rule
> by which map,grep,etc are unambiguously methods of Array, but can still
> be called in a fashion similar to [1]. That would, I suspect, satisfy
> everyone.
Well, if the source file were considered to be just a big giant class,
sans
class main {
...
}
then it becomes as simple as having a method in Object, grep, something
like:
class Object {
method grep($a_closure, *@input) {
...
}
}
Yay!
Luke
On Friday, December 13, 2002, at 03:07 AM, Piers Cawley wrote:
> What's wrong with:
>
> class Array {
> method grep ( &block ) {
<snip>
> }
>
> sub grep (Object $obj, @*ary) { @ary.grep($obj); }
>
> AFAICT, (modulo getting the laziness done right, this should allow
> you to write)
>
> grep { ... } @ary;
> grep /.../, @ary;
The only issue is that it still treats C<grep> as a universal sub --
it's just giving you an identically named C<grep> method of Array, too.
The ideal solution IMO is one that would remove C<map>, C<grep>, etc.
_entirely_ from the main/core/Object, and leave it _solely_ as a method
of Array. Not because C<grep> is inherently evil, but because that
would give us a completely generic way to make other "piped" grep-style
functions, like C<part>, without polluting the core namespace.
A (placeholder for a) R-to-L "dot-like" operator:
grep {...} <- @foo;
would be intended to be the *exact* equiv of
@foo.grep {...};
but with a reversed syntax for the invocant. So grep-like functions
could be nested, and new ones could be created by making new methods of
Array, AND we could get rid of the "specialness" of the Perl5 map/grep
syntax -- the syntax isn't special to a few list-munging functions, it
can be used for anything.
@out = sort <- map {...} <- grep {...} <- @in;
So it's almost what we had in Perl5, but more regular.
Of course, maybe '<-' is just spelled post-"given", and we're done:
@out = sort
given map { ... }
given grep { ... }
given @in;
Or would that be @out = .sort given .map ...etc...?
MikeL
> >> The only encompassing solution would seem to be to find a grammar rule
> >> by which map,grep,etc are unambiguously methods of Array, but can
> >> still be called in a fashion similar to [1]. That would, I suspect,
> >> satisfy everyone.
>
> On Friday, December 13, 2002, at 03:07 AM, Piers Cawley wrote:
> > What's wrong with:
> >
> > class Array {
> > method grep ( &block ) {
> <snip>
> > }
> >
> > sub grep (Object $obj, @*ary) { @ary.grep($obj); }
> >
> > AFAICT, (modulo getting the laziness done right, this should allow
> > you to write)
> >
> > grep { ... } @ary;
> > grep /.../, @ary;
>
> The only issue is that it still treats C<grep> as a universal sub --
> it's just giving you an identically named C<grep> method of Array,
> too. The ideal solution IMO is one that would remove C<map>, C<grep>,
> etc. _entirely_ from the main/core/Object, and leave it _solely_ as a
> method of Array. Not because C<grep> is inherently evil, but because
> that would give us a completely generic way to make other "piped"
> grep-style functions, like C<part>, without polluting the core
> namespace.
To what end? Actually, if we have multimethods correctly sorted, one
could envisage a CunningCollection class:
class CunningCollection {
method grep ( Object $obj ) { .as_array.grep($obj) }
sub grep ( Object $obj, CunningCollection $coll ) is exported {
$coll.grep($obj);
}
}
And it's trivial to do the same with any other syntax-like generic
function you care to come up with, no need for an extra syntactic wart.
>
> A (placeholder for a) R-to-L "dot-like" operator:
>
> grep {...} <- @foo;
>
> would be intended to be the *exact* equiv of
>
> @foo.grep {...};
>
> but with a reversed syntax for the invocant. So grep-like functions
> could be nested, and new ones could be created by making new methods
> of Array, AND we could get rid of the "specialness" of the Perl5
> map/grep syntax -- the syntax isn't special to a few list-munging
> functions, it can be used for anything.
>
> @out = sort <- map {...} <- grep {...} <- @in;
>
> So it's almost what we had in Perl5, but more regular.
>
> Of course, maybe '<-' is just spelled post-"given", and we're done:
>
> @out = sort
> given map { ... }
> given grep { ... }
> given @in;
>
> Or would that be @out = .sort given .map ...etc...?
Both of your proposed options are, frankly, vile. The
multimethod/generic function approach has the advantage of putting the
'burden' of writing the generic function on the implementor rather
than on the user. Given that implementation happens once and something
is used countless times, that seems like a decent trade off to me.
>
> Both of your proposed options are, frankly, vile. The
> multimethod/generic function approach has the advantage of putting
> the
> 'burden' of writing the generic function on the implementor rather
> than on the user. Given that implementation happens once and
> something
> is used countless times, that seems like a decent trade off to me.
Dictionary.com sez:
"vile
adj. vil·er, vil·est
1. Loathsome; disgusting: vile language.
2. Unpleasant or objectionable: vile weather. See Synonyms at
offensive.
3.
- a. Contemptibly low in worth or account; second-rate.
- b. Of mean or low condition.
4. Miserably poor and degrading; wretched: a vile existence.
5. Morally depraved; ignoble or wicked: a vile conspiracy."
Is this one of those BOFH things where you insult the hell out of
someone and then give them a pat on the head, and six months later
they're arrested while sneaking into the London Zoo wearing a leather
corset and silk panties? (*)
Otherwise, I'm left to wonder. As I read Mike's post, he's proposing
that we regularize a feature of the language, make it extensible, and
potentially use a conceptual framework based on an existing syntactical
element.
Yours, on the other hand, gives (I hope) the extensibility, doesn't
require the syntactic bits but does appear to require that every such
method be implemented twice.
I'm going to need some more convincing.
=Austin
(*) Because if so, I'm all for it!
> --- Piers Cawley <pdca...@bofh.org.uk> wrote:
>
> >
> > Both of your proposed options are, frankly, vile. The
> > multimethod/generic function approach has the advantage of putting
> > the 'burden' of writing the generic function on the implementor
> > rather than on the user. Given that implementation happens once
> > and something is used countless times, that seems like a decent
> > trade off to me.
>
> Dictionary.com sez:
>
> "vile
> adj. vil·er, vil·est
> 1. Loathsome; disgusting: vile language.
> 2. Unpleasant or objectionable: vile weather. See Synonyms at
> offensive.
> 3.
> - a. Contemptibly low in worth or account; second-rate.
> - b. Of mean or low condition.
> 4. Miserably poor and degrading; wretched: a vile existence.
> 5. Morally depraved; ignoble or wicked: a vile conspiracy."
I choose 2.
> Is this one of those BOFH things where you insult the hell out of
> someone and then give them a pat on the head, and six months later
> they're arrested while sneaking into the London Zoo wearing a
> leather corset and silk panties? (*)
I gave him a pat on the head? I told him that his proposed solutions
were unpleasant or possibly loathsome, and that he should throw them
away and stick with my proposed generic subroutines solution and you
call that a pat on the head? Coo.
> Otherwise, I'm left to wonder. As I read Mike's post, he's proposing
> that we regularize a feature of the language, make it extensible,
> and potentially use a conceptual framework based on an existing
> syntactical element.
>
> Yours, on the other hand, gives (I hope) the extensibility, doesn't
> require the syntactic bits but does appear to require that every
> such method be implemented twice.
Um. Not really implemented twice no. One subroutine implementation
can act as the facade for an awful lot of overloaded methods in the
class. Look at the grep implementation again:
class Array {
method grep ( Block &block ) {...}
method grep ( Rule $rx ) { ... }
method grep ( rx/<expr>/ $expr ) { ... }
sub grep ( Object $selector, @*ary ) is exported { ... }
}
A single generic sub is used to provide a functional interface to a
bunch of methods. Now, when we add grep behaviour to the
'CunningCollection' class, we will need to overload the generic sub
so that, in the case of
grep .selector, $some_cunning_collection;
the $cunning_selector doesn't just get stuffed into an array. One
could also imagine a scenario where someone implements a new
'selecting' object:
class NewSelector {
method grep ( $self: @*args ) {
grep $self.as_block, *@args;
}
sub grep ( NewSelector $selector, @*args ) is exported {
$selector.grep( *@args );
}
}
And I fail to see how Mike's proposed syntax will deal with
this. Remember that the one time (per class admittedly) cost of
setting up a generic sub buys us a good deal of not having to use
gratuitous punctuation (or ghod help us 'is given') at use time.
map { .[0] }
sort { $^a[1] cmp $^b[1] }
map { [ $_ => some_transform($_) }
grep /.../, @array
happily stays as it is; I fail to see what recasting that as
map { .[0] } <-
sort { $^a[1] cmp $^b[1] } <-
map { [ $_ => some_transform($_) } <-
grep /.../, @array
or any other 'noisy' suggestion buys us. It just seems like the wrong
kind of Laziness to me.
My only concern is that the first implies (as it does in perl5) yet
more special behaviors attached to the {...} brackets. Either "no
comma is needed after a closure", or "no comma needed after the first
arg of the specific functions named C<map>, C<grep>, ...
I'm worried that in attaching even _more_ specialness to curlies (which
are already highly (impossibly?) magical), we're setting ourselves up
for some hurt down the road. It was OK in perl5, but I don't know if
it's OK in perl6.
Mind you (purely devil's advocate), I'm not entirely sure the R-to-L
syntax truly _needs_ to be in Perl6. It's true I use it all the time,
but I can retrain to use L-to-R method calls with little effort.
If we have a post-given, e.g. C<map {...} given @a> or C<map {...} is
given @a>, I think that gives us R-to-L without any special {...} rules
at all.
MikeL
> On Friday, December 13, 2002, at 10:59 PM, Piers Cawley wrote:
>> map { .[0] }
>> sort { $^a[1] cmp $^b[1] }
>> map { $_ => some_transform($_) }
>> grep /.../, @array
>>
>> happily stays as it is; I fail to see what recasting that as
>>
>> map { .[0] } <-
>> sort { $^a[1] cmp $^b[1] } <-
>> map { $_ => some_transform($_) } <-
>> grep /.../ <- @array
>>
>> or any other 'noisy' suggestion buys us. It just seems like the wrong
>> kind of Laziness to me.
> <edited to fix a minor typo>
>
> My only concern is that the first implies (as it does in perl5) yet
> more special behaviors attached to the {...} brackets. Either "no
> comma is needed after a closure",
I think that's already a given; there's definitely discussion
elsewhere that takes that as read. And it's (prototyped) perl 5
behaviour, changing it to require a comma would be the Wrong Thing.
> or "no comma needed after the first arg of the specific functions
> named C<map>, C<grep>, ...
Definitely the Wrong Thing.
> I'm worried that in attaching even _more_ specialness to curlies
> (which are already highly (impossibly?) magical), we're setting
> ourselves up for some hurt down the road. It was OK in perl5, but I
> don't know if it's OK in perl6.
>
> Mind you (purely devil's advocate), I'm not entirely sure the R-to-L
> syntax truly _needs_ to be in Perl6. It's true I use it all the time,
> but I can retrain to use L-to-R method calls with little effort.\
Personally I really don't like the L to R style; I know we've got it
for C<< for ... -> $a { ... } >>, but I can see the logic behind
that, otherwise L to R looks worryingly like C++ to me.
> If we have a post-given, e.g. C<map {...} given @a> or C<map {...} is
> given @a>, I think that gives us R-to-L without any special {...}
> rules at all.
No, just the addition of much ugliness to code for no gain in
readability. And one more area where Perl 6 fails to look like Perl 5
for no good reason.
That's ok. Personally, I do. You find R2L easier to read, I find L2R
easier. TIMTOWDI. Perl6 should be smart enough to support both.
>I know we've got it
> for C<< for ... -> $a { ... } >>, but I can see the logic behind
> that, otherwise L to R looks worryingly like C++ to me.
I'm not convinced that language snobbery is a good reason to include
or exclude a feature from Perl6. And, if there is logic in having L2R
in one case (for), why shouldn't we generalize it to be useful (or at
least possible) in all cases?
> > If we have a post-given, e.g. C<map {...} given @a> or C<map {...} is
> > given @a>, I think that gives us R-to-L without any special {...}
> > rules at all.
>
> No, just the addition of much ugliness to code for no gain in
> readability. And one more area where Perl 6 fails to look like Perl 5
> for no good reason.
Personally, I'm not fond of the specific syntax that MikeL is suggesting.
However, I think that L2R is valuable enough that it should make it
into the language, and I don't have a better suggestion.
--Dks
I haven't been arguing against his syntax for adding L to R
pipelines, but against the damage he proposes doing to R to L syntax.
> However, I think that L2R is valuable enough that it should make it
> into the language, and I don't have a better suggestion.
Well, L2R is really easy:
@ary.map({...}).grep(rx/.../).whatever(...);
For ugly values of 'really easy' of course.
Why?
Yes, technically we can do both R2L and L2R. We can also support an
alternative Scheme/Lisp form of perl's syntax, as well as a
Forth/Postscript style. Heck, we can probably manage a prolog-style
unification style for a not-insignificant subset of perl programs.
That doesn't mean its a good idea.
--
Dan
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk
> >You find R2L easier to read, I find L2R
> >easier. TIMTOWDI. Perl6 should be smart enough to support both.
>
> Why?
>
> Yes, technically we can do both R2L and L2R. We can also support an
> alternative Scheme/Lisp form of perl's syntax, as well as a
> Forth/Postscript style. Heck, we can probably manage a prolog-style
> unification style for a not-insignificant subset of perl programs.
> That doesn't mean its a good idea.
Just so I'm clear, are you saying that you think L2R is a bad idea,
and should not be supported? Or just that it has not yet been
demonstrated that this is a good idea?
--Dks
> I haven't been arguing against his syntax for adding L to R
> pipelines, but against the damage he proposes doing to R to L syntax.
Fair enough. I'd like to find a way for neither of them to go away,
or get damaged.
> > However, I think that L2R is valuable enough that it should make it
> > into the language, and I don't have a better suggestion.
>
> Well, L2R is really easy:
>
> @ary.map({...}).grep(rx/.../).whatever(...);
>
> For ugly values of 'really easy' of course.
Yick. I'll definitely agree on the "ugly" part.
However, I'm curious--and I know this has been hashed over, I'm just
not clear on where we stand at this point--are you proposing that map,
grep, and whatever would be methods on Array? Because that seems
unnecessarily restrictive. And yet, having them be methods of Object
seems a bit TOO generous.
Perhaps the answer is to have an inheritance tree that goes
Object
|
v
Collection
|
+-Array
|
+-Hash
|
+-etc (maybe Set, or maybe junction)
...and map, grep, etc, would be elements of Collection, overriden in
sensible ways by the derived classes?
This is an off-the-cuff idea and I may well be full of it.
--Dks
I've suggested a full blown Collection hierarchy elsewhere, but this
would be an ideal place for it. Then you can set up the function
style variants with just a couple of generic functions:
sub grep ( Object $selector, @*args ) { @args.grep($selector) }
sub grep ( Object $selector, Collection $coll ) {
$coll.grep($selector)
}
You know, the more I monkey with multi dispatch stuff, the more I
like it.
> This is just your friendly neighborhood curmudgeon reminding you that in
> Perl 6, everything is an object. This is a concept that, as Perl
> programmers, we're not familiar with.
Are these objects class based or where do the methods come from? Is there
an accomodation for something like classless objects? Being forced into
class based objects might be problematic for a capabilities system where
you wouldn't want to have objects bristling with exposed methods.
Joshua Jore
Once again we're getting steadily closer to inventing Ruby.
--
void russian_roulette(void) { char *target; strcpy(target, "bullet"); }
I think supporting two distinct syntaces, one being a mirror image of
the other, is a bad idea. I'll leave people to argue over which one is
better because it keeps them out of the way. ;)
--
Congratulations, Simon - I think I've finally discovered someone with a
mind that is more warped than mine.
- Lionel Lauer
Piers earlier suggested having anonymous classes available (Class.new,
etc.), which seems like a good idea, meaning you could instantiate a new
object in a brand new class all at runtime if you needed to.
--
It's a testament to the versatility of the human mind that we're so able
to compensate for our own incompetence.
- Darrell Furhiman
Agreed, but I don't think this is necessarily a Bad Thing.
Larry said ~~ "People have been borrowing ideas from Perl for a long time,
now it's time to borrow some back".
I like Ruby, I like dot ops, and I like being able to chain them together
from left to right. I would really like it if these were some of the
ideas that we borrow back from Ruby (and other places).
As it happens, I've already borrowed them for the Template Toolkit.
Of course, TT doesn't count as a Real Programming Language, but it
does support the same syntax for accessing data and it's very useful.
myhash.keys.sort.join(', ') # valid in both Ruby and TT
Of course, this is semantically no different to the Perl 5 equivalent:
join(', ', sort keys %$myhash)
but I find it easier to read as it progresses more naturally, to me at
least, from left to right. Take myhash, get the keys, sort them, then
join them together.
This is essentially a pipeline style of processing:
a --> b --> c
whereas the usual right to left is technically a nested form:
a ( b ( c ) )
which effectively reverses the order of evaluation of the pipeline:
c --> b --> a
I think both are equally valid and should be supported, if possible.
Sometimes it makes sense to think about a problem from start to finish
(input driven or "push"). Other times it's better to think about the
desired goal and work backwards towards the beginning (output driven
or "pull").
In one situation you might think "I want to take myhash, extract the
keys, sort them and then join them together to make a string" and
write C<$myhash.keys.sort.join(', ')>. In another you'll think
"I need a string containing the sorted keys of myhash" and instead
write C<join(', ', sort keys %$myhash)>.
It seems to me that L.R syntax falls out naturally in Perl 6 from the
dotop. Hash objects will have 'keys' methods, Array objects will have
'sort' and 'join' methods and everything should just work as expected.
$hash.keys.sort.join(', ');
The sticky issue is how to pass a block to sort, map, grep, etc.
Well, if we can't come up with anything better than explicitly passing
a block as an argument, e.g.
$hash.keys.sort({ ... }).join(', ');
then I still think this is better than nothing at all.
If you end up writing pathological cases where you're passing lots of
blocks as arguments, then perhaps it would be better written in a regular
Perl 5 right to left (nested), or even a mixed style.
join( ', ', sort { ... } $hash.keys );
If we can come up with something that makes this syntactic pill a little
easier to swallow, then that's great. But even if we can't, I don't think
it's the end of the world, or even the world.end :-)
A
These are questions about the general design of Perl 6's OO system and out of the scope of ths discussion. The Perl 6 OO Cookbook does a good job of documenting what OO will look like in Perl 6 this week:
http://cog.cognitivity.com/perl6/
I think it's a good idea, and that it should *not* be supported.
Disagreed--we're getting steadily closer to inventing Smalltalk. :)
Which isn't altogether a bad thing. (As long as we don't vet closer
to inventing Lisp...)
...except for the parts I completely made up, as placeholders for real
stuff later. :-) (But I think I have those sections all marked now.)
MikeL
On Monday, December 16, 2002, at 05:45 PM, Dave Storrs wrote:
> Just so I'm clear, are you saying that you think L2R is a bad idea,
> and should not be supported? Or just that it has not yet been
> demonstrated that this is a good idea?
We _must_ (for some value of "must" that is real close to being a 100%
drop-dead requirement) support --> (L2R), in the form of
@a.grep( {...} )
.map( {...} )
.sort;
i.e. however else we do it, array processing functions _MUST_ exist as
methods of Array. That may not be the preferred spelling, or anything
close to attractive, but it would be simply pathetic for it not to
exist.
Almost everyone's been clamoring over how we want OO and OO is cool and
everything should be treatable as an object. If arrays are objects,
the above is How It's Gonna Look, unless we want to invent a
method-call syntax for arrays that is completely different from that of
scalars.
So if anyone _doesn't_ want the above dot-syntax to exist AT ALL,
please explain the rationale!
_However_, the above code is probably the most formal usage of the
array-manipulation methods. If we want another way to say it, e.g. <--
(R2L) or a prettier --> (L2R), we could probably have it. But it would
have to be in _addition_ to the above, not _instead_ of. We can add
the Perl5-style:
@out = sort map {...} grep {...} @a;
if we want to, but I don't think it should be given a free ride in
Perl6. It's not regular (not like anything else in the language),
sucks up those names as globally reserved (as opposed to merely methods
of arrays), implies more possible wacky behaviors of curlies, and
cannot credibly be tortured into being OO upon @a.
So whether prettyified <-- (R2L) and --> (L2R) forms exist and what
they look like, we can argue about. But the method form (L2R) @a.grep,
etc, simply _must_ be valid, if not encouraged.
MikeL
Those are simple method calls, so there's no reason we shouldn't
support them, though they will *only* work if each returns an actual
array, rather than a list. They are, however, not the same as doing:
@b = @a grep {} map {} sort {};
because that's true L2R, as it'll work for:
@b = (*@a, *@b, foobar()) grep {} map {} sort {};
That can't work as methods of the list, unless we're wildly
redefining how lists work, which I don't think we're going to do.
*That's* the sort of way, the L2R way, that I'd argue against.
Shifting directions in mid-stream is, well, really tough for us old
codgers.
And you can't get rid of the old way, since it's just implicit
function calls. To forbid
@b = sort {} map {} grep {} @a;
is the same as forbidding
@b = sort({}, map({}, grep({}, @a)));
which I think would be... unwise. As would chopping sort/map/grep and
friends from the language entirely. One of the hallmarks of perl is
its richness, and I think losing that would be ill-advised.
And it's part of this nutritious breakfast! Well, adjacent to it, at
least... :-P
Silly rabbit, Ruby is Smalltalk!
> Simon Cozens wrote:
>> Once again we're getting steadily closer to inventing Ruby.
> Agreed, but I don't think this is necessarily a Bad Thing.
Now, I do like Ruby. And I definately don't see this as a Bad Thing.
In my opinion, Perl6 should have all the best features from all the best
languages ;)
> myhash.keys.sort.join(', ') # valid in both Ruby and TT
> Of course, this is semantically no different to the Perl 5 equivalent:
> join(', ', sort keys %$myhash)
The first one seems to be more readable to me, although I am used to using
the second one. I think it would be easier for new people to learn (and to
use) the first case rather the second one (I am taking a newbie point of
view here ;)
> I think both are equally valid and should be supported, if possible.
TIMTOWTDI revisited. I am not sure how Larry stands on thsi fundamental
Perl paradigm in Perl6, but I have grown accustomed with TIMTOWTDI and
that's why I like Perl.
> The sticky issue is how to pass a block to sort, map, grep, etc.
> Well, if we can't come up with anything better than explicitly passing
> a block as an argument, e.g.
> $hash.keys.sort({ ... }).join(', ');
This is not as bad. At least it seems to me quite natural and easily
understandable.
> If you end up writing pathological cases where you're passing lots of
> blocks as arguments, then perhaps it would be better written in a
> regular Perl 5 right to left (nested), or even a mixed style.
> join( ', ', sort { ... } $hash.keys );
Now this it where things start to get weird, of course. Lots of
possibilities for obfuscation, but again, Perl5 has been famous for these
kind of things.
Petras Kudaras
Um...I'm sorry, I really don't understand that, could you explain it
to me? If it's a good idea, why shouldn't we support it?
--Dks
I honestly don't understand why not...can you explain it to me? So
long as, within any given statement, it is clear which syntax is being
used, what's the problem? Perl has always been famous for supporting
the kitchen sink and letting you choose which faucet you want to turn
on--e.g., we have OO style, imperative style, and a pretty full
language built into the regexen.
--Dks
Just to make sure I'm not one of those people, I'll clarify my terms:
I am calling this L2R:
@b = @a --> sort --> map { $_++ } --> grep { $_ > 0 };
I don't care about the syntax at all, I just made up something that
seemed moderately clear to me. In point of fact, I hope we DON'T use
the above syntax, or anything else where you are required to have an
operator between each element of the pipeline.
I am calling this R2L:
@b = grep { $_ > 0 } map { $_++ } sort @a;
Note that this is just Perl5 code.
> We _must_ (for some value of "must" that is real close to being a 100%
> drop-dead requirement) support --> (L2R), in the form of
>
> @a.grep( {...} )
> .map( {...} )
> .sort;
>
> i.e. however else we do it, array processing functions _MUST_ exist as
> methods of Array. That may not be the preferred spelling, or anything
> close to attractive, but it would be simply pathetic for it not to
> exist.
Well, I generally agree with you, but with an important nit: they
shouldn't be members of Array, they should be members of Collection,
Array's base class. Otherwise, what if I define an UnorderedMultiSet class and I want to grep over it?
Ok, let me play Devil's Advocate (*) for a moment. Why do we need
this? Why should these names be locked up in the Array class? What
if I want to grep a list, or if I want to define some kind of class
for which it is meaningful to grep an instance...perhaps an
UnorderedMultiSet class. If these functions are locked up in Array, I
will need to either derive my UnorderedMultiSet from Array
(inappropriate), use an Array internally (perhaps inconvenient), or
redefined the methods myself (wasteful).
> have to be in _addition_ to the above, not _instead_ of. We can add
> the Perl5-style:
>
> @out = sort map {...} grep {...} @a;
>
> if we want to, but I don't think it should be given a free ride in
> Perl6. It's not regular (not like anything else in the language),
> sucks up those names as globally reserved (as opposed to merely methods
> of arrays), implies more possible wacky behaviors of curlies, and
> cannot credibly be tortured into being OO upon @a.
Hmmm...I don't suppose that, with implicit promotion to Array, we can
get out of this with the indirect object notation, can we? I'm not
sure what it looks like this week, but perhaps we could make a minor
requirement change (e.g., need a comma on the methods and a trailing :
on the @a) and shoehorn it into something like this:
@out = sort map {...}, grep {...}, @a:;
--Dks
Question on this: for me, one of the trickiest things when teaching
Perl5 has always been explaining the difference between an array and a
list, when you need one versus the other, why they aren't precisely
the same, and where the differences are.
What exactly are the advantages of having both in Perl6? Is it
possible that we could put them together and have only one or the
other without losing anything (that we aren't willing to lose)?
> @b = (*@a, *@b, foobar()) grep {} map {} sort {};
>
> That can't work as methods of the list, unless we're wildly
> redefining how lists work, which I don't think we're going to do.
I don't know enough to see why this is a problem. Can you explain it?
> *That's* the sort of way, the L2R way, that I'd argue against.
> Shifting directions in mid-stream is, well, really tough for us old
> codgers.
Mid-stream in terms of the work that's been done on Parrot or in terms
of your programming experience? i.e., are you saying that it would
require major redesign and recoding on the existing engine, or that it
would be hard to get used to having it in the language?
> function calls. To forbid
>
> @b = sort {} map {} grep {} @a;
>
> is the same as forbidding
>
> @b = sort({}, map({}, grep({}, @a)));
>
> which I think would be... unwise. As would chopping sort/map/grep and
> friends from the language entirely. One of the hallmarks of perl is
> its richness, and I think losing that would be ill-advised.
Indeed.
--Dks
I was under the impression that the distinction between array and list
was going away in perl 6. Surely if (1,2,3) creates an anonymous
array reference, then (1,2,3).foo will work for any foo able to
operate on an array.
> > @b = (*@a, *@b, foobar()) grep {} map {} sort {};
> >
> > That can't work as methods of the list, unless we're wildly
> > redefining how lists work, which I don't think we're going to do.
>
> I don't know enough to see why this is a problem. Can you explain it?
So, the above would be written a little punctuatively different:
@b = (*@a, *@b, foobar()).grep({}).map({}).sort({});
-Scott
--
Jonathan Scott Duff
du...@cbi.tamucc.edu
@a is an array; *@a is a list.
--
"In matters of principle, stand like a rock; in matters of taste, swim with
the current."
-- Thomas Jefferson
How else would you disambiguate?
# > We _must_ (for some value of "must" that is real close to
# being a 100%
# > drop-dead requirement) support --> (L2R), in the form of
# >
# > @a.grep( {...} )
# > .map( {...} )
# > .sort;
# >
# > i.e. however else we do it, array processing functions
# _MUST_ exist as
# > methods of Array. That may not be the preferred spelling,
# or anything
# > close to attractive, but it would be simply pathetic for it not to
# > exist.
If we put in my idea of "longest possible signature" when there's no
parens and a low-precedence 'dot' operator, we could do this without the
parens. *ducks*
# Well, I generally agree with you, but with an important nit:
# they shouldn't be members of Array, they should be members of
# Collection, Array's base class. Otherwise, what if I define
# an UnorderedMultiSet class and I want to grep over it?
Fine. What do you grep over when you're grepping a hash? .k? .v? .kv
and pass two values in? Pair objects?
# > have to be in _addition_ to the above, not _instead_ of. We can add
# > the Perl5-style:
# >
# > @out = sort map {...} grep {...} @a;
# >
# > if we want to, but I don't think it should be given a free ride in
# > Perl6. It's not regular (not like anything else in the language),
# > sucks up those names as globally reserved (as opposed to
# merely methods
# > of arrays), implies more possible wacky behaviors of curlies, and
# > cannot credibly be tortured into being OO upon @a.
#
# Hmmm...I don't suppose that, with implicit promotion to
# Array, we can get out of this with the indirect object
# notation, can we? I'm not sure what it looks like this week,
# but perhaps we could make a minor requirement change (e.g.,
# need a comma on the methods and a trailing : on the @a) and
# shoehorn it into something like this:
#
# @out = sort map {...}, grep {...}, @a:;
Eww. Indir object is like this:
@out = sort map grep @a: {grepblock} {mapblock};
#I'm not sure you can actually leave out the
# parens--it might be ambiguous.
I assume you can see why this is a Bad Thing.
--Brent Dax <bren...@cpan.org>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)
"If you want to propagate an outrageously evil idea, your conclusion
must be brazenly clear, but your proof unintelligible."
--Ayn Rand, explaining how today's philosophies came to be
Oh, yeah, that's it. Sorry.
I actually thought the indirect object syntax would be... umm...
@out = sort map grep @a : {grepblock} : {mapblock} :;
(with three ':'s, one per method?)
Wow. Now that's *spectacularly* ugly! It looks like it has cooties.
(Hmm, perhaps ':' can be the 'cootie' operator...)
MikeL
Yeah. I don't know what the precise class tree will look like, but as
long as you can call these methods on an Array and whatever other
collections exist, it works, regardless of how we put them there.
MikeL
:-) I forget if there was a problem with longest-possible sig, but I'm
certainly all for it. Though I'm not sure if something like
{codeblock}.sort;
might actually have a valid meaning(?), in which case the no-parens
version would _still_ be ambiguous. :-P
Honestly, I still don't see what's so evil about R2L as:
@out = sort given map {...} given grep {...} given @a;
It seems to solve all the issues with not needing parens, not requiring
{...} to magically eat a trailing comma but-only-sometimes, not needing
to declare C<grep>, etc, in more than one place. And it's arguably
more descriptive than the older (albeit shorter) syntax. And a *lot*
more generically useful for things other than lists/arrays.
$obj.foo(...);
foo ... given $obj; # identical
MikeL
Odds are it'll either inherit from multiple parent classes, one of
which does the collection bits, or it'll inherit the collection
interface (or whatever we call it). Or it might just be documented to
work that way and does, without any actual inheritance of anything.
As it stands, there's a couple of problems with it. First, IIRC you
can't chain post-modifier things. Unless the likely has occurred that
Larry changed his mind from 8 months ago :).
Another is that C<sort> and company I<should> be methods of Array
(inherited or not), and if they're only in one place, then your
example would have to be:
@out = .sort given .map({...}) given .grep({...}) given @a;
The last problem is that R2L is not the problem. It is supported by
the basic syntax of the language:
@out = sort map {...} grep {...} @a;
Or some punctuational variant thereof.
If that doesn't work I can honestly say that Perl 6 is not Perl
(provided C<sort> and company are declared as forwarder calls, which I
don't see a problem with).
L2R is the big one that I'm hoping for. The pipe syntax is such a
powerful concept from Unix, I'm surprised Perl hasn't stolen it
before.
> $obj.foo(...);
> foo ... given $obj; # identical
I don't see how that works. My interpretation:
$obj.foo(...);
.foo(...) given $obj; # identical
Your way works for topic-defaulting calls, as in:
sub foo(my $arg //= $topic) is given($topic) {...}
foo $obj;
foo given $obj; #identical
Perhaps I'm missing something?
Luke
And all because Mike Lazzaro wrote:
> Honestly, I still don't see what's so evil about R2L as:
>
> @out = sort given map {...} given grep {...} given @a;
A few things.
First, C<given> already has a non-void-context meaning.
Second, I find this *really* hard to decipher. ;-)
Can I suggest that an alternative solution might be the following:
Suppose Perl 6 had two new very low precedence operators: ~> and <~
(a.k.a. "bind rightwards" and "bind leftwards")
Suppose ~> takes its left argument and binds it to
the end of the argument list of its right argument,
then evaluates that right argument and returns the result.
So an L2R array-processing chain is:
@out = @a ~> grep {...} ~> map {...} ~> sort;
There might also be a be special rule that, if the RHS is
a variable, the LHS is simply assigned to it. Allowing:
@a ~> grep {...} ~> map {...} ~> sort ~> @a;
Further suppose that <~ takes its right argument, and binds
it in the indirect object slot of the left argument, which
argument it then calls. So an R2L array-processing chain is:
@out = sort <~ map {...} <~ grep {...} <~ @a;
Or, under a special rule for variables on the LHS:
@out <~ sort <~ map {...} <~ grep {...} <~ @a;
That way, everything is still a method call, the ultra-low precedence of
<~ and ~> eliminate the need for parens, and (best of all) the expressions
actually *look* like processing sequences.
Damian
I love this.
And any class could override the <~ operator, right? So filehandles could
use it for output, etc. I suppose it could be done like arithmetic
overloading, if you define both <~ ("I'm being pointed at from the right")
and ~> ("I'm being pointed at from the left") in your class then Perl will
use whichever appears in code, but if you define just one, Perl will use
it for both.
Trey
--
I'm looking for work. If you need a SAGE Level IV with 10 years Perl,
tool development, training, and architecture experience, please email me
at tr...@sage.org. I'm willing to relocate for the right opportunity.
I think this is a big step towards readability. It allows you to put
whatever part of the expression wherever you want (reminiscent of
Latin); i.e. always keep the important parts standing out. I also
think that the operator (especially a cool 3d-looking one like ~>) is
also much more readable than a word in this case.
It's a shame <~ is ambiguous. It's a lexical ambiguity, which can be
solved with whitespace....
Luke
> I think this is a big step towards readability. It allows you to put
> whatever part of the expression wherever you want (reminiscent of
> Latin);
You didn't think Perligata was just for *fun*, did you? ;-)
> It's a shame <~ is ambiguous. It's a lexical ambiguity, which can be
> solved with whitespace....
...and the longest token rule.
And, of course, it's no more ambiguous than the ~~ operator:
foo ~~ $bar # means: foo() ~~ $bar
# not: foo( ~ ~$bar )
Damian
Hello,
Can one see it as a shell redirection/pipe? This may sound funny,
but is the following ok?
@b <~ @a ~> @c; # @c = @b = @a;
(@b <~ @a) ~> @c; # same order i guess
so one can also:
@keep <~ grep /good/ <~ @list ~> grep /bad!/ ~> @throw;
is this if valid too?
@b ~> @a <~ @c; # push @a, @b, @c;
or: @b, @c ~> push @a;
qw/hello world/ ~> print
I guess it modifies $_
print "$_ \t %stat{$_} \n" <~ grep /^[Aa]/ <~ keys %stat
print "$_ \t %stat{$_} \n" for grep /^[Aa]/, keys %stat
Could we get pairs (or more), and also something like a step, for
example to only take one array elements every two?
Have a nice day,
Frederic
Just add ^~ and v~ and we've got our own Befunge flavor.
(a) OOh, shiny!
(b) Can <~ and ~> be used at the same time?
I'm not entirely sure of what functions take two array params
meaningfully, but could we do:
@a ~> grep (...) ~> sort ~> for <~ map (...) <~ @b {
(for content goes here)
}
With the understanding that
(1) EWWW, that is horribly ugly, but it was the first thing I could come
up with that meaningfully takes two list args
(2) Anyone who ACTUALLY does this with a for be shot on sight?
It would be more meaningful in another function that takes two lists and
does something useful, but without a body block ... More of a
@a ~> grep (...) ~> apply <~ sort <~ @b ;
So that the grep'd elements of @a are applied, 1:1, to the sorted @b ... ala
apply (grep (..., @a), sort(@b));
(again, more useful for a longer chain)
--attriel
Damian's proposal didn't say anything about array params. If I understood
him correctly, then this should print "FOO" on standard out:
my $foo = "FOO";
$foo ~> print;
The opposite 'squiggly arrow' fiddles the indirect object, so perhaps this
would print "FOO" on standard error (modulo the STDERR syntax, which I think
changed when I wasn't looking):
$foo ~> print <~ STDERR;
Philip
Disclaimer
This communication together with any attachments transmitted with it ('this E-mail') is intended only for the use of the addressee and may contain information which is privileged and confidential. If the reader of this E-mail is not the intended recipient or the employee or agent responsible for delivering it to the intended recipient you are notified that any use of this E-mail is prohibited. Addressees should ensure this E-mail is checked for viruses. The Carphone Warehouse Group PLC makes no representations as regards the absence of viruses in this E-mail. If you have received this E-mail in error please notify our ISe Response Team immediately by telephone on + 44 (0)20 8896 5828 or via E-mail at postm...@cpw.co.uk Please then immediately destroy this E-mail and any copies of it.
Please feel free to visit our website:
DOH! All the examples were using @'s, and somehow that translated to
"this is an array opthingy" :o
> $foo ~> print <~ STDERR;
That makes a fair amount of sense (and certainly more than any of my
array-based flawed examples :)
Thanks for clearing up my fogginess :o
--attriel
Hehe, yep ;-)
I'm not even sure how that would parse, though that:
@keep <~ grep /good/ <~ @list ~> grep /bad!/ ~> @throw;
would go like:
( @keep <~ grep /good/ <~ @list ) ~> grep /bad!/ ~> @throw;
which is probably not what i wanted...
Frederic
Brilliant! Keep pushing this. Finally, I'll be able to get investor
backing for my USB foot-pedal shift-key device. They say the first 20
million is the hardest...
Woo-hoo!
Q: How do you recognize a perl6 programmer?
A: His pinky is bigger than his thumb.
=Austin
> I'm not even sure how that would parse, though that:
> @keep <~ grep /good/ <~ @list ~> grep /bad!/ ~> @throw;
> would go like:
> ( @keep <~ grep /good/ <~ @list ) ~> grep /bad!/ ~> @throw;
>
> which is probably not what i wanted...
I would, from the descriptions, imagine that:
@keep <~ grep /good/ <~ @list ~> grep /bad!/ ~> @throw;
Would parse as:
@keep <~ grep /good/ <~ @list;
@list ~> grep /bad!/ ~> @throw;
Due to that being what is almost always going to be intended, I think.
Also, since we'd want $a <~ 2 + 4; to be $a = 6;, I would imagine that <~
and ~> would need low priorities. Further, since <~ stars at the end of
the list and works its way left, it would need a lower priority than ~>
which starts at the beginning and works its way right. So if it did have
a parenthetical variation, I would imagine it would be
@keep <~ grep /good/ <~ (@list ~> grep /bad!/ ~> @throw);
Which is, still, probably not what you wanted.
OTOH, I'm still new at posting here, and I may not be following all the
bits that came before :o
--attriel
Oh, then we just need a syntax to split the streams. ... I know!
@list ~| grep /bad!/ ~> @throw ~| grep /good/ ~> @keep;
which, of course, could be written in the more readable form:
@list ~| grep /bad!/ ~> @throw
~| grep /good/ ~> @keep;
And that, of course, leads us to sort of "unzip" were mutual exclusion
is not a requisite:
@list ~| grep length == 1 ~> @onecharthings
~| grep [0..29] ~> @numberslessthan30
~| grep /^\w+$/ ~> @words
~| grep $_%2==0 ~> @evennumbers;
:-)
Ummm, whellll... that depends on the semantics of A <~ B when A is not
a function. If it's just assignment, why not just use = ? But
assuming it does assign, yes, that's what it would do.
> so one can also:
> @keep <~ grep /good/ <~ @list ~> grep /bad!/ ~> @throw;
You're playing with my brain, here. That, in theory, would be
equivalent to:
(@keep <~ grep /good/ <~ @list) ~> grep /bad!/ ~> @throw;
@keep = @throw = grep /bad/, @list.grep(/good/)
So, in other words, no.
> is this if valid too?
> @b ~> @a <~ @c; # push @a, @b, @c;
(@b ~> @a) <~ @c;
(@a = @b) = @c
Would end up setting @a to @c.
> or: @b, @c ~> push @a;
> qw/hello world/ ~> print
I think it would be good to allow only one parameter on the left. The
latter is correct (except for qw// is spelled <<>>).
> I guess it modifies $_
> print "$_ \t %stat{$_} \n" <~ grep /^[Aa]/ <~ keys %stat
> print "$_ \t %stat{$_} \n" for grep /^[Aa]/, keys %stat
That is not at all how it works. Print would try to use
grep %stat.keys: /^[Aa]/
As a filehandle.
> Could we get pairs (or more), and also something like a step, for
> example to only take one array elements every two?
In that case you would probably just want to use the versatile C<for>
loop, instead of cluttering syntax to support that.
Luke
For the record, I think this is great.
> Brilliant! Keep pushing this. Finally, I'll be able to get investor
> backing for my USB foot-pedal shift-key device.
http://www.tuxedo.org/~esr/jargon/html/entry/double-bucky.html
--Dks
Nope. <~ and ~> only *rearrange* arguments, so if you only type @list
once, you can only do things that you could before when you typed
@list only once.
When we present this in the documentation (wishful thinking, now), it
will be important that we present it in precisely that way, as
argument rearrangers, lest people actually try that kind of foulplay.
In that documentation we should probably suggest that the arrows go
only one way per statement, otherwise you might not get what you
expect.
> Due to that being what is almost always going to be intended, I think.
> Also, since we'd want $a <~ 2 + 4; to be $a = 6;, I would imagine that <~
> and ~> would need low priorities.
Precedences. Yes.
> Further, since <~ stars at the end of the list and works its way
> left, it would need a lower priority than ~> which starts at the
> beginning and works its way right.
Not necessarily. <~ will necessarily need to be right-associative,
while ~> left, however. It would be logical to give them the same
precedence, except for the opposite associativity thing, where parsers
get different results based on their parse method. So different
precedences would be good only to ensure that different parsers saw
the same thing.
> So if it did have a parenthetical variation, I would imagine it
> would be
>
> @keep <~ grep /good/ <~ (@list ~> grep /bad!/ ~> @throw);
>
> Which is, still, probably not what you wanted.
Right. And probably not recommended.
> OTOH, I'm still new at posting here, and I may not be following all the
> bits that came before :o
You're quickly getting the hang of it.
Luke
Spookily, this quantumish operation can be achieved with Perl's
quantumish operators.
@list ~> (grep /bad!/ ~> @throw) | (grep /good/ ~> @keep);
I'd actually think I'd be happier if that didn't work. Fortunately, I
don't think it does (how do you put an argument on the end of a "|"
expression?)).
What we really need is a beam-split operator:
@list ~> (-grep /bad!/ ~|~ grep /good/) ~> @result;
Then @result would contain all things bad or good, but not both,
because they interfere! :)
> And that, of course, leads us to sort of "unzip" were mutual exclusion
> is not a requisite:
>
> @list ~| grep length == 1 ~> @onecharthings
> ~| grep [0..29] ~> @numberslessthan30
> ~| grep /^\w+$/ ~> @words
> ~| grep $_%2==0 ~> @evennumbers;
I'm not going even to try this one.
> :-)
(-:
Luke
Actually, if you can say "@a ~> sort ~> grep /foo/ ~> @output" then
it's pretty obvious that ~> is left-associative, a la << in C++.
Remember: cout << "Hello, world!" << nl;
First does cout<<"HW" and returns cout-prime,
then does cout-prime << nl
Likewise, the perl example does
@a ~> sort, returning @a-prime
@a-prime ~> grep /foo/, returning @a-2prime
@a-2prime ~> @output, returning @output-prime, I hope!
Reversing the direction:
@output <~ grep /foo/ <~ sort <~ @a
First does sort :@a, (I hope the syntax is right) returning @a-prime
then does grep /foo/ :@a-prime, returning @a-2prime
then does @output.operator() :@a-2prime
which we hope gets transmogrified into assignment, and I likewise hope
this will return @output-prime.
So <~ looks right-associative.
> > @keep <~ grep /good/ <~ @list ~> grep /bad!/ ~> @throw;
Assuming that <~ and ~> have equal precedence, and that there's not
some hideous special case backing this syntax, the above becomes:
1: @list ~> grep /bad!/
2: ~> @throw
3: grep /good/ <~
4: @keep <~
Which greps the @throw list for goodies -- not what I think you want.
> @keep <~ grep /good/ <~ @list;
> @list ~> grep /bad!/ ~> @throw;
> Due to that being what is almost always going to be intended, I
> think.
Which brings up the point: What DO we want here?
Frankly, I'm in love with the idea of a simple pipeline operator. I
find it really easy to write AND read scripts like this:
cat file
| sed -e ...
| grep -v ...
| nl
| sort -k ...
| awk ...
| sort
> output
Being able to "draw" the pipeline make it really readable for the
maintainer. The idea of doing something similar:
@a
~> grep
~> map
~> @output
is attractive. Regardless, I'm sure I don't like
$foo ~> print <~ STDOUT
That one's going to die a lonely death.
=Austin
So what we have is (using a scalar for an arbitrary variable) is:
$a ~> subroutine $arg1;
is equivalent to:
subroutine $arg1, $a;
and
subroutine $arg1 <~ $a;
is equivalent to:
subroutine $arg1 $a:; # or , equivalently, subroutine $a: $arg1;
and
.. ~> $a;
is equivalent to
$a = ...;
and similarly,
$a <~ ...;
is equivalent to
$a = ...;
~> is left associative, <~ right associative, have the same precedence,
and can't be mixed in one expression because of conflicting associativity
That means that a standard chain like:
@list ~> grep /good/ ~> map -> { s/good/bad/ } ~> @badlist;
would parse as
((@list ~> grep /good/) ~> map -> { s/good/bad/ } ) ~> @badlist;
to
((grep /good/ @list) ~> map -> {s/good/bad/ } ) ~> @badlist;
to
(map -> {s/good/bad/}, (grep /good/ @list)) ~= @badlist;
to
@badlist = (map -> {s/good/bad/}, (grep /good/ @list));
to
@badlist = map -> {s/good/bad/}, grep /good/ @list;
(modulo possible regex sytax).
Not sure if you aren't getting this backwards, but anyway I often find
myself confused with right and left.
> It would be logical to give them the same
> precedence, except for the opposite associativity thing, where parsers
> get different results based on their parse method. So different
> precedences would be good only to ensure that different parsers saw
> the same thing.
Actually I don't think you can define a grammar where two operators have
the same precedence but different associativity. Be it a pure BNF
grammar, or a classical yacc specification (using the %left and %right
declarations).
Congratulations on re-inventing C<part>. :^)
--Brent Dax <bren...@cpan.org>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)
"If you want to propagate an outrageously evil idea, your conclusion
must be brazenly clear, but your proof unintelligible."
--Ayn Rand, explaining how today's philosophies came to be
OK, but let it be known that the resulting megathread is now _your_
fault, not mine. :-) I have enough blamed on me.
> That way, everything is still a method call, the ultra-low precedence
> of
> <~ and ~> eliminate the need for parens, and (best of all) the
> expressions
> actually *look* like processing sequences.
I too think this idea is fabulous. You are my hero.
Let the record show that I came back to 50+ messages this morning, in
which nearly *all* were agreeing with each other, in this thread and
all the others. Wow. :_)
MikeL
Smiley aside, this is brilliant. It is nicely high-level (allowing for
parallelization/optimization behind the scenes), it reads nicely, and
it works as a high-leverage idiom.
I can see this as a nice basis for built-in threading below the level
of developer control. Also, it enables the "two dimensional coding"
that Damian likes.
And it doesn't have to be an array op. It could be a continuation op:
-$b |~> + sqrt($b ** 2 - 4*$a*$c) ~> $n1;
|~> - sqrt($b ** 2 - 4*$a*$c) ~> $n2;
(Yes, I know this would be a primo spot for a junction, but that's off
topic.)
So |~> does ~> except it remembers the LHS of the last invocation, if
one isn't provided (NOT the last ~>, but the last |~>).
Likewise <~| I guess, but what does it remember?
It could remember the object:
my WshObject $obj = $app.CreateObject($browser, $pfx);
MenuBar 0 <~| $obj;
ToolBar 0 <~|;
AddressBar 0 <~|;
Height 600 <~|;
Width 500 <~|;
Visible 0 <~|;
Or it could remember the method:
my ($a, $b, $c, $d) = get_some_objects();
MethodCall $arg1, $arg2, $exp - $re + $ssion <~| $a;
<~| $b;
<~| $c;
<~| $d;
Shiny! is right.
=Austin
-----Original Message-----
Rafael Garcia-Suarez <rgarci...@free.fr> wrote:
> Actually I don't think you can define a grammar where two operators have
> the same precedence but different associativity. Be it a pure BNF
> grammar, or a classical yacc specification (using the %left and %right
> declarations).
You are correct in stating that in a classical yacc specification, you can't
declare two operators to have the same precedence but different
associativity. But that's because syntactically you can't express the idea.
You'd have to do something like
%left PIPE_LEFT_OPERATOR
%right PIPE_RIGHT_OPERATOR
Or you could put them in the opposite order. But, syntactically, they do
have to be on different lines, and that makes them have different
precedence.
However, you could have the following productions in a yacc grammar:
exprB: exprA PIPE_LEFT_OPERATOR exprA
| exprA PIPE_RIGHT_OPERATOR exprA %PREC PIPE_LEFT_OPERATOR
;
(or something close to that -- it's been a while since I actually wrote yacc
grammars).
I assume that the generated parser would act in a manner similar to the way
it behaves when it catches you trying to chain together %nonassoc operators:
it generates a parse error.
And given the fact that (IMHO)
"hello, world" ~> print <~ STDERR;
is an abomination, a parse error would be just fine by me.
But cooler heads might just decree that the shift/reduce conflict is to be
resolved one way or another, so that
A ~> B~> C~> O <~ X <~ Y <~ Z
parses as either
(A ~>B ~> C ~> O) <~ (X <~ Y <~ Z)
or
(A ~>B) ~> C) <~ (O <~ X <~ Y <~ Z)
Neither is likely to be what you want, however. And given the level of
difficulty that most people have with precedence and associativity rules, I
think it reasonable to require the parens if you want to mix ~> and <~ like
that.
=thom
There are 10 kinds of people in the world:
those who understand binary, and those who don't.
Michael Lazzaro wrote:
> I too think this idea is fabulous. You are my hero.
I also think this is semantically fabulous but syntactically slightly
dubious. '~' reads 'match' in my book, so I'm reading the operators
as 'match left' and 'match right'. Or perhaps even 'stringify left'
and 'stringify right' with a different reading of '~'.
I would prefer something like <| and |> which has a more obvious
connotation (to me at least) of "pipe left" or "pipe right".
Damian is my hero regardless. :-)
A
But that would mean only perl6 could pass perl6, which isn't much different
from the perl5 situation, is it?
[Yes, I'm twisting things somewhat. the perl5 parser, written in C, can parse
perl5]
Although my brain thinks that having expressions with both <~ and ~> should
be illegal, because it's too damn confusing. Roughly:
<~ ... ~> # My brain leaking out of my ears
~> ... <~ # My brain collapses because it's under too much pressure.
Nicholas Clark
But with the different precedence. At last, I can assign from a list without
using parentheses:
@a = 1, 2, 3; # newbie error
@a <~ 1, 2, 3; # would work
Something else springs to mind. Consider the C<for> syntax:
for 1,2,3 ~> foo -> $a { ... }
Is there any way we could unify these two operators without creating
ambiguities? If we
could, then using straight arrows would be nicer to type than the squiggly
ones.
Dave.
I meant that if <~ and ~> are going to have the same precedence, you
can't parse
s ~> t <~ u
It's not a well formed phrase of the language (even though this language
can't described by a nonambiguous BNF grammar.)
In fact, this is different from the Perl 5 situation you're alluding to.
or :
@a <~ 1 <~ 2 <~ 3;
or :
1, 2, 3 ~> @a;
which would be also written as :
3 ~> 2 ~> 1 ~> @a;
shoot me :
3 ~> 2 ~> @a <~ 1;
(Aha, Damian's 1st proposal seems to imply that <~ has highest precedence
than ~>).
> Something else springs to mind. Consider the C<for> syntax:
>
> for 1,2,3 ~> foo -> $a { ... }
>
> Is there any way we could unify these two operators without creating
> ambiguities? If we
> could, then using straight arrows would be nicer to type than the squiggly
> ones.
I think I see what you're saying...
$a ~> foo;
calls foo on $a, while
$a -> $x { ... }
um, does nothing... OK, I didn't see what I thought I said.
Actually, I do see something like:
$a ~> -> $x { ... }
as having meaning, namely "call the anon sub with $a as an argument.
Does syntax already exist for doing that? Can one do:
-> $x { ... } ($a);
already?
If not, then the "~> ->" construct has a use, perhaps a semi-common use,
and perhaps it should be simplified. Not to suggest another operator
here, but "$a ~-> $x { ... }" anyone?
But you were looking for a way to play off their similar meanings to
avoid having to use a tilde....
The BNF for anonymous subs is something like (I haven't read the
existing grammars, so if I'm not using the standard terms...sorry):
anon_sub :== "sub" block
| "sub" "(" paramlist ")" block
| "->" block
| "->" paramlist block
The BNF for left-to-right pipelines would be something like:
lr_pipe :== lr_pipe "~>" variable
| lr_pipe "~>" function_call
If we were to combine -> and ~>, would it lead to any ambiguity? I'm
not sure. Certainly we'd be talking about more than a one-token lookahead.
Actually, I'm not sure the lr_pipe is unambiguous in its own right. I
don't have it complete, obviously, but I see problems with the two calls
as is...
What is the result of:
$input ~> %functionTable{$state} ~> $state;
Is it equivalent to:
%functionTable($state) = $input;
$state = %functionTable($state);
or
$state = %functionTable($state).($input);
How does the grammar differentiate between the two?
Or would I have to type
$input ~> %functionTable{$state}.() ~> $state;
instead?
>
>
> Dave.
>
>
>
I don't like either of these operators. What's wrong with "@out = sort map
{...} grep {...} @a"?
__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com
> I love this.
>
> And any class could override the <~ operator, right?
Right.
> I suppose it could be done like arithmetic
> overloading, if you define both <~ ("I'm being pointed at from the right")
> and ~> ("I'm being pointed at from the left") in your class then Perl will
> use whichever appears in code, but if you define just one, Perl will use
> it for both.
Hmmmm. Maybe. I'm not certain that Perl 6 operator overloading will be as
highly dwimical as Perl 5's is.
Damian
> Damian's proposal didn't say anything about array params. If I understood
> him correctly, then this should print "FOO" on standard out:
>
> my $foo = "FOO";
> $foo ~> print;
Correct.
> The opposite 'squiggly arrow' fiddles the indirect object, so perhaps this
> would print "FOO" on standard error (modulo the STDERR syntax, which I think
>
> changed when I wasn't looking):
>
> $foo ~> print <~ STDERR;
Bad Philip! Wicked, wicked Philip!
;-)
One *might* argue that <~ ought to be of higher precedence than ~>
(i.e. that invocants ought to be bound ahead of other arguments).
If so, then:
$foo ~> print <~ $*STDERR
is really:
$foo ~> print $*STDERR:
is really:
$foo ~> print $*STDERR: $foo
So yes.
But don't do that!
;-)
Damian
> Oh, then we just need a syntax to split the streams. ... I know!
>
> @list ~| grep /bad!/ ~> @throw ~| grep /good/ ~> @keep;
Unfortunately, that's already taken (it's the bitwise-OR-on-a-string operator).
Fortunately that doesn't matter, since no extra binary operator is actually
needed to achieve the unzipping you desire.
All we need is a unary prefix form of ~>.
Unary ~> would (by analogy to unary dot) append the current topic to the
argument list of its operand.
Thus, your examples become simply:
given @list {
~> grep /bad!/ ~> @throw;
~> grep /good/ ~> @keep;
}
And:
given @list {
~> grep length == 1 ~> @onecharthings;
~> grep [0..29] ~> @numberslessthan30;
~> grep /^\w+$/ ~> @words;
~> grep $_%2==0 ~> @evennumbers;
}
Damian
> I'm not even sure how that would parse, though that:
>
> @keep <~ grep /good/ <~ @list ~> grep /bad!/ ~> @throw;
>
> would go like:
>
> ( @keep <~ grep /good/ <~ @list ) ~> grep /bad!/ ~> @throw;
Correct, if <~ is indeed slightly higher precedence than ~>
> which is probably not what i wanted...
True. The presence of both operators in an expression probably ought
to trigger a (silenceable) warning.
Damian
> I also think this is semantically fabulous but syntactically slightly
> dubious. '~' reads 'match' in my book,
Really? We don't have any trouble in Perl 5 with an = character
being used in various unrelated operators:
== comparison
= assignment
~= match
=> comma
<= less than or equal to
or with - as a component of each of:
-- decrement
- difference
-= subtraction
-> dereference
-X file op
I'm just suggesting the same for the ~ character:
~~ smart-match
~ concatenate
~| stringy bitwise OR
~> append args
<~ invocate
> I would prefer something like <| and |> which has a more obvious
> connotation (to me at least) of "pipe left" or "pipe right".
I can certainly see the appeal, and I did consider this very alternative
(after Dan had privately suggested the two symbols to me). But they simply
don't work as well visually.
I mean, compare:
@a ~> grep {...} ~> map {...} ~> sort ~> @a;
@a <~ sort <~ map {...} <~ grep {...} <~ @a;
with:
@a |> grep {...} |> map {...} |> sort |> @a;
@a <| sort <| map {...} <| grep {...} <| @a;
I don't know about *your* font, but in mine the ~> and <~ versions are
at least twice as readable as the |> and <| ones.
Damian