Re: What about if (my $var = foo()) { ... }
by friedo (Prior) on Dec 29, 2007 at 15:52 UTC
|
if (my $result = some_func()) {
# do something with $result
}
I use this construct all the time, and am not aware of any problems with it. The conditional is testing the return value of the assignment, which is true if some_func() returns something true. If it's false, then $result gets whatever false value was returned and the block does not execute (or the compiler may optimize away the assignment completely -- I don't know how that works.)
Off hand, I can't think of any reason why this would not also be allowed in Perl 6.
| [reply] [d/l] [select] |
|
|
friedo,
Off hand, I can't think of any reason why this would not also be allowed in Perl 6.
In perl 5, we write:
for my $name (keys %people) {
# do something with $name
}
The $name lexical is implicitly scoped to the for block. This is not the case in perl 6. The way perl 6 solves this is by introducing parameters to the block so you achieve the same thing in a cleaner way (from a design perspective).
| [reply] [d/l] |
|
|
Eh? Going away? What's the corresponding Perl 6 construct and how/why is it considered to be "cleaner"?
| [reply] |
|
|
|
|
Re: What about if (my $var = foo()) { ... }
by duelafn (Parson) on Dec 29, 2007 at 16:27 UTC
|
if testa() -> $a { say $a }
elsif testb() -> $b { say $b }
else -> $b { say $b }
| [reply] [d/l] |
Re: What about if (my $var = foo()) { ... }
by grinder (Bishop) on Dec 29, 2007 at 16:06 UTC
|
I think you have eaten too much Christmas pudding :) You seem to be thinking the following constructs are equivalent:
These constructs are hardly equivalent and there is no ambiguity that needs to be cleaned up, regardless of whether they happen to appear within a conditional.
A lexical declared within an if is not prone to the my $foo if 0 persistency problem, period. Consider the construct
if (my $result = some_func())
assuming some_func() is some sort of cyclic iterator that returns a positive number, then 0, then undef, the if branch will be taken only when $result contains a positive number. If $result contains 0 or undef, the conditional will evaluate to false, and the else branch (if any) will be taken instead.
At no point will $result retain its previous contents. Even if it did at a purely implementational level, you're initialising it with a value via the assignment of the results of some_funct(), and so you're safe.
• another intruder with the mooring in the heart of the Perl
| [reply] [d/l] [select] |
|
|
grinder,
No, I assure you I know they are different and completely understand why postfix is wrong. Please read my response to dragonchild. My questions are specific to this construct.
The reason we don't do:
if (some_func()) {
my $val = some_func();
}
Is because some_func may change return values in subsequent invocations. The reason why we don't do:
my $val = some_func();
if ($val) {
# ...
}
Is because we want $val scoped as small as possible.
This only works because of the implicit scoping in perl 5 which is going away in perl 6 (at least in for blocks). I am wondering if there is an alternative way of writing this that accomplishes both things.
| [reply] [d/l] [select] |
|
|
if (my $val = some_func()) {
# ...
}
and keep as small a scope as possible, how about:
{
my $val = some_func();
if ($val) {
# ...
}
}
| [reply] [d/l] [select] |
Re: What about if (my $var = foo()) { ... } (explicit)
by tye (Sage) on Dec 29, 2007 at 16:22 UTC
|
See Re^2: Duh. 'my' scope in if else blocks.. If you still want that, then you just put an explicit scoping block around the area where the variable is used, of course. I'd probably put the assignment outside of the conditional as well.
| [reply] |
Re: What about if (my $var = foo()) { ... }
by dragonchild (Archbishop) on Dec 29, 2007 at 15:52 UTC
|
Those are different constructs. As has been discussed before, postfix notation only looks like the same as the normal versions. There are scoping and other differences between normal and postfix if, normal and postfix while, and normal and postfix for.
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
| [reply] |
|
|
dragonchild,
Yes, I know they are different constructs (I said as much). Was giving background information into why I was asking the question confusing? If so, I am only interested in the construct in the thread title and the questions I asked about it. I know I must sound like a broken record by now, I have a newborn and a 2 year old at home and I haven't had much sleep lately.
| [reply] |
Re: What about if (my $var = foo()) { ... }
by ikegami (Patriarch) on Dec 29, 2007 at 22:52 UTC
|
I'm confused. if BLOCK already creates a scope (in 5.8, at least)
>perl -c -Mstrict -we"if (my $r = f()) { g() } print($r);"
Global symbol "$r" requires explicit package name at -e line 1.
-e had compilation errors.
Note that the scope is around the entire statement, so any elsif clauses, "then" blocks, elsif blocks and else blocks will have access to the variable.
>perl -c -Mstrict -we"if (my $r = f1()) { g1() } elsif (my $r = f2())
+{ g2() }"
"my" variable $result masks earlier declaration in same scope at -e li
+ne 1.
-e syntax OK
Update: Nevermind, I understand the question now. Like someone's already said, there's nothing stopping you from creating an explicit block.
>perl -c -Mstrict -we"{ my $r = f(); if ($r) { g() } } print($r);"
Global symbol "$r" requires explicit package name at -e line 1.
-e had compilation errors.
Caveat: last, next and redo will ignore the implicit block but will treat the explicit bare block as a loop.
>perl -le"sub f { 1 } for (1..2) { if (my $r = f()) { next } print '
+!' }"
>perl -le"sub f { 1 } for (1..2) { { my $r = f(); if ($r) { next } }
+ print '!' }"
!
!
| [reply] [d/l] [select] |
Re: What about if (my $var = foo()) { ... }
by polettix (Vicar) on Dec 30, 2007 at 14:42 UTC
|
This issue was discussed -- "inside-out" -- some time ago, starting from this post from merlyn and more or less ending with this reply from TheDamian.
I would also add that the idiom could be useful even when the function is pure, but heavy on CPU. Just as a form of self-baked cache.
Hey! Up to Dec 16, 2007 I was named frodo72, take note of the change! Flavio
perl -ple'$_=reverse' <<<ti.xittelop@oivalf
Io ho capito... ma tu che hai detto?
| [reply] |
|
|
polettix,
Thanks! I tried hard to find this thread when I posted this because I remembered it. Unfortunately, I misremembered TheDamian being the one providing the solution and thought he was the one asking the question. Using Super Search to find posts by TheDamian asking a question (not a reply) didn't help and so I gave up.
| [reply] |
Re: What about if (my $var = foo()) { ... }
by ambrus (Abbot) on Jan 26, 2008 at 17:13 UTC
|
I've just found some code on my scratchpad which shows that apart from postfix modifiers, there's at least one other way where scoping rules get crazy. The following code behaves differently on perl 5.10.0 from 5.8.8.
perl -we '@a = qw"a b"; while (my $x = pop @a) { push @x, \$x; print \
+$x, ": ", ($x || 0), "\n"; redo if 0 != @x % 3; }; '
Note: I don't understand what happens in either case. I don't even really understand the simple my $x if 0 case.
| [reply] [d/l] [select] |
|
|
perl -we " @a = qw!a b!;while (my $x = pop @a) { push @x, \$x; print \
+$x, q!: !, ($x || 0), qq!\n!; redo if 0 != @x % 3; };
I believe the old behaviour is a bug, because $x isn't supposed to change | [reply] [d/l] |