|
in reply to Re^2: Regex result being defined when it shouldn't be(?) in thread Regex result being defined when it shouldn't be(?)
defined $var or equivalently defined($var) will return the integer 1 (which is a TRUE value; 1 is also TRUE in C, so this shouldn't confuse you) if the variable is defined. It will return undef (which is a FALSE value) a FALSE value (see haukex's answer) if the variable is undefined. You then take that value, either 1 or undefthe FALSE value, and stringify it. The integer 1 stringifies into "1". The FALSE value undef stringifies into "". If you don't want undef FALSE to become "", don't stringify. (The eq operator is forcing the stringification on both its arguments.)
If you really just want a boolean that decides whether the $var is defined or not, just use the truthiness of the result of defined $var -- that is explicitly the boolean test for whether the $var is defined, and the defined $var and !defined $var syntax are explicitly saying "variable is defined" and "variable is not defined". This is similar to C: if you define a function int is_five(int x) { return (x==5); }, then the return value of is_five(var) and !is_five(var) are explicit ways of testing whether or not the variable is 5. From your claim, in C, I would have to write is_five(var)==-1 to verify that var is 5, and is_five(var)==0 to verify that var is not 5, which I vehemently disagree with: that notation obfuscates what c is doing, not clarifies what it's doing internally. Just trust that Perl will do the right thing with boolean expressions in a boolean context, just like you trust that C does the right thing with boolean results in a boolean context.
if it's the lack of parentheses that are confusing you, then use the parentheses.
Aside: Urgh... I did one last refresh before hitting create, and saw that haukex beat me by a minute or two again. :-(. I went to all the trouble of writing this up, so I'll hit create anyway.
update: I was wrong: defined($var) doesn't return undef or 1; it returns the special value, as haukex said. c:> perl -le "print defined($x)//'<undef>'; print defined($x)||'untrue
+'"
untrue
c:>
Re^4: Regex result being defined when it shouldn't be(?)
by haukex (Archbishop) on Nov 14, 2017 at 16:55 UTC
|
defined $var ... will return undef (which is a FALSE value) if the variable is undefined.
Sorry, that's not quite correct, compare the outputs of the following:
$ perl -wMstrict -MDevel::Peek -le 'my $x = undef; Dump( $x )'
$ perl -wMstrict -MDevel::Peek -le 'my $x = !1; Dump( $x )'
$ perl -wMstrict -MDevel::Peek -le 'my $x = defined(undef); Dump( $x )
+'
(Update: Whoops, just saw your update, you saw that yourself)
The rest of your post is excellent though, so no worries about the duplicated efforts, TIMTOWTDI :-) I especially like the comparison with C, and it makes another important point: comparing a true/false value explicitly is brittle: If defined decided to return 0 as a false value instead, then defined(...) eq "" will break!
| [reply] [d/l] [select] |
Re^4: Regex result being defined when it shouldn't be(?)
by chenhonkhonk (Acolyte) on Nov 14, 2017 at 17:01 UTC
|
In C and in Perl, the result of a true conditional is 1. EDIT: In Perl, false can be 0 or "" depending on context. Or not. I don't like this. /edit
When I'm doing checks on a bunch of values, if I used the implicit return from a is_defined() function, I can only have a boolean in response. If I want multiple types of responses I must use an explicit equals. Even in the boolean context, nearly all my conditions have some sort of equality test - even in the case of less than or greater than. To not have that form is an exception when reviewing the code, I have to stop and say "wait, what is the function supposed to be returning? a number? a string? a reference/pointer?".
You even state that saying is_five()==1 is somehow not intuitive, when that is literally what your is doing, it is checking the truthfulness of whether that number is five. | [reply] |
|
|
Just a couple of thoughts to try to get you into a Perl mindset :-)
First, note that there is a conceptual gray area between what is "a function" and "an operator". In C, I could replace all a==b's with a function is_equals(a,b), and in Perl, often functions that accept a single argument are called "operators", see e.g. Named Unary Operators (Update: and Terms and List Operators (Leftward)). That's why I look at "return values" the same, no matter if it's a return value from an operator, or a return value from a function.
In C and in Perl, the result of a true conditional is 1.
Not quite, in Perl it could also be "0 but true" (e.g. sysseek), or in theory any other "true" value.
In Perl, false can be 0 or "" depending on context. Or not. I don't like this.
Look at it this way: If in C some function that returns an int is documented to return "a true value" on success, then that does not mean it will return 1 on success, it will return a nonzero value. Just in Perl, the same abstraction also applies if a function is documented to return "a false value".
You even state that saying is_five()==1 is somehow not intuitive
Do you think that instead of if ( a==5 ), I should write if ( (a==5)==1 )? But then I have to write if ( ((a==5)==1)==1 ), and if ( (((a==5)==1)==1)==1 ), and ... ;-)
Plus, if a function is documented to return "a negative integer" on failure, like many C functions, you don't check that with somefunc()==-1 either.
I have to stop and say "wait, what is the function supposed to be returning? a number? a string? a reference/pointer?"
That's what the documentation is for... but if you wanted to be explicit in Perl, you could use if ( !(...) ) and if ( !!(...) ) (although the latter is of course redundant) - just don't use eq or == to check boolean values.
| [reply] [d/l] [select] |
|
|
Sysseek does not return a conditional, it returns a position or undef. I used the word conditional because it has a standard definition, and you are pretending to not understand it. Presumably. You can try to pretend being explicit about what a return value of something must be is bad, but if you say that you can't sit there and argue that having literally no idea is more informed. That is worse than wrong.
In C there are more than one return values on failures, and there are functions which return status values or pointers. Ironically, mentioning sysseek is important, they couldn't do if( ! sysseek() ){...} because the failure state, undef, and a success state, 0, both become a truthful value after not so they ended up using an exception to get around a lousy logic style. Additionally, even if you use defined, you have to know in advance whether or not your function can return a defined-but-false value. With explicit return values, there is no confusion unless you are deliberately being foolish. Defined itself not returning the value on success or undef on not defined is probably the core reason we can't have sensible returns.
And documentation is nice, except if you've ever worked in a production environment with code more than five minutes old. Say 20+ years.
| [reply] |
|
|
|
|
|
|
| |
|
|
|
|