Re: A set of new operators. In keeping with the design of Perl?
by Juerd (Abbot) on May 19, 2003 at 06:45 UTC
|
Perhaps the best example of this is $var ||= 100; which is shorthand for $var = 100 unless $var; or even if( not $var ) { $var = 100; }
Actually, it's a shorthand for $var = $var || 100;, just like how $var += 4; is a shorthand for $var = $var + 4;
?<:=
?>:=
?<=:=
?>=:=
?lt:=
?gt:=
?ge:=
?le:=
I don't like them. Too hard to remember and too ugly.
maybe in perl 6?
http://dev.perl.org/perl6/list-summaries/p6summary.2003-02-09.pod.html#shortcut%20=
Finally, is it possible to invent new operators using overload? Or would you have to resort to source filters to implement this outside of the core?
No; yes.
Juerd
# { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }
| [reply] [d/l] [select] |
|
|
Thanks for the link juerd, I hadn't seen that discussion. However, I think that my idea is quite different to that proposal which suggested a short-hand for the trinary operator involving 3 operands.
eg. $var ??= $x : $y;
The operators I am seeking only involve 2 operands.
Too hard to remember ...
This: $var = $var op $expr ? $var : $expr;
becomes this: $var ?op:= $expr;
Is that hard to remember?
...and too ugly.
Agreed, they ain't beauiful. I was trying to retain the notions of the ternary and the operators and the assignment, but as they are no longer ternary, maybe the ? or the final = could be dropped:
# Instead of these these or these?
$lvalue ?<:= $rvalue; $lvalue <:= $rvalue; $lvalue ?<: $rvalue;
+
$lvalue ?>:= $rvalue; $lvalue <=:= $rvalue; $lvalue ?>: $rvalue;
+
$lvalue ?<=:= $rvalue; $lvalue >:= $rvalue; $lvalue ?<=: $rvalue;
+
$lvalue ?>=:= $rvalue; $lvalue >=:= $rvalue; $lvalue ?>=: $rvalue;
+
$lvalue ?lt:= $rvalue; $lvalue lt:= $rvalue; $lvalue ?lt: $rvalue;
+
$lvalue ?gt:= $rvalue; $lvalue le:= $rvalue; $lvalue ?gt: $rvalue;
+
$lvalue ?ge:= $rvalue; $lvalue gt:= $rvalue; $lvalue ?ge: $rvalue;
+
$lvalue ?le:= $rvalue; $lvalue ge:= $rvalue; $lvalue ?le: $rvalue;
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] [d/l] [select] |
Re: A set of new operators. In keeping with the design of Perl?
by Abigail-II (Bishop) on May 19, 2003 at 11:41 UTC
|
Perl6 will have user defined operators, so you can always
create a module that defines the operators you propose.
It also is going to have a pluggable parser, so you could
even do it on the parser level.
In Perl5, you cannot define new operators using overload.
You can give new meaning to existing operators though. So
you could always pick an operator you hardly use, and give
the meaning like you give for instance ?le:=, use
that for a while and see whether you really use that so often
it would warrant inclusion in the Perl core.
As for // and //=, the development track
for 5.9.0 has those operators.
Abigail | [reply] |
Re: A set of new operators. In keeping with the design of Perl?
by htoug (Deacon) on May 19, 2003 at 08:25 UTC
|
Us die-hard old-timers who have been brought up on archaic languages like C are quite familiar with the operators you mention - they are taken from C.
Now that newfangled //= operator is something else - I seem to recollect (foggily that is) that it took several years and approximately 3 cubic lightyears of flames on the P5P list before it was accepted.
Now don't you start along that road young whipper-snapper - we'll rustle up a posse of compatibility police and chase you out of the territory.
Seriously: I don't think I have had use for your suggested operators more than a couple of times, and so I don't think it would be worth the trouble. Implement them as functions - that would get rid of the evaluate twice problem. You can even call them meaningfull and pretty names like 'max', 'min' and so on.
Wouldn't that solve your problems? | [reply] |
|
|
module In::Extremis;
multi infix:max= (Num $curr is rw, Num $new) is exported {
$curr = max $curr, $new;
}
multi infix:min= (Num $curr is rw, Num $new) is exported {
$curr = min $curr, $new;
}
Oops! Too late. ;-) | [reply] [d/l] [select] |
|
|
Having cut my teeth on C back in the late 70's, I think the "old-timers" is probably a closer fit to me, than "young whipper-snapper", but both points taken:)
Codifying the operators into subs like 'min' and 'max' works where the semantics of the operation fits the names, which isn't always the case, but there are a couple of problems with that.
You need a 'min_str', min_str_i' and 'min_num' to really cover all bases.
The cost of building stack frames for an operation where all the information the compiler needs to make the assignment is available right there in the expression seems proflagate.
Were it possible for the compiler to do sub-expression elimination that might eleviate some of the problem, but then you need to make special cases for the possibility that the double side effect is actually what the programmer intended (as horrendous doing so would be:),
I would stil have to type/maintain both instances of both operands though. Not onnerous, but another source of potential bugs.
The P6 macro facility might address some of the issues, but the double-side-effects problem of C macro fame would probably persist. I haven't gleaned enough information on the P6 object mechanisms yet to work out whether it is possible to add operators/methods to the base 'types'.
Maybe TheDamian or Elian know?
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] |
|
|
You need a 'min_str', min_str_i' and 'min_num' to really cover all bases.
You can get most of the way there with multimethods. Which, fortunately, Perl 6 has:
multi max (Str *@candidates) {
reduce {$^a gt $^b ?? $^a :: $^b} @candidates;
}
multi max (Num *@candidates) {
reduce {$^a > $^b ?? $^a :: $^b} @candidates;
}
However, I suspect that won't be sufficiently Lazy for Perl 6. So my preference is for a max function that selects what kind of comparison to do, based on call context:
sub max (*@args) {
if want~~Str { reduce {$^a gt $^b ?? $^a :: $^b} @args }
else { reduce {$^a > $^b ?? $^a :: $^b} @args }
}
$biggest_str = ~max @values; # Str context, so use gt
$biggest_num = +max @values; # Num context, so use >
$biggest_num = max @values; # scalar context, default to >
And to get all the way there (i.e. to allow for user-specified comparisons such as case-insensitive), max would have an optional closure argument (just as sort does now) so that the comparator could be explicitly specified:
# Let call context decide...
multi max (*@args) {
if want~~Str { reduce {$^a gt $^b ?? $^a :: $^b} @args }
else { reduce {$^a > $^b ?? $^a :: $^b} @args }
}
# Let the user specify...
multi max (&compare, *@args) {
reduce {compare($^a,$^b)>=0 ?? $^a :: $^b} @args;
}
$biggest_str = ~max @values;
$biggest_num = +max @values;
$biggest_num = max @values;
$biggest_mag = max {abs $^a <=> abs $^b} @values;
$biggest_lookup = max {%hash{$^a} cmp %hash{$^b} @values;
| [reply] [d/l] [select] |
|
|
|
|
|
Re: A set of new operators. In keeping with the design of Perl?
by Elian (Parson) on May 19, 2003 at 12:26 UTC
|
Your scheme would still need to evaluate the conditional twice (once in boolean context, and once in either scalar or list context), so if that's what youre looking to stop you're out of luck. There wouldn't be anything to stop you from bodging this together as a new parser rule for perl 6, I suppose. | [reply] |
|
|
It wasn't an efficiency issue (for a change:), it was my other windmill, that of elegance, 'once and once only', duplcated code is two chances to get wrong etc.
Realise that there i no way to avoid (in assembler terms), loading the two values, comparing them, branching if condition not satisfied, do the assignment.
But avoiding the need for the programmer to type the terms twice each as well as the potential for invoking the rvalue expression twice when it could be a volatile function or one with side effects appealled to me.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] |
|
|
I disagree - I think you need to evaluate the conditional once in scalar or list context, as appropriate, and then evaluate that result in a boolean context. Which implies that if the conditional involves an expensive operation, that operation need only be invoked once.
Of course, people that write clever stuff would need such behaviour documented, but that'd be true whichever approach were selected. And with the entire grammar so mutable, chances are a couple of extra lines in the docs could even show how to avoid this behaviour.
Hugo
| [reply] |
Re: A set of new operators. In keeping with the design of Perl?
by hardburn (Abbot) on May 19, 2003 at 14:18 UTC
|
We also have the ternary operator ? : ; which is often used in expressions like
That'll be ?? :: in Perl6.
?>:=
I think that is too much information to store in 4 ASCII characters. Some might argue that ? : already goes too far with information-packing. I personally learned C/C++ in a high school class (one of the very few languages I actually took a structured class for) and was never taught about the ? : operator. I never saw it until I learned Java, and even then I almost never used it until I learned Perl. It was a shortcut (and one of the things Java avoids religiously is shortcuts), and I didn't really "get it" for quite some time. Naturally, Perl religiously embraces shortcuts, but I think the operators you propose go too far.
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
Note: All code is untested, unless otherwise stated
| [reply] [d/l] [select] |
|
|
$x =min $x, $y; # p5
$x ?>:= $y; # my half-assed notion:)
$x min= $y; # p6+
$x =max $x, $y; # p5
$x ?<:= $y; # Mine
$x max= $y; # p6+
The most recent situation where I encountered this was
for ( 0 .. $#{ $hash{$set}{data} } ) {
$hash{$set}{min} = $hash{$set}{min} < $hash{$set}{data}[$_]
? $hash{$set}{min}
: $hash{$set}{data}[$_];
}
which starkly demonstrates the problem. Contrast that with
$hash{$set}{min} ?<:= $hash{$set}{data}[$_] for 0 .. $#{ $hash{$set}{d
+ata} };
Which is easier to read?
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] [d/l] [select] |
|
|
for ( 0 .. $#{ $hash{$set}{data} } ) {
$hash{$set}{min} = $hash{$set}{min} < $hash{$set}{data}[$_]
? $hash{$set}{min}
: $hash{$set}{data}[$_];
}
I personally find the above solution easier to read. However, since this is in a loop, and regular ? : evaluates the data twice, your proposed operator could be considerably faster in some cases. Naturally, the premature optimization alarms are ringing here, so I'm going to stop typing now (:
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
Note: All code is untested, unless otherwise stated
| [reply] [d/l] [select] |
|
|
$x =min $x, $y; # p5
For me that's perfect.
A function min - thats just three chars, you add = and what you have is the same number of chars (for golfers), much more clear than ?<:=, and more flexible - it can handle lists instead of just pairs.
Update: Sorry this was just just a temporary blurr of my consiousness. It did not address the arguments by BrowserUk. | [reply] [d/l] [select] |
|
|
my $set = $hash{$set};
my $data = $set->{data};
for (@$data) {
$set->{min} = $set->{min} < $_ ? $set->{min} : $_;
}
Hugo | [reply] [d/l] |
|
|
use List::Util qw(min);
$hash{$set}{min} = min @{$hash{$set}{data}};
I love that module. Thank goodness it's in the core since 5.8. Of course that doesn't address your beef, but in this case I think you're looking for aliasing, not a condensed form of the ternary. Some of that is available with Perl5 already, had you phrased your loop differently:
for (@{$hash{$set}{data}}) {
$hash{$set}{min} = $hash{$set}{min} < $_
? $hash{$set}{min}
: $_;
}
And in Perl6 (I'm probably getting the syntax wrong) it'd be something like:
my $min := $hash{$set}{min};
for(@{%hash{$set}{data}}) { $min = $min < $_ ? $min : $_ }
Makeshifts last the longest. | [reply] [d/l] [select] |
|
|
|
|
Re: A set of new operators. In keeping with the design of Perl?
by zby (Vicar) on May 19, 2003 at 08:29 UTC
|
The ternary operator is allready rather rarely used. A shortcut that is not used daily is easily forgotten and then it is not usefull at all it just obscures the code.
It would be usefull to count the use of some language constructs on some big standard sample - to have the numbers. The difficult thing would be to agree on what a standard sample is. | [reply] |
|
|
| [reply] |
|
|
| [reply] [d/l] [select] |
|
|
|
|
Re: A set of new operators. In keeping with the design of Perl?
by gmpassos (Priest) on May 19, 2003 at 18:51 UTC
|
You are just talking about "Syntax Sugar". Don't think that what you write is exactly what happens behind scenes.
Just because you write the variable once, this doesn't means that it will be called once in the interpreter. For example:
$x = $x * $y ;
## With the Syntax Suger:
$x *= $y ;
But note that internally it works like the first! It get the value of $x, multiply by $y, than save the result in $x.
But this are different:
$var = $var . 'xyz' ;
$var .= 'xyz' ;
The 1st rewrite all the variable, with the extra of 'xyz'. the 2nd just append 'xyz' to $var.
So, how do you think that the interpreter will work with this 2 ways?:
$latest = $latest > time() ? $latest : time();
## With your Syntax Suger:
$latest ?>:= time() ;
The only good thing in the 2nd is to avoid the rewrite for it self ($latest = $latest ;) of the 1st option. But why not just write:
## Probably what should be made internally:
my $tmp = time() ;
$latest = $tmp if $latest > $tmp ;
Personally I don't like to use much Syntax Sugar, unless the basic (.= += .... $x++). I don't like them for conditional blocks, since I think that this part need to be explicity, since other programers need to know how to read your code (and generally they don't know much about Syntax Sugar). But of course that your idea is valid, since is original. ;-P
Graciliano M. P.
"The creativity is the expression of the liberty". | [reply] [d/l] [select] |