I am on Perl 5.8 and am needing to assign a default value. I ended up doing this:
if ($model->test) {
$review = "1"
} else {
$review = ''
}
The value of $model->test
is going to be either "1"
or undefined. If there's something in $model->test
, set $review
to "1"
otherwise set it equal to ''
.
Because it's not Perl 5.10 I can't use the new swanky defined-or operator. My first reaction was to use the ternary operator like this...
defined($model->test) ? $review = "1" : $review = '';
but that didn't work either.
Does anyone have an idea how to assign this more efficiently? Janie
You have a precedence problem. What you have is the same as
You could make it work with parens.
But it's much cleaner to move the assignment out.
Of course, you could simply use
But why change undef to an empty string?
First of all, "That didn't work either" is not the most helpful thing you could tell us. It's important to know exactly how it didn't work: what did it do, what did you expect, and how to they differ?
But the problem with
is operator precedence. The conditional operator
? :
binds more tightly than the assignment operator=
, so the above is equivalent to:So if
$model->test
is defined, it does the equivalent ofYou can fix that problem with parentheses:
But really, why would you want to? The conditional (ternary) operator is useful when you want to use the result. If the result is going to be discarded, as it is here, it's clearer (and, as you've seen, less error-prone) to use an if/else statement:
or, if you insist on writing it on one line:
If you really want to use a conditional expression, you can do this:
which is probably a reasonable way to do it.
BUT :
The
defined
operator itself yields either"1"
(true) or""
(false). so the whole thing can be reduced to:Besides the conditional operator, I often like to use
do
, which returns the value from the last evaluated expression:I assume that
$model->test
is supposed to return a true or false value.Unless it specifically states that the false value is
undef
, the method could be rewritten to start returning some other false value instead. Which would break anything that only checks if the value is defined.( I think it is a bug that the method returns
undef
instead of the canonical false value. )So the best way to set
$review
is to test the truthfulness of the returned value; not it's definedness.I would like to point out that this still has a bug in it. If you want to be able to use the value as a number, it will emit warnings if it was false.
To fix that you should return
!1
(canonical false value), which will return a value that is the string''
, but also has the numerical value of 0.Notice that it could be simplified to just:
If you only want to change the value only when it is false, you could use the or operator
||
.If you really only want to know if it is defined, or not why don't you just use
defined
.If you want to change the value only when it is undefined, and you have Perl 5.10 or newer you could use the defined-or operator (
//
).On an older Perl, that would require more than one statement.
I'd usually write this as:
where the parentheses are for clarity for other people reading the code.
Then just use this: