Ah, that changes things a fair bit. I was merely going by the behaviour you had originally - $4 eq 'play' doesn't return 'true' and 'false' but '1' and undef. One alternative is to use a function that converts, such as:
sub bool2str
{
shift ? 'true' : 'false'
}
Then you could use bool2str($control{play}) to get the strings you want. | [reply] [d/l] [select] |
I am not sure yet how to add an additional function to my module. I get the shift idea, tho the syntax is new.
Instead, could I just intialize the hash with a full list of options set to false, then set them true based on $4?
my %control = map { $_ => 'false' } split ' ', 'play ctrl loop'
my %control = map { $_ => 'true' } split ' ', $4;
| [reply] [d/l] |
You could try it before posting and get the answer to your own question ;-)
It won't work for a couple of reasons. First, my designates the creation of a lexical variable. You can't do that twice - you'll get two different variables. However, if you change that to:
my %control = map { $_ => 'false' } split ' ', 'play ctrl loop'
%control = map { $_ => 'true' } split ' ', $4;
it still won't work (although it will compile/run now). That's because you're assigning one hash to it (created via the first map), and then assigning a second hash to it, completely reinitialising the hash, losing all of the settings from the first time. Like many other things in perl, TMTOWTDI, though. First, I'll explain the logic.
The idea is that you want to set up everything to false, and then reset to true for anything you find. Or, another idea is to set up everything you find to true, and then set everything else to false. Let's try the first one.
my %control = map { $_ => 'false' } qw(play ctrl loop);
$control{$_} = 'true' for split ' ', $4;
Here we create the %control hash by using perl's built-in split-on-whitespace operator, qw. This is faster because it can do this split during compilation, rather than each time through the loop. (If it's only done once during your execution, it probably is not much faster, but is a good habit to be in.) Then, we split $4 on whitespace, and set that key in your %control hash to 'true' for each one. Alternately:
my %control = map { $_ => 'false' } qw(play ctrl loop);
%control = (%control, map { $_ => 'true' } split ' ', $4);
This one has the same initialisation. However, we use assignment to create a brand new hash, starting out with all the 'false' values, and then adding all the 'true' values. As we're assigning to a hash, perl will automatically discard duplicate keys, saving only the last value. For example, in the initialisation, play will be set to 'false', but if it's in $4, the second line will reset it to 'true' because it's later in the list being assigned.
Second option, setting everything found to true, and setting the rest to false:
my %control = map { $_ => 'true' } split ' ', $4;
$control{$_} ||= 'false' for qw(play ctrl loop);
The ||= operator will only set the left variable ($control{$_}) if it isn't set to a true value already. Now, perl isn't going to look at the word "true" and determine that it's true while the word "false" is false. They're both true - the definition of "false" is undef, the number 0, the string '0', or the empty string, ''. The definition of "true" is not false. Thus, the string 'true' is noth undef, the number 0, the string '0', or the empty string, thus must be true. So if the first line has set the value to true, the second line won't change it. Alternately:
my %control = map { $_ => 'true' } split ' ', $4;
%control = ((map { $_ => 'false' } qw(play ctrl loop)), %control);
I think by now, you should be able to figure this out. Finally, one last alternative:
my %control = ((map { $_ => 'false' } qw(play ctrl loop)),
(map { $_ => 'true' } split ' ', $4));
Here we're doing the same as before, but all in one line.
Now you get to pick which one makes the most sense and is the most readable. Don't pick one just because it's neat and clever - that just makes it harder to read later.
| [reply] [d/l] [select] |
could I just intialize the hash with a full list of options set to false, then set them true based on $4?
my %control = map { $_ => 'false' } split ' ', 'play ctrl loop'
my %control = map { $_ => 'true' } split ' ', $4;
| [reply] [d/l] |
my %control = map { $_ => 'false' } split ' ', 'play ctrl loop'
my %control = map { $_ => 'true' } split ' ', $4;
Nice logic, but you will clobber all those 'false' key/value pairs by assigning a new list to %control. Replace the second line with something like the following and you should be set:
$control{$_} = 'true' foreach split ' ', $4;
Some people feel the long form is more maintainable:
foreach ( split ' ', $4 ) {
$control{$_} = 'true';
}
| [reply] [d/l] [select] |
Thanks!
Now that I see it longform it makes a more sense the other way.
So is perl always so versatile in regards to parameter ordering? That is soooo slippery to put the foreach after the assignment, but it is readable.
| [reply] |