in reply to Re^3: A short whishlist of Perl5 improvements leaping to Perl7 in thread A short whishlist of Perl5 improvements leaping to Perl7
Yes, Python doesn't have block scopes.
It has 4 scope levels° - it took me a while to understand them - and function scope is the smallest.
To mimic something similar to blocks you'll need again a named function in Python, since "lambdas" (aka anonymous subs in Perl) are limited to one statement only. Python compensates it by allowing nested named functions, leading to enclosed scope. *
> push @out, {A => $one, b => $two} while my ($one, undef, $two) = some_function())
This is certainly not doing what you expect, those $one and $two variables are different.
DB<17> @out=()
DB<18> $x=2; push @out, { A =>$one } while my $one = $x--
DB<19> x @out
0 HASH(0x31f07b8)
'A' => undef
1 HASH(0x31f0410)
'A' => undef
DB<20> @out=()
DB<21> $x=2; push @out, { A =>$one } while $one = $x--
DB<22> x @out
0 HASH(0x32023b0)
'A' => 2
1 HASH(0x3202428)
'A' => 1
DB<23>
Please keep in mind that declarations are only effective for following statements.
°) Local, Global, Built-in, Enclosed
UPDATE
*) remember Py's mantra about "explicit is better than implicit"? Perl's scoping rules are explicit ones here (and easier to understand)
Re^5: A short whishlist of Perl5 improvements leaping to Perl7
by eyepopslikeamosquito (Bishop) on Nov 24, 2020 at 21:40 UTC
|
remember Py's mantra about "explicit is better than implicit"? Perl's scoping rules are explicit ones here (and easier to understand)
Good point.
After reading Zen of Python,
I suggest Python's scoping rules violate four more principles:
- Beautiful is better than ugly
- Simple is better than complex
- Errors should never pass silently
- If the implementation is hard to explain, it's a bad idea
| [reply] |
Re^5: A short whishlist of Perl5 improvements leaping to Perl7
by eyepopslikeamosquito (Bishop) on Nov 25, 2020 at 01:15 UTC
|
Just remembered I did a Rosetta code node, implementing the same PGA-TRAM algorithm in Perl, Python, Haskell and C++.
In Perl I chose simple lexical scoping to data-hide the rtoa hash:
{
my %rtoa = ( M=>1000, D=>500, C=>100, L=>50, X=>10, V=>5, I=>1 );
sub roman_to_dec {
reduce { $a+$b-$a%$b*2 } map { $rtoa{$_} } split//, uc(shift)
}
}
Not wanting to get a headache from understanding Python scoping, I chose to data-hide the rtoa hash by making it a default function argument instead:
def roman_to_dec(r, __rtoa = dict(M=1000, D=500, C=100, L=50, X=10, V=
+5, I=1) ):
return reduce( lambda t,n: t+n-t%n*2, (__rtoa[c] for c in r.upper())
+ )
Suggestions for alternative/better ways to implement this algorithm in Perl and Python are still welcome (11 years later! :).
| [reply] [d/l] [select] |
|
{
my %rtoa = ( M=>1000, D=>500, C=>100, L=>50, X=>10, V=>5, I=>1 );
sub roman_to_dec {
reduce { $a+$b-$a%$b*2 } @rtoa{split//, uc(shift)}
}
}
Or double your fun with a double-split.
sub roman_to_dec { reduce { $a+$b-$a%$b*2 }
@{{split/(\d+)/, 'M1000D500C100L50X10V5I1'}}{split//, uc pop}
}
Or back to a map...
sub roman_to_dec { reduce { $a+$b-$a%$b*2 }
map 'M1000D500C100L50X10V5I1' =~ /$_(\d+)/i, split//, pop
}
Well, that was fun - thanks
| [reply] [d/l] [select] |
|
I'm not sure why rtoa has to be in the closure.
you can mimic your semantic in Python by using a generator function acting as closure, defining a nested function roman_to_dec and returning it.
I don't have Python installed and am not a Py expert, so please accept my semantically equal Perl interpolation.
(untested)
sub generator {
my %rtoa = ( M=>1000, D=>500, C=>100, L=>50, X=>10, V=>5, I=>1 );
my $c_nested = sub {
reduce { $a+$b-$a%$b*2 } map { $rtoa{$_} } split//, uc(sh
+ift);
};
return $c_nested;
}
*roman_to_dec = generator();
NB: This will look much easier in Python because it's automatically dereferencing.
UPDATE
I suppose most Pythonistas would rather prefer making rtoa a class variable and using roman_to_dec as a method. TIMTOWTDI. ;-)
| [reply] [d/l] [select] |
|
"Dear $name" # Perl and PHP
"Dear %s" % expr # Python and Ruby % printf-like operator
"Dear {0}".format(expr) # Python format string method
"Dear "+`expr` # Python backticks (TMTOWTDI)
"Dear #{expr}" # Ruby string interpolation
"Dear @{[expr]}" # Perl "Baby Cart" string interpolation
Curiously, Python is the only member of the gang of four languages to
allow you to reverse the order of the two string multiply operands:
5 * "X" also produces "XXXXX" in Python! TMTOWTDI! :)
5 * "X" ... but not in Ruby (won't compile: type error)
5 x "X" ... or Perl (produces empty string)
That is, the string multiply operator is commutative in Python,
but not in Perl or Ruby.
This language idiosyncrasy makes string multiply based solutions
most attractive in Python. To illustrate, note these code snippets
from my string multiply based solutions to this game:
$"x(318%$_/9) Perl
" "*(318%i/9) Ruby
318%i/9*" " Python
This is a very rare example of Python out-golfing both Perl and Ruby.
From my early 195-stroke function-based Python solution:
n=99
z=lambda:`n or 99`+" bottle"+"s of beer on the wall"[n==1:]
while n:y=z();n-=1;print"%s, %s.\n"*2%(y,y[:-12],n and"Take one down a
+nd pass it around"or"Go to the store and buy some more",z())
notice the expression:
n and"Take one down and pass it around"or"Go to the store and buy some
+ more"
Shortening the two strings above to "Take" and "Go to"
for clarity, let's consider the many and varied ways
of doing this in Python (TMTOWTDI):
"Take"if n else"Go to"
(n>0)*"Take"or"Go to"
["Go to","Take"][n>0]
("Go to","Take")[n>0]
n and"Take"or"Go to"
"GToa kteo"[n>0::2] # "Slice and Dice" wins this golf!
As you can see, I missed the winning Python "Slice and Dice"
tactical trick in this game.
| [reply] [d/l] [select] |
|
I'm not sure why rtoa has to be in the closure.
Just realised it doesn't thanks to the introduction of state variables in perl v5.10.
use v5.10;
use strict;
use warnings;
use List::Util qw(reduce);
sub roman_to_dec {
state %rtoa = ( M=>1000, D=>500, C=>100, L=>50, X=>10, V=>5, I=>1 );
reduce { $a+$b-$a%$b*2 } map { $rtoa{$_} } split//, uc(shift);
}
my @testdata = ( "XLII", "LXIX", "mi" );
for my $r (@testdata) {
print "$r: ", roman_to_dec($r), "\n";
}
| [reply] [d/l] |
|
|
|
|
|
|