Re: why does push not default to $_? (simple)
by tye (Sage) on Dec 05, 2008 at 04:07 UTC
|
print has a quite complex signature. It must distinguish between print $this; and print TO_THIS;, for example. So it also can tell between print @empty; and print;.
push is quite simple. You can write your own sub that offers the exact same interface:
sub Push(\@@);
So what to push onto the array is simply a (flattened) list (of scalar values). So push can't tell the difference between push @a; and push @a, @empty;... unless its simple interface gets special-cased for this. I'm not surprised that such special-casing was not deemed worth allowing the questionable usage of an implied $_.
At some point, somebody did some extra work to add the warning you get. The code you want would be added at the same point, but it would have to synthesize code to push the current value of $_ onto the stack before the push opnode (or thereabouts). That is certainly more work than just emitting a warning.
But then you'd have to fight the backward-compatibility battle -- which, frankly, I would consider a rather silly battle since transforming something that is useless and emits a warning into something useful (but perhaps of dubious wisdom) seems quite reasonable regarding backward compat.
| [reply] [d/l] [select] |
|
Am I understanding you right, the prototyope mechanism of builtins like push can't distiguish between missing parameters and empty parameters. But some special functions like "print" and "splice" have a proper non-prototype-based interface? (*)
I'm not really missing that feature, it's just a meditation about design and orthogonality.
IMHO, it would be much easier to prog if perl had more axiomatic rules instead of a bunch of special exeptional cases. Something like "if the last obligatory list @ or scalar $ in a prototype is ommitted in the code, $_ will be included instead throwing an error".
Or as more flexible approach "you can use "@_" and "$_" in prototypes to flag parameters which default to $_ if missing" ²
anyway, perl6's solution to flag these functions with a trailing . and making them methodes of an invisible $_ seems reasonable! (eg .print; .push @a;)
UPDATES:
(*) Must be! That's why prototype returns undef for print and split, showing they are not overridable!
DB<10> use Data::Dumper
DB<11> print Dumper prototype "CORE::split"
$VAR1 = undef;
DB<12> print Dumper prototype "CORE::print"
$VAR1 = undef;
DB<13> print Dumper prototype "CORE::push"
$VAR1 = '\\@@';
(²) But I don't know if it makes sense to push a global like $_ on the stack... | [reply] [d/l] [select] |
|
validate_pos 1, ( { default => $_ } ) x ( @_ - 1 )
UPDATE: Oops, that last snippet doesn't make any sense. Indeed, as I think about it further, what does it mean to have an array of values, all of which default to $_ if absent? I think it's best to stick with the case of allowing explicitly listed parameters to default:
validate_pos 1, ( { default => $_ } ) x 57
| [reply] [d/l] [select] |
|
|
|
Re: why does push not default to $_?
by ikegami (Patriarch) on Dec 04, 2008 at 21:38 UTC
|
push @a, @b;
It would push $_ when @b is empty instead of push nothing as expected.
Update: Or maybe not. That's doesn't break print, after all.
| [reply] [d/l] [select] |
|
Good argument, but whats the difference to
print @b;
if @b is empty? It doesn't print $_
for (1..13) {
print @b;
}
Furthermore there is no error with:
push @a, @b;
but you get a warning with
push @a;
so perl can distinguish between missing parameters and empty parameters...
| [reply] [d/l] [select] |
|
Yeah, I already noticed and updated my node.
The only possible reason I could see if an undue burden on the parser, since it would be the first function to default the second argument. You could send a perl (wishlist) bug report?
| [reply] |
|
|
Re: why does push not default to $_?
by tilly (Archbishop) on Dec 05, 2008 at 00:51 UTC
|
I would guess that Larry never thought that anyone really wanted that shortcut. So it never happened.
While I wouldn't personally object if it was added to Perl, I would object if I had to maintain code that used that shortcut... | [reply] |
Re: why does push not default to $_?
by perreal (Monk) on Dec 06, 2008 at 03:00 UTC
|
Well, I think print and push are different in that
when you see:
print;
it feels like you want to print something, that thing being directly related to the context (default arg) makes sense.
on the other hand:
push @a;
feels like we want to push @a to some place... like a stack. If there was a default stack than the right action would be to push @a to the default stack.
So, I guess it is more about linguistics than implementation, | [reply] [d/l] [select] |
|
There is a default stack. At least according to shift and pop.
Making 1-arg push (and unshift) work with @_ (or @ARGV) as a default 1st arg would, IMHO, be more consistent (I have accidentally expected this behaviour once). Unfortunately, its not terribly useful. I don't find myself adding to @_ frequently.
| [reply] [d/l] [select] |
|
It's not a good idea. The only thing you could push onto the "stack" is would be the contents of an array. For example, you can't make push $foo; work without breaking push @foo, $x;. The usefulness of the feature is just too limited to compensate for the confusion the its implementation would cause.
| [reply] [d/l] [select] |
Re: why does push not default to $_?
by ptoulis (Scribe) on Dec 06, 2008 at 00:48 UTC
|
The Camel book gives a good hint: "The underline is the underlying operand in certain operations."
These "certain operations" are the unary functions and the iterators like foreach,for, map{}, grep{}. The idea is that in a unary function there is only one operand and since these are used very often and Perl is Huffman encoded, it makes great sense to have a special name when this operand is not specified.
The push function is not unary and it would be a bad idea to include special names in its operands. Moreover, push mutates its first operand and it would really be a bad idea to change data and at the same time hide from the developer how the data is being changed. | [reply] [d/l] [select] |
|
> Moreover, push mutates its first operand and it would really be a bad idea to change data and at the same time hide from the developer how the data is being changed.
Well for me, calling push with only one parameter is quite obvious. At least not less than print without parameter.
Please, in which chapter did you find that quote in the camel book?
UPDATE: here what I found in 2.9.3 Global Special Variables
Here are the places where Perl will assume $_ even if you don't use it:
* Various unary functions, including functions like ord and int,
as well as all the file tests (-f, -d) except for -t, which defaults to STDIN.
* Various list functions like print and unlink.
* The pattern-matching operations m//, s///, and tr/// when used
without an =~ operator.
* The default iterator variable in a foreach loop if no other variable
is supplied.
* The implicit iterator variable in the grep and map functions.
* The default place to put an input record when a <FH> operation's
result is tested by itself as the sole criterion of a while test. Note that
outside of a while test, this will not happen.
Mnemonic: underline is the underlying operand in certain operations.
Well various doesn't sound very specific, and print and unlink are not unary. | [reply] |
|
Well for me, calling push with only one parameter is quite obvious. At least not less than print without parameter.
The difference is that print does not alter its operands but push does. Even ignoring these there is hardly a good reason to use $_ for push. For example, in iterators which set the $_ you might want to use something like:
for(1..100) { push @a;}, but still you would be better going by push @a,(1..100);
Please, in which chapter did you find that quote in the camel book?
You can find the quote in Chapter 28-Special Names, page 659.
| [reply] [d/l] [select] |
|
Re: why does push not default to $_?
by JavaFan (Canon) on Dec 06, 2008 at 02:13 UTC
|
I meditated but couldn't find a special reason, do you know any?
Simple, because noone found it interesting enough to actually sit down and write a patch. That's how perl5 development works. New features don't get added if enough people want them. New features get added if one person wants it badly enough to write a patch.
So, if you want push to accept a default second argument, write a patch and submit it. I'm not in charge, so I won't have a final say whether it will get in, but if you have the patch, you'll have a pretty good chance. Without the patch and just the wish, chances are almost non-existant.
| [reply] |
|
| [reply] |
|
I never said I want that push accepts a default second argument, I just want a consistent and orthogonal behaviour.
Then Perl isn't your forte. Perl was designed with the human mind and natural languages in mind - neither of which are consistent or orthogonal. (BTW, my 'you' was a generic you, not specifically aimed at you).
It may be the occupational disease of a mathematician, but I just prefer a predictabel symmetry in logical systems!
Guido van Rossum is a mathematician as well. Hence Python. (This isn't meant as a jab at Python - far from it; Python is a nice language, it just has a different philosophy than Perl).
| [reply] |
|
|
|
|
|
Re: why does push not default to $_?
by toolic (Bishop) on Dec 04, 2008 at 21:40 UTC
|
Update: OK, I sit corrected :) I guess I missed the point of the question.
push is a Perl built-in function which requires 2 arguments.
Of related interest: Builtin functions defaulting to $_
| [reply] |
|
push @a;
push @a, 'a';
push @a, 'a', 'b';
Second, if it was true, that doesn't answer why the second parameter can't be optional, defaulting to $_.
| [reply] [d/l] [select] |
|
push @a;
It is syntax which will compile, but it does generate a warning. Can you show an example of where this would be used?
use strict;
use warnings;
use diagnostics;
use Data::Dumper;
my @a = 1..3;
push @a;
print Dumper(\@a);
__END__
% ./728108.pl
Useless use of push with no values at ./728108.pl line 9 (#1)
(W syntax) You used the push() or unshift() function with no argum
+ents
apart from the array, like push(@x) or unshift(@foo). That won't
usually have any effect on the array, so is completely useless. It
+'s
possible in principle that push(@tied_array) could have some effec
+t
if the array is tied to a class which implements a PUSH method. If
+ so,
you can write it as push(@tied_array,()) to avoid this warning.
$VAR1 = [
1,
2,
3
];
| [reply] [d/l] |
|
|
|
|
Re: why does push not default to $_?
by mr_mischief (Monsignor) on Dec 08, 2008 at 21:49 UTC
|
My first guess would be that push is paired with pop. You might very well want to say, for example, pop @foo; without putting what was popped anywhere. If push() took $_ by default, one might expect pop() to assign to $_ by default. Logical pairs that don't both deal with the same implicit variable should probably neither one do so. | [reply] [d/l] |