Don't write this:
my @folk = ("Hibbs",
"Daglish",
"Schwartz",
"Vroom");
Write this:my @folk = (); push (@folk, "Hibbs"); push (@folk, "Daglish"); push (@folk, "Schwartz"); push (@folk, "Vroom");Why? It's easier to maintain. You can insert or remove any single line easily, at the beginning, middle, or end. You can remove all the hard-coded lines, or move them to a later point (inside a loop, maybe).
The down-side is that the array name has to be repeated on each line, and there is probably a slight performance penalty.
Now you're going to show me something that uses "qw", aren't you? OK, go ahead, but don't forget to show me how it looks when an entry contains spaces.
I don't like the push way of constructing arrays. I use the following idioms:
my @array = ( "Hibbs", "Daglish", "Schwartz", "Vroom", );
... which works well for adding in any place, and also (un)commenting entries. If I'm sure there are no newlines/whitespace-only elements in the array needed, I also may use the following:
my @array = grep { /\S/ } split /\n/, '
foo
bar baz
and so on
';
depending on how my input data gets delivered (multi-column Excel data fits better into this model for example).
my @array = ( "Hibbs", "Daglish", "Schwartz", "Vroom", );
I agree. And the little thing that makes this really work well is training oneself to add that trailing comma (after "Vroom") to the last entry. (Ditto for hashes entries, too.)
-xdg
Code written by xdg and posted on PerlMonks is [http://creativecommons.org/licenses/publicdomain|public domain]. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.
Now to get back some of that lost XP by upvoting the helpful replies...
ah, I like being a Friar anyway, it goes with my T-shirt.
You may have an optional comma before the closing parenthesis of a list literalIn fact, you can have extra commas anywhere you want in a list except (for reasons I can't explain) at the very front of it. They will not cause undef items to be created, nor will including nested empty lists.
my @items = ((),,,,5); print "<$_>\n" for @items; # prints only one item
Actually it does work in C, and that's most likely where perl picked up the habit too. One reason it's very useful is when you're generating code with macros, it's much easier to append commas to things than to insert them between things.
--
integral, resident of freenode's #perl
No, it does not.
$ cat > a.c int a[] = (1,2,3,); $ gcc -c a.c a.c:1: error: syntax error before ')' token
Not even in C++
$ cat > a.cpp int a[] = (1,2,3,); $ gcc -c a.cpp a.cpp:1: error: expected primary-expression before ')' token
It helps to remember that in C you need to use {} as brackets around a compound initialiser (something which is different from perl, where , has taken on a much greater role).
thaum:/tmp bsmith$ cat >a.c
int a[] = { 1, 2, 3, };
thaum:/tmp bsmith$ gcc -c a.c
thaum:/tmp bsmith$
--
integral, resident of freenode's #perl
I don't like the push way of constructing arrays.You think that's bad, I once had to maintain a program that did this:
my @array; $array[$#array] = "Hibbs"; $array[$#array] = "Daglish"; $array[$#array] = "Schwartz"; $array[$#array] = "Vroom"; ...And so on for about 30 lines.
One of the few times I felt justified in regexing some code.
$array[@array] = "Hibbs";or
$array[++$#array] = "Hibbs";?
I use the former idiom as well, but I've run across this style a couple of times, too:
my @array = ( 'Hibbs' ,'Daglish' ,'Schwartz' ,'Vroom' );
The one time I had the chance to actually ask a coder about that style, he gave me two rationales. First, he liked it because of a string-cat convention that's similar:
my $string = 'this is a very long string that has a certain number ' .$number .' of segments.' ."\n";
In print statements, this coder often mirrored that convention using commas instead of periods to pass the list of strings to [doc://print]. (This is apparently faster, though it smacks of premature optimization to me. But I digress.)
The second reason was that he found the trailing comma to be confusing; by moving commas to the front, he provided a visual reminder to put the comma in when adding to the list but without the "confusing" trailing comma. To each their own, I guess.
Anyone have thoughts on this style? Just curious as to what advantages/disadvantages there might be.
That doesn't really help here since you can't insert at the top safely.
The style has been called [http://perl.4pro.net/pcs.html|The Perlish Coding Style]. Accoding to that document, the following would be the proper alignment:
{ my @array = ( 'Hibbs'
, 'Daglish'
, 'Schwartz'
, 'Vroom' )
; my $string = 'this is a very long string that has a certain number '
. $number
. ' of segments.'
. "\n"
}
Personally I don't see any evident maintainability that initialization-by-[doc://push]es buys me over the "standard" one that any decent text editor couldn't give me just as easily. The only "problem", if you really, really want to call it a problem, may have to do with the first and last entry. If you're really, really that concerned about the few extra keystrokes these may involve, then you how 'bout
my @folk = (
"Hibbs",
"Daglish",
"Schwartz",
"Vroom"
);
instead?
my @folk = qw(Hibbs Daglish Schwartz Vroom),
"Node Reaper";
my @folk = map {s/_/ /g; $_}
qw(Hibbs Daglish Schwartz Vroom
Node_Reaper);
Neither work. Second one has the dreaded can't modify read only string error. Which is a good example of the issues the OP was making I guess. Sigh, i should know better for both of these too. :-(
I will quibble with the "grasping at straws" comment tho. I think this approach often is just fine for dealing with spaces in a qw() string.
Right, I can see your point. I think for me it would come down to a matter of whether run time issues are more important than development time issues. Generally I'd say that development time is more important so I'd probably go with whatever saved me the most work.
use YAML qw( Load );
my @folk = @{ Load( <
my @folk = ();
push (@folk,
"H".
"i".
"b".
"b".
"s"
);
push (@folk,
"D".
"a".
"g".
"l".
"i".
"s".
"h"
);
...etc. Of course that's also problematic if you want to edit an individual letter. So I find the style below a bit better (especially when using a modern editor like edlin). Plus it uses a more descriptive name than the bland "@folk"...
push (@Hibbs_Daglish_Schwartz_Vroom,
chr(0b1001000).
chr(0b1101001).
chr(0b1100010).
chr(0b1100010).
chr(0b1110011)
);
push (@Hibbs_Daglish_Schwartz_Vroom,
chr(0b1000100).
chr(0b1100001).
chr(0b1100111).
chr(0b1101100).
chr(0b1101001).
chr(0b1110011).
chr(0b1101000)
);
push (@Hibbs_Daglish_Schwartz_Vroom,
chr(0b1010011).
chr(0b1100011).
chr(0b1101000).
chr(0b1110111).
chr(0b1100001).
chr(0b1110010).
chr(0b1110100).
chr(0b1111010)
);
push (@Hibbs_Daglish_Schwartz_Vroom,
chr(0b1010110).
chr(0b1110010).
chr(0b1101111).
chr(0b1101111).
chr(0b1101101)
);
p\ u\ s\ h\ (\ @\ H\ i\ b\ b\ s\ _\ D\ a\ g\ l\ i\ s\ h\ _\ S\ c\ h\ w\ a\ r\ t\ z\ _\ V\ r\ o\ o\ m\ ,\ c\ h\ r\ (\ 0\ b\ 1\ 0\ 0\ 1\ 0\ 0\ 0\ )\ )\ ;\
That won't work. Perl is not C.
That won't work. Perl is not C.Perl is pretty close though. What part of Perl's syntax makes CPP choke (just curious)?
$ perl -P -MO=Deparse cpp.pl:1:2: warning: backslash-newline at end of file push @Hibbs_Daglish_Schwartz_Vroom, 'H'; cpp.pl syntax OK
That style of code is totally ugly and unusable. What if your original list of data erroneously switched two characters and you now have to swap the last and next-to-last character? This coding style is flawed in that aspect. You should use the following coding style instead:
push (@Hibbs_Daglish_Schwartz_Vroom, ""
. chr(0b1010110)
. chr(0b1110010)
. chr(0b1101111)
. chr(0b1101111)
. chr(0b1101101)
);
Actually I use this coding style when manipulating SQL SELECT statements:
SELECT monkey, bananas from my_table where 1 = 1 and flung_poo is null and size > 800 ;
That style of code is totally ugly and unusable [...] You should use the following coding style instead:
No, no, no! Yours is better than the previous alternatives but one may still get confused when swapping bits. And all those calls to [doc://chr], oh my! Now [doc://pack] can do all this for cheap. Thus you should use the following coding style instead:
push @Hibbs_Daglish_Schwartz_Vroom, pack qw/(B8)* 01010110 01110010 01101111 01101111 01101101 /;
Except that one would almost certainly want to write a specialized sub to do this, should he later change his mind with respect to the order in which to store bits into chars, chars into strings and strings into the array:
sub insert (\@@) {
my $arr=shift;
push @$arr, pack '(B8)*', @_;
}
# ...
insert @Hibbs_Daglish_Schwartz_Vroom,
qw/
01010110
01110010
01101111
01101111
01101101
/;
perlmonks.org content © perlmonks.org and ambrus, Anonymous Monk, blazar, bmann, Corion, demerphq, Fletch, friedo, ikegami, integral, japhy, PhilHibbs, radiantmatrix, Roy Johnson, xdg
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03