Re: Perl oddities
by jmcnamara (Monsignor) on Mar 01, 2005 at 10:40 UTC
|
I find the return value of a hash in a scalar context odd.
$ perl -le '%h = (a =>1, b => 2); print scalar %h'
2/8
From perldata:
If you evaluate a hash in scalar context ... the value returned is a string consisting of the number of used buckets and the number of allocated buckets ...
Buckets!
I can't imagine that this is useful to anyone except the implementor of the hashing function and the occasional person with pathological data.
It would be much more useful, or sensible, if hash in a scalar context returned the number of keys:
$ perl -le '%h = (a =>1, b => 2); print scalar keys %h'
2
And before anyone leaps to the defense of this artifact I'm just stating that I find it odd. I can live with it.
I think that there were a lot of things that I used to find odd but since I can't remember what they are I guess that I've just come to accept them. :-)
--
John.
| [reply] [d/l] [select] |
|
In Perl 6, a hash in scalar context will return a reference to the hash, which will behave appropriately in boolean, numeric, or string contexts. (You'll have to call a special method to get the bucket filling information.) I'd like to note for the record, however, that the main reason hashes did not return the number of keys by default in numeric context in Perl 5 was that it was potentially a very expensive operation on DBM files and the like. But Perl 6 will gladly let you hang yourself by the foot there...
| [reply] |
|
I also find this artifact useless, but a saving
grace is that you can at least say:
if (%hash)
{
# it's not empty
}
even though the string "0/8" evaluates to true. | [reply] [d/l] |
|
| [reply] |
|
Update: Nonsense below, I misread the post.
It would be much more useful, or sensible, if hash in a scalar context returned the number of keys:
As soon as you try to use it as a number, "2/8" will be numified to 2 so actually it does effectively return the number keys.
perl -le '%h = (a =>1, b => 2); print %h+0'
2
The number of buckets is some bonus info for free.
| [reply] [d/l] |
|
In the above case yes but as the number of keys is increased the buckets will get reused and the result won't be correct:
$ perl -le '%h = (1 .. 10); print scalar %h'
5/8
$ perl -le '%h = (1 .. 12); print scalar %h'
5/8
$ perl -le '%h = (1 .. 100); print scalar %h'
33/64
:-)
Actually, I searched for a genuine use for this feature for a long time and I almost found one: Power Twool.
--
John.
| [reply] [d/l] |
|
Re: Perl oddities
by Anonymous Monk on Mar 01, 2005 at 12:10 UTC
|
| [reply] [d/l] |
|
Now that Perl 6 has interesting values of undef, it's easy to fix system, though we will probably rename it just to avoid confusion. Make it sysrun, or maybe just run.
open returns a filehandle object in Perl 6.
Perl 6 will have a switch statement because we finally figured out how it relates to smart matching and topicalization and exception handlers.
The IO system for Perl 6 will be truly OO and not just made to look that way like Perl 5 did. So it'll be fairly easy to have whatever odd methods you like on derived IO classes, including regional locking.
The parsing rules for function parentheses have been regularized in Perl 6, though not necessarily to everyone's delight. ;-)
| [reply] [d/l] [select] |
|
system returning true on failure, false on success. I know why it's doing that, I know where it's coming from (and that's why), but it still makes me gag each and every time I use it.
I think Larry realises this. I'm hoping that Perl6's system function knows to do something like return $rc but ! $rc. Then 0 would be true and non-zero would be false, when checked in boolean context, but the return code would still be available:
my $rc = system(...);
unless ($rc)
{
print "system failed with rc = $rc!\n";
}
(Or something like that - my perl6 isn't rusty, it's just not there yet ;->) | [reply] [d/l] [select] |
|
IMO system() (and related ops) should just raise an exception on error. There is no reason to force everyone to write all these return code checks when 90 % of the time you'll want to bail out on error anyway (and if not, you can use eval, or try() in perl6).
| [reply] |
|
But it doesn't have a (native) switch.
No fair, picking on explicit design decisions. :-)
Warn (wrongly) for one particular function
What's wrong about the warning? It's there to prevent the common pitfall of expecting things like this to work right:
print (stat)[9];
And seems like a perfectly reasonable warning. Many other warnings are special-cased and very specific, so I don't know why you chose this one.
Update: I didn't realize the warning would trigger with one and only one space. That does seem kind of peculiar. But if that was the crux of what the OP was talking about, it wasn't exactly clear. | [reply] [d/l] |
|
| [reply] [d/l] [select] |
|
As noted, I find the oddity in that it warns about exactly one space - althought it doesn't do that always:
perl -wle 'print ("foo")' # Warning
perl -wle 'print ("foo");' # No warning
perl -wle 'print (")");' # Warning
perl -wle 'print ("\x29");' # No warning
Now, I know why it's happening (I've studied the source), and I also know what the intent is, but that's beside the point. brian asked about oddities, and I do find this an oddity.
But the single space is not the only thing that I find an oddity. I also find it odd (as in, irregular, different that you would expect based on how similar constructs are handled - you know, what brian was asking for - so spare me the explainations on why it is this way - I know already) that is only has these warnings for print and I think one other function. For other functions, it doesn't warn.
$ perl -wle 'print ("foo") . "bar"'
print (...) interpreted as function at -e line 1.
Useless use of concatenation (.) or string in void context at -e line
+1.
foo
$ perl -wle 'my $s = length ("foo") . "bar"'
Why warn only with print and a single space, but not with length or other functions? Or other amounts of whitespace? That I find an oddity. | [reply] [d/l] [select] |
|
Re the last one, it should simply be gotten rid of. The reason it's there is to keep you from accidentally saying print (1+2)/3;. That now gives /both/ a useless use of division in void context and a print interpreted as function. The "print interpreted as function" was there long before the "... in void context"; the later is more useful, but was harder for perl to notice.
Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).
| [reply] [d/l] |
Re: Perl oddities
by Joost (Canon) on Mar 01, 2005 at 11:03 UTC
|
my $fh = open "<","filename";
$fh->print "stuff";
$fh->close;
Which would also make it easier to replace a filehandle with some other object.
| [reply] [d/l] [select] |
|
Change your arrows to dots and that's almost exactly how it looks in Perl 6.
| [reply] |
|
See Fatal, which does exactly that, override open (or whatever else you want) to die if it fails. The scheme falls down for system, as system returns a false value on success ...
| [reply] |
|
| [reply] [d/l] [select] |
|
I'm actually considering using IO::All - now that is an almost rediculously convenient module.
| [reply] |
|
Re: Perl oddities
by TimToady (Parson) on Mar 01, 2005 at 18:18 UTC
|
This is a great thread, if only because it lets me point out that most of this stuff is fixed in Perl 6. :-)
It's going to take me a while, but I think it would be valuable if I responded to most of these. First, the OP...
The behavior of -M, -A, and -C is intentionally differentiated from the bare values returned by stat(), so that's probably not going to change.
The mkdir problem will be solved by making the mode an optional named parameter that goes before the list of directories if you do specify it.
And finally, print FH @list is illegal several ways in Perl 6. First, there are no bareword filehandles in Perl 6--they're just regular variables. Second, indirect objects are no longer differentiated by the absence of a comma, but by the insertion of a colon. (The reason it doesn't work with comma in Perl 5 is that print wouldn't know whether it's supposed to treat its first arg as an object to print to or a value to be printed to STDOUT.)
| [reply] [d/l] [select] |
|
| [reply] |
|
Sure, but we're trying to pick a more useful set of oddities. And nobody's paying me enough to remove all the oddities. :-)
| [reply] [d/l] |
Re: Perl oddities
by BrowserUk (Patriarch) on Mar 01, 2005 at 11:34 UTC
|
The -M, -A, and -C file test operators return the file modification, access, and creation times in days since the start of the program. Why? Why why why? Does anyone actually use the values for anything other than to compare them to each other?
The relativity of the dates produced by -M, -C and -A are useful for things like "delete all *.tmp files more than 5 days old" etc.
For example, this lists all the .pl file in the current directory that have been modified in the last 24 hours.
perl -le "-M() < 1 and print for map glob, @ARGV" *.pl
435230.pl
junk.pl
junk2.pl
junk3.pl
My least favorite oddity is the need to use /g option on a regex in order for pos to be set.
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.
| [reply] [d/l] |
|
My vote for weirdest feature of Perl is reset.
dates produced by -M, -C and -A are useful for things like "delete all *.tmp files more than 5 days old" etc.
And for command line utilities you are making your decision
at the time of invocation, $^T, so that is the important time. These op's must have been
a grand convenience for find2perl.
I agree these are a strange and odd convenience feature but
given the early mission of Perl to be a better shell/awk/sed
I don't find it weird.
Be well,
rir
| [reply] [d/l] [select] |
|
reset will be demoted to a method on a package or hash object. It will no longer be a keyword. We can't get rid of the functionality entirely if we want to be able to translate Perl 5 to Perl 6 though. But it can definitely stand to be de-Huffmanized, or more accurately, Huffmanized to be longer. Funny how we associate Huffman with making easy things easier but not harder things harder...
| [reply] [d/l] |
|
and having it be relative to the start of the program (actually, $^T, which you can change to suit) saves having to call time() for each -M, -A, or -C (in addition to making the results equal for different files with the same timestamp).
| [reply] |
|
| [reply] [d/l] |
|
|
Re: Perl oddities (s/// doesn't DWIM in map)
by grinder (Bishop) on Mar 01, 2005 at 13:55 UTC
|
I still find myself being tripped up from time to time by the following, even though I should know better:
my @w= qw/ per coercer berserker / ;
print "$_\n" for map { s/er/aler/g } @w;
The above produces the output "1 2 3". To make it DWIM, one must say:
my @w = qw/ per coercer berserker / ;
print "$_\n" for map { s/er/aler/g; $_ } @w;
I've always found that odd. (Yes, I know why it works that way).
- another intruder with the mooring in the heart of the Perl
| [reply] [d/l] [select] |
|
This can be solved much more generically in Perl 6 with mutator methods and topics:
print "$_\n" for map { .=subst(/er/, 'aler', :global) } @w;
But what you're really asking for is something other than map here, I think... | [reply] [d/l] [select] |
|
Good point. More generic: Having no built-in s/// that returns a modified copy is annoying.
| [reply] |
|
| [reply] [d/l] [select] |
|
|
|
A related oddity is that map can modify its input, in addition to generating output. That leads to the pitfall of
my @new = map { s/foo/bar/; $_ } @old;
# @old is modified along with @new!
# should be my @new = map { s/foo/bar/; $_ } map {$_} @old;
If map couldn't modify its input, the whole "map in a void context" debate might never have happened. for would be used for modifying input, map would be used for generating new output. Of course, it's a tradeoff, giving up some liberty for safety.
Caution: Contents may have been coded under pressure.
| [reply] [d/l] [select] |
|
my @new = map { local $_ = $_; s/foo/bar/; $_ } @old; also avoids the problem. Probably faster than using two maps, too. Still ugly, unfortunately.
| [reply] [d/l] [select] |
|
s/foo/bar/ for my @new = @old;
Makeshifts last the longest. | [reply] [d/l] |
|
I understand that you were just giving an example, but it looks like gratuitous chaining to me. Why not just
for (@w) {
s/er/aler/g;
print "$_\n";
}
You might also be interested in Algorithm::Loops 'filter'.
Caution: Contents may have been coded under pressure.
| [reply] [d/l] |
|
Because that might be part of a much larger chain.
Additionally, what's gratuitous in one set of eyes is natural in another's. For example, I find Java to be a gratuitous (mis)use of classes, but others, like Smalltalkers, find it to be gratuitously procedural. :-)
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
Re: Perl oddities
by hv (Prior) on Mar 01, 2005 at 12:46 UTC
|
I find the behaviour of int() odd: I want it to be like floor(), since then I can easily make ceil() and other useful functions for myself without loading the expensive POSIX module:
sub ceil { -int(-shift) }
I've never been able to see a good reason for the existing "truncate towards zero" behaviour.
Hugo | [reply] [d/l] [select] |
|
sub ceil {
my $n = shift;
int($n) + ($n > int($n));
}
sub floor {
my $n = shift;
int($n) - ($n < int($n));
}
Caution: Contents may have been coded under pressure.
| [reply] [d/l] |
|
There's no promise in the docs that less than and greater than return 1 and 0. Just "true" and "false". It could return 37 for true, and undef for false.
| [reply] |
|
|
Re: Perl oddities
by dragonchild (Archbishop) on Mar 01, 2005 at 14:09 UTC
|
Disambiguation messes with me. Once you have found something wonky, you put a + somewhere and Perl gets what you mean. Why a plus-sign?? I'm not adding a left-squiggly to shift when I do
sub foo {
my $self = shift;
$self->{+shift} = 3;
return $self;
}
Also, while we're talking about prototypes, why do some internals prototype and others don't? Can't the prototype for vec() look at how many elements there are in the array before bitching at me? And, I have to override CORE::GLOBAL::vec to eliminate the prototype. Overriding CORE::vec, even in a BEGIN block, isn't good enough. (Can you tell I don't like Perl's prototypes in any form?)
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] [d/l] |
|
There are several things wrong there that are fixed in Perl 6. You won't need the plus because you'll disambiguate autoquotes differently, so that a shift in curlies is always a real shift. And plus is always numeric in Perl 6--it's not a no-op as it is in Perl 5. But mostly, methods just look
different. Your code might look more like this in Perl 6:
method foo ($self: $key) {
.{$key} = 3;
return $self;
}
As for vec, that interface is a total kludge. You'll be much happier with real bit arrays, I expect.
| [reply] [d/l] [select] |
|
| [reply] |
Re: Perl oddities
by trammell (Priest) on Mar 01, 2005 at 17:41 UTC
|
Unary - on strings always struck me as weird:
my $foo = '-bar';
print $foo;
print -$foo;
| [reply] [d/l] |
|
Yeah, I'm not sure anyone has ever used that feature. It snuck in there because certain linguists love to write their linguistic booleans as +feature and -feature, plus there was
some resonance with Tk's -foo syntax. But we're probably breaking that too in favor of something more natively Perlish.
| [reply] |
Re: Perl oddities
by Anonymous Monk on Mar 01, 2005 at 13:33 UTC
|
sub add ($$) {$_[0] + $_[1]}
my @arr = (3, 4);
print add(@arry);
It issues a warning and prints 2, not the 7 I'd expect.
Perl doesn't DWIM in:
sleep 2.5;
You can tie some magical variables, and get the expected effects, but with other magical variables, no subroutines tied to them are ever called.
$ perl -wle 'print+(localtime())[5]'
105
C all over again.
brian, are you going to collect the results here, and give them to Larry before Perl6 comes out? ;-) | [reply] [d/l] [select] |
|
Perl 6's flattening rules are completely revised so that hashes and arrays don't actually have to care whether they're in scalar or list context until they're bound to parameters. Nevertheless, what you're saying there still won't work. If you want to treat an array as a list of parameters where Perl 6 is expecting a scalar, you have to use an explicit unary * to tell it that's what you want.
Fractional seconds weren't supported by most versions of Unix when Perl was invented, but that has changed for the better over the years. In Perl 6 most times will be represented in floating-point seconds, so a fractional sleep should do what you expect.
Tying and magic are done entirely differently in Perl 6 (through mixins and such), though you can never get entirely away from the fact that some semantics are going to hide other semantics unless you construct a class that specifically knows about both sets of inherited or composed semantics. However, it should work more like you expect, insofar as the latest layer of semantics should hide the built-in magic, and not vice versa.
As for localtime, it was always intended to be a thin interface over C. But Perl 6 will give an OO interface to most of the list-returning functions, and you'll get at the values with methods on the returned object. So we can fix the year+1900 problem at least for the method call.
I'm not brian, but I can probably pass these on to Larry before Perl 6 comes out... :-)
| [reply] [d/l] [select] |
|
Perl doesn't DWIM in:
sleep 2.5;
But see:
use Time::HiRes qw(sleep);
...
sleep 2.5;
You can't make core Perl do this, because the number of systems on which this worked was once miniscule compared to the number of systems on which it could never work.
| [reply] [d/l] [select] |
|
merlyn,
You can't make core Perl do this
To the letter of the law, that's true. In spirit though, select(undef, undef, undef, 2.5); is usually close enough. It would be nice if you didn't have to use something so ugly with core Perl though.
| [reply] |
|
You can't make core Perl do this
Did I say we should change Perl to allow this? No. Do you understand the premises of this thread? brian was asking for what people consider oddities of Perl thinking. Now I'm sure any oddity has its reason for being odd (after all, it's there the way it is because someone put it there, and not because Larry has a piece of radioactive material next to his computer and he's just watching how the rays mutate Perl) - but that's not the point.
I expect Perl to DWIM (just like it does in many other things), and if on my system select undef, undef, undef, 2.5 waits for about 2500 milliseconds, then there's no reason to assume sleep 2.5 can't.
| [reply] |
|
Just avoid prototypes and you will be happier. 99.9% of the time they aren't needed and often they hurt, like in this case.
| [reply] |
|
sleep 2.5;
works if you
use Time::HiRes qw/sleep/;
The alternative
select(undef, undef, undef, 2.5);
looks too much like a hack and isn't very clear.
/J
Update: I can't believe I didn't scroll down to see the existing answers to this question :)
| [reply] [d/l] [select] |
Re: Perl oddities
by Anonymous Monk on Mar 01, 2005 at 13:23 UTC
|
Perl has sin and cos, but no tan. I know you can make your own tan function, but that's not the point. It's not convenient (hence, unPerlish) for the programmer to make his/her own (or load a module to do so). Besides, calling sub in Perl is expensive. Even many calculators have a button for the tan function. | [reply] [d/l] [select] |
|
| [reply] |
|
sin, cos, and atan2 are "primitive" functions.
Well, once you have a routine for sin, then cos is the same thing, but pi/2 sooner. And I'm fairly sure that's the way it's implemented in the libraries.
Using atan2 to do an inverse sin or cos is a bit of a walk in the park, but essentially I guess you have to find the 'Y' value once you have the 'X', then submit both to atan2, and that will give you the angle you're looking for.
That's a nice brain exercise right after lunch.
Alex / talexb / Toronto
"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds
| [reply] [d/l] [select] |
|
|
I know. But you can do away with either sin or cos as well - they are the same primitive, just shifted a quarter of a phase. That of course doesn't mean tan couldn't be present. After all, Perl gives us
push, pop, shift and unshift, when they can all be trivially implemented using splice. Perl is a rich language, and any minimal approach is, to quote brian, what I consider exceptions to normal Perl thinking. Normal Perl thinking is "programmer convenience". A minimalistic approach isn't programmer convenience.
| [reply] |
|
|
|
|
| [reply] [d/l] [select] |
|
And the reason for this (that so far as I can tell no one has yet said) is simple: those functions are defined for all values of their argument. tan isn't. arcsin and arccos aren't.
Well, division isn't defined for all values of its arguments either, and neither are log and sqrt. So, I agree it's not much of a reason at all.
| [reply] |
Re: Perl oddities
by hardburn (Abbot) on Mar 01, 2005 at 14:27 UTC
|
$ perl -e 'map { $_ }, qw/foo bar/'
syntax error at -e line 1, near "},"
Execution of -e aborted due to compilation errors.
I'm fine with it not being required, but it shouldn't yell at you if you happen to include it.
"There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.
| [reply] [d/l] |
|
The comma after the block is optional in Perl 6. On the other hand, you have to use a block there. The expression form is not supported in Perl 6. Or more precisely, the first arguments will be expected to be an expression that returns a closure to be executed.
| [reply] |
|
And if you're trying to map your inputs into hashrefs with a comma, you can't. :-/
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
|
Sure you can, but you need the dreaded +:
print map +{$_}, qw/foo bar/
| [reply] [d/l] |
|
|
|
Re: Perl oddities
by sh1tn (Priest) on Mar 01, 2005 at 23:35 UTC
|
Oddity ... I think there is one – Perl made me love programming!
| [reply] |
|
I don't think we've quite got around to fixing that one in Perl 6 yet, but we're working on it. :-)
| [reply] [d/l] |
Re: Perl oddities
by bluto (Curate) on Mar 01, 2005 at 16:46 UTC
|
print FH @list
Normally this doesn't bother me unless I have to use parens (due to a parsing or emacs alignment issue)...
print(FH <list>);
... looks even worse.
The other thing I think is odd is how split() removes null fields at the end of a line if you don't give a LIMIT argument. Normally when I process a delimited file I expect each line to have the same number of fields, though some may be empty. For short scripts I tend to write quick sanity checks like this...
my @values = split /:/, $line;
die "invalid line: '$line'" unless @values == 7;
It looks nice, but I have to remember to go back and set LIMIT to a negative (or large) number.
| [reply] [d/l] [select] |
|
In Perl 6 it's probably one of
print($fh: @list);
$fh.print(@list);
instead, or maybe you'll use pipes:
@list ==> $fh.print;
$fh.print <== @list;
As for split, we haven't decided yet whether to change the default. I can argue it both ways. | [reply] [d/l] [select] |
|
open $hash{foo}, ">", "foobar";
print { $hash{foo} } "Test\n";
Makes me shudder every time. | [reply] [d/l] |
|
I do it this way:
print FH ('test', 'ing', 1, 2, 3);
Actually, I lied. I simply don't use barewords filehandles.
| [reply] [d/l] |
Re: Perl oddities
by bart (Canon) on Mar 01, 2005 at 22:40 UTC
|
First of all, I'd like open and opendir to have returned an open handle, or undef on failure, instead of changing a passed argument on the side. But Joost already mentioned that.
And second, I find it not just odd but also extremely annoying how the -X operators ignore parens as a hint for parsing precedence. Take this example:
print -M($0) + 1;
This yields:
Argument "test.pl" isn't numeric in addition (+) at test.pl line 2.
Use of uninitialized value in print at test.pl line 2.
Perl treats this the same as
print -M ($0 + 1);
Not exactly what I had in mind. You have to wrap the parens around both operator and argument, to make it behave like I want. Just like Applescript.
print +(-M $0)+1;
| [reply] [d/l] [select] |
Re: Perl oddities
by YuckFoo (Abbot) on Mar 01, 2005 at 18:53 UTC
|
It is odd that regex capture variables are not put in an array somewhere and I have to explicitly list them:
# too much work...
my ($this, $that, $some, $other) = ($1, $2, $3, $4);
# would rather:
my ($this, $that, $some, $other) = @_;
YuckFoo | [reply] [d/l] |
|
| [reply] [d/l] [select] |
|
Often you can just assign the results of the match. Make sure you are in list context if you have only one capture.
my ($this, $that, $some, $other) = /(this)(that).*(some)....(other)$/;
my ($cap) = /hello(there)/; # OK
my $cap = /hello(there)/; # BUG
| [reply] [d/l] |
|
| [reply] |
|
I generally do as gaal suggests. However, if this were impossible, and if you had a long list of regex capture variables, you could always do:
my ( $this, $that, $some, $other, $foo, $bar, $baz ) = ( $1 .. $+ );
dave
| [reply] [d/l] |
|
I am aware of the method suggested by gaal. I usually do not use it because I almost always wrap the regex up with an 'if'. Throw in a my function and it starts to get messy.
# Ugly to me...
if (my ($this, $that, $some, $other) = $line =~ /(this).*(that).*(some
+).*(other)/) {
do_it();
};
# Better, I think...
if ($line =~ /(this).*(that).*(some).*(other)/) {
my ($this, $that, $some, $other) = ($1, $2, $3, $4);
do_it();
}
This business doesn't DWYM:
my ( $this, $that, $some, $other, $foo, $bar, $baz ) = ( $1 .. $+ );
The magical string incrementer is summoned to build a list of strings starting with the first capture, ending with the last.
YuckFoo | [reply] [d/l] [select] |
|
|
#!/usr/bin/perl
use strict;
use warnings;
$_ = "this that some other foo bar baz";
if (/(this)\s*(that)\s*(some)\s*(other)\s*(foo)\s*(bar)\s*(baz)/) {
my ($this, $that, $some, $other, $foo, $bar, $baz) = ($1 .. $+);
print "$this, $that, $some, $other, $foo, $bar, $baz\n";
}
__END__
Use of uninitialized value in concatenation (.) or string at
Use of uninitialized value in concatenation (.) or string at
Use of uninitialized value in concatenation (.) or string at
Use of uninitialized value in concatenation (.) or string at
Use of uninitialized value in concatenation (.) or string at
Use of uninitialized value in concatenation (.) or string at
Use of uninitialized value in concatenation (.) or string at
, , , , , ,
What does work is:
#!/usr/bin/perl
use strict;
use warnings;
$_ = "this that some other foo bar baz";
if (/(this)\s*(that)\s*(some)\s*(other)\s*(foo)\s*(bar)\s*(baz)/) {
my ($this, $that, $some, $other, $foo, $bar, $baz) =
map {;no strict 'refs'; $$_} 1 .. $#-;
print "$this, $that, $some, $other, $foo, $bar, $baz\n";
}
__END__
this, that, some, other, foo, bar, baz
A trick I've been using for quite a long time. ($#+ instead of $#- works as well). | [reply] [d/l] [select] |
Re: Perl oddities
by ikegami (Patriarch) on Mar 02, 2005 at 06:49 UTC
|
What's with the 1; at the end of every module. Are there any modules that don't return true? Couldn't they just die instead? | [reply] [d/l] [select] |
|
Modules should be made to return their name (or Class maybe if that is a type.)
| [reply] [d/l] |
Re: Perl oddities
by PreferredUserName (Pilgrim) on Mar 01, 2005 at 15:09 UTC
|
I've always been annoyed that you can't say:
if ($condition)
do_something();
The lame "Perl is saving you from nested elses"
rationale for this doesn't wash. Since when is
Perl a bondage and discipline language?
I often have written:
do_something() if $condition;
, which is less clear to me, to avoid taking
up four lines of screen/brain space with:
if ($condition)
{
do_something();
}
| [reply] [d/l] [select] |
|
Actually, I think C made the wrong choice here. It's not the braces that are being redundant, but the parentheses!
The parens are there only to avoid syntactic ambiguity if the following statement isn't a block. So the parens are what Perl 6 lets you get rid of:
if $condition { do_something() }
In fact, the braces are much more important in Perl 6 because they almost always indicate a closure, or at least a potential closure. That's important because the braces indicate delayed evaluation. A closure is treated as an argument to the control construct, so you could also write the above
as:
statement:<if>($condition, { do_something() });
But the converse is also true, that if you define your
own statement:<foo> with the same signature,
you can call it as:
foo $condition { do_something() }
just as if it were a built-in control construct. To do this in Perl 5 requires chewing gum and bailing wire, plus assorted smoke and mirrors.
| [reply] [d/l] [select] |
|
I'm not going to argue the logic of this. Being able to create a brand new language without making my jaw tired, running out of wire and having to go back to the store to get more, and in a non-smoking city ... that is great.
The fact is that most of the more popular languages use those parens. Whether your history is C/C++, Java, Perl5, or others which I've probably forgotten (I don't remember enough Pascal or Fortran to print out "hello world" - whether they do or not, I can't recall, but I'm not sure they quite qualify among the more popular languages, at least not from the perspective of those who would use Perl6), you're used to it. While it may not be intuitively natural for a human being to put parens around their conditional, it has been trained into a large majority of programmers to do it, even if that is against our nature.
Sometimes, bad choices are propogated to get over the inertia of the results of those choices. Rather than spending time retraining in the revolutionary new pattern of behaviour (I'd use the word "paradigm", but I think that word has lost all meaning), we stick to the tried-and-true-more-or-less. It helps languages, such as Java or C#, take off, because there is less retraining involved.
The trade-off here is that this may indeed be a revolution in language design. But it will delay the adoption of Perl6 (I think I've read something in the Apocalypses where this has been conceded already), possibly (although hopefully not) to the point where it just cannot acheive critical mass.
Another problem is for those of us who have to deal with multiple languages. I'm doing mostly perl5 right now, but I am still responsible for some C++ code (a couple KLOC), some shell scripts (probably about a dozen KLOC - ugh!), and have input into some Java code design issues. Yet another pattern will mess me up for a while - I can imagine that a number of people will just be too busy to pick up another language, especially one that has not (yet) hit critical mass, making it just a bit more difficult to acheive that critical mass. I'm not sure if I'll fall into this group or not yet.
I'm not saying that perl6 in general (or making parens optional in specific) is a bad idea. Someone has to come up with the revolutions every once in a while if we're ever going to get to that AI which just does what we ask it, without having to do all the drudgery of actually coding. It's just a risk. Whether good or bad, only time will tell.
Perl6 has, from what little I've read, so many time savers here and there - taken one at a time, most are pretty minor. Taken all together, it's pretty daunting. In some ways, renaming it away from "perl" may have been a good idea, so that no one thinks about it like perl. ;-) I think that perl6 shares less in common with perl5 than C++ shares with C ;-)
| [reply] |
|
|
|
|
|
|
if ($condition) {
do_something();
}
A couple of things:
1. I've found that the braceless if can slow me down when reading C code. I have to remember that the next command is the thing that's done.
2. Cuddling the braces around their control statements saves a lot of whitespace without much loss of readability. Consider the following extension of my suggestion above:
if ($condition) {
do_something();
} else {
if ($another_condition) {
do_something_else();
} else {
do_yet_a_third_thing();
}
}
Just my $0.02
----
My mission: To boldy split infinitives that have never been split before!
| [reply] [d/l] [select] |
|
Which is more important - do_something() or $condition? The important bit should be left-most in indentation. I have often found
if (really_long_and_boring_condition)
do_something_useful()
to be much harder to read in C. Plus, people seem to feel that just cause you don't have braces means you don't have to follow proper indentation practices. (Not that braces always help, but it allows me to bounce on % in (g)vi(m).)
Personally, I prefer the following alternatives:
do_something_useful()
if really_long_and_boring_condition;
# Or ...
really_long_and_boring_condition
&& do_something_useful();
Depending on which is more important to understanding the program's flow.
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] [d/l] [select] |
|
I would argue that if the condition is "really long and boring", then it is *more* important to have braces and whitespace so it is easier to see where the actual action being taken is at a glance. The only one you mention that could work for me is:
do_something_useful()
if really_long_and_boring_condition;
Unfortunately, that's at the expense of putting the cart before the horse IMHO. The action doesn't matter if the condition is not satisfied.
----
My mission: To boldy split infinitives that have never been split before!
| [reply] [d/l] |
|
|
| [reply] [d/l] |
Re: Perl oddities
by dragonchild (Archbishop) on Mar 01, 2005 at 17:27 UTC
|
It's also kind of odd when your filehandle is not a simple scalar or bareword:
That's something that also bugs me - why is a filehandle a bareword, but every other bareword gets smacked down by strict?
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
|
Don't forget that labels escape strictures too. If Perl can tell what it is, strict doesn't care. With filehandles it knows by position. With labels, it's the colon. You can forward define subs too, and get away with it.
--
brian d foy <bdfoy@cpan.org>
| [reply] |
|
Perl 6 has no barewords at all. If Perl 6 can't tell what it is from context, it's an error. Classes must be predeclared or use the :: prefix, for instance. They aren't just bareword strings anymore.
| [reply] [d/l] |
Re: Perl oddities
by Anonymous Monk on Mar 01, 2005 at 21:28 UTC
|
$::foo refers to the global variable called foo in the main package, not in the current package.
This works out the same for package main, but it just doesn't DWIM for other packages. The first three times I read through the documentation, I assumed it was just refering to this similarity: clearly, the writers of the Perl parser could tell what package they were in, so they could expand $::foo appropriately. After all, they need to figure out packages for function calls. Instead, it means the same as $main::foo, something that a simple regexp could do for me, if I wanted it to.
Since I thought the point of the package notation was to let the globals stand out with the double colon sigil syntax, I was disappointed to learn that I'd have to hard-code the package name in multiple places: first, in the the package, and second, for all the global variables within that package.
"our" variables solve the hard-coded package name issue, but don't have a special sigil to make them stand out as globals anymore...*sigh*
--
Ytrew | [reply] |
|
In Perl 6, :: behaves more like you expect, and is no longer automatically associated with either package main or any other top-level package. Class names are searched for starting in the current package, so
$::foo would be a variable in the current package if declared there.
| [reply] [d/l] [select] |
|
| [reply] |
Re: Perl oddities
by BrowserUk (Patriarch) on Mar 02, 2005 at 08:41 UTC
|
My other "love to hate" oddity of Perl 5 is lvalue subs. To quote me:
As they are, the only thing that can be done with the assigned value is ... well, to assign it to something. Sure, you can decide what to assign it to using the values past via the normal @_ mechanism to make the determination, but there is absolutely no way to inspect the value of the assign value either before you assign it nor after is was assigned. That means it is impossible to perform any verification on the assigned value. This may work for things like substr and splice, that simply don't care what is assigned, but it makes using lvaue subs for any other purpose pretty much useless. I note that vec can and does inspect the value assigned in that it will reject non-numerical assignments as it has to process them in order to use them. This is exactly the facility I would like to use.
I'd really like to see lvalue subs made useful:(
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.
| [reply] |
|
lvalue subs will be useful, but only with a lot of ugly syntax. I hope that macros and attributes will be powerful enough to fix this, and suspect that they will be, though it still jars me that I'll need to depend on the module that has the macros in it.
Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).
| [reply] |
Re: Perl oddities
by ikegami (Patriarch) on Mar 01, 2005 at 20:47 UTC
|
print FH @list is not unique. It's called the "indirect object" method invocation syntax. The example in perlobj is new Critter ('Barney', 1.5, 70). True, FH is not (necessarily) an object here, but it behaves just like one.
| [reply] [d/l] [select] |
|
I had never really thought of it like that: maybe because we teach it in the second day of Learning Perl and I don't talk about objects and such then. This has also been around a bit longer than
Too bad this doesn't seem to work.
#!/usr/bin/perl
STDOUT->print( "Hello World!\n" );
I get this error:
Can't locate object method "print" via package "IO::Handle" at io.pl l
+ine 3.
If I change it slightly, though, I get the expected output. I'm surprised I didn't get the "perhaps you forgot to load ..." message that usually comes with this sort of error.
#!/usr/bin/perl
use IO::Handle;
STDOUT->print( "Hello World!\n" );
--
brian d foy <bdfoy@cpan.org>
| [reply] [d/l] [select] |
|
>perl -e "bless({}, 'Cow')->moo();"
Can't locate object method "moo" via package "Cow" (perhaps you forgot
+ to load "Cow"?) at -e line 1.
>perl -e "STDOUT->print();"
Can't locate object method "print" via package "IO::Handle" (perhaps y
+ou forgot to load "IO::Handle"?) at -e line 1.
>perl -v
This is perl, v5.6.1 built for MSWin32-x86-multi-thread
(with 1 registered patch, see perl -V for more detail)
Copyright 1987-2001, Larry Wall
Binary build 633 provided by ActiveState Corp. http://www.ActiveState.
+com
Built 21:33:05 Jun 17 2002
| [reply] [d/l] |
Re: Perl oddities
by PhilHibbs (Hermit) on Mar 21, 2005 at 13:46 UTC
|
I thought that ctime was the change time of the inode, rather than creation time. chmod a file and see it change. | [reply] |
|
You're correct. You'll even see this referenced in perldoc -f -C.
thor
Feel the white light, the light within
Be your own disciple, fan the sparks of will
For all of us waiting, your kingdom will come
| [reply] |
Re: Perl oddities
by marinersk (Priest) on Mar 01, 2005 at 22:44 UTC
|
File timestamp relative to start of program is also useful when writing file utilities; on some operating systems you can actually get a filename twice, once before you modified it and once after -- checking its timestamp relative to program start eliminates the need to track which files you've already processed.
| [reply] |
Re: Perl oddities
by blazar (Canon) on Mar 02, 2005 at 10:18 UTC
|
print FH @list
You don't put a comma between the filehandle name and the list you give to print. I've just always thought that was odd, and I go out of my way to point it out to people in Perl classes. I don't have a problem with this while I code, but I still think it's an odd corner of syntax.
Well, it's more of a coincidence than a real fact, but that looks much like indirect object dereferentiation, a la
FH->print(@list)
and (BTW) it won't be a coincidence any more in Perl6... | [reply] [d/l] |
Re: Perl oddities
by Limbic~Region (Chancellor) on Mar 02, 2005 at 19:22 UTC
|
brian_d_foy,
I find the way Perl handles mixed tied interfaces odd.
use Tie::Hash::Sorted;
tie my %s_hash, 'Tie::Hash::Sorted';
print tied( %sorted_data )->Count, "\n";
The alternative is to split the functionality into two pieces.
my $s_href = tie my %s_hash, 'Tie::Hash::Sorted';
print "$_\n" for keys %s_hash;
print $s_href->Count, "\n";
| [reply] [d/l] [select] |
Re: Perl oddities
by Anonymous Monk on Mar 02, 2005 at 00:59 UTC
|
While I agree with your observations about the odities of -M, -A, and -C, print FH @list makes perfect sense to me. If one was to put a comma between the two, I would expect the filehandle and list to be printed (ie. the glob and the list); especially with the possibility of Filehandles now being assigned to variables ( open my $fh => ''), I'd find it counterintuitive to see perl differentiate between:
print $fh,@list;
# ref($fh) = GLOB
and
print $fh,@list
That'd be some cooky DWIMery, considering, then, that _if_ we wanted to print something like GLOB<0x...>, we'd have to do this: print "$fh",@list, which would function in a significantly different manner than print $fh,@list. Thus, to me it's a perfectly rational and well thought out syntax.
I still prefer, however, $fh->print();. In addition, the workaround to this oddity would be to force the explicit declaring of the filehandle to write to, or the like. | [reply] [d/l] [select] |
Re: Perl oddities
by mattk (Pilgrim) on Mar 04, 2005 at 19:01 UTC
|
I'd like to know why POSIX.pm doesn't include an interface to strptime(3). Time::Piece has it, but it's broken (you can't get proper epoch values out of it when you use it as your constructor). I'm looking forward to Perl6's OO-based time functions already. | [reply] |
Re: Perl oddities
by fraktalisman (Hermit) on Mar 05, 2005 at 13:30 UTC
|
Looking at TimToady's answers, this thread looks a bit like a Perl 6 wishlist. And a chance to get a better idea of what Perl 6 is going to be like, without following the developers' discussions about it.
But I don't think Perl will stop to have oddities, just because it has so many influences (or compatibilities?) of other languages and tools.
| [reply] |
|
I'm a little disappointed in all the comments about perl6. This thread could have been a nice discussion providing insights into how people think, and all the noise about "But we've fixed that in perl6 and boy will it be neat!" is getting irritating.
| [reply] |
|
I'll disagree. I think that this list of oddities is a perfect place to vent, to reflect on where we are, how we got here, and, just as importantly, if not moreso, where we are going. Many of these oddities seem to have been made into RFCs for perl 6 - which is why perl 6 seems to solve so many of them. But, don't worry, a year or two after perl 6 comes out, we can have this thread all over again with perl 6's own oddities, as brian_d_foy points out ;-}
(I'm not disagreeing with it "getting irritating" - that's your feelings, and you're entitled to them. Just disagreeing with the implication that this is not a nice discussion providing insights into how people think, which I think it has done, and more: whether those oddities will be addressed or not in future versions of perl.)
| [reply] |
|
|
|
Re: Perl oddities
by Dedalus (Scribe) on Mar 01, 2005 at 21:37 UTC
|
pipe A=>B
does rather the opposite to what it looks like it should. | [reply] [d/l] |
|
So does push(@a => $b);. Why are you using => instead of ,?
By the way, your code is equivalent to pipe('A', B); and not pipe(A, B).
| [reply] [d/l] [select] |
|
Why should not I? It is perfectly valid, and would seem to make visual sense, pipe one thing into an other. Arrows are pretty, but not DWIM, it is a shame.
| [reply] |
|
| [reply] [d/l] |
substr oddity
by Ytrew (Pilgrim) on Mar 04, 2005 at 05:14 UTC
|
I'm not sure if this one counts as an oddity, or a bug.
I think it's defined behaviour, but I'm not sure.
substr() is implemented as an Lvalue subroutine, and it's a fatal error when assigned to incorrectly. I think means that when substr() is passed as a parameter, it gets treated like an Lvalue, since it can be assigned back to by modifying @_.
This code crashes on the subroutine call:
use strict;
use warnings;
my $x="";
foo( substr($x,2,1) ); # crashes here
print "Alive!\n"; # not reached
sub foo {}
This code doesn't:
use strict;
use warnings;
my $x="";
my $y=substr($x,2,1); # warns, doesn't crash
foo($y); # no-op
print "Alive\n"; # we get here just fine
sub foo {}
I maintain that this is an odd behaviour, one way or the other. My hunch is that it counts as an "oddity" as opposed to a "bug": can the experts confirm or deny this?
--
Ytrew | [reply] [d/l] [select] |
|
P:\test>perl -wle"sub foo{}; my $s =''; foo( substr $s, 2, 1 );"
substr outside of string at -e line 1.
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.
| [reply] [d/l] |
|
This doesn't seem to happen on Win32 5.8.4 (AS 810). Which version are you using?
Well, I'm running version "5.8.6 built for PA-RISC2.0-thread-multi-LP64", running on HP/UX. I also get the same behaviour for 5.6.1.
But your snippet doesn't actually demonstrate the problem: you get the warning message, but can't actually detect whether the code crashed. Here's what I get when I add a trace statement after the call to substr().
$ perl -wle 'sub foo{}; my $s=""; foo( substr($s,2,1) );print "Not rea
+ched\n"'
substr outside of string at -e line 1.
$
Note that "not reached" is never reached, and is not printed, because the code crashes on the substr() call.
--
Ytrew | [reply] [d/l] |
|
|
|