Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re^3: A short whishlist of Perl5 improvements leaping to Perl7

by Eily (Monsignor)
on Nov 24, 2020 at 12:26 UTC ( #11124130=note: print w/replies, xml ) Need Help??


in reply to Re^2: A short whishlist of Perl5 improvements leaping to Perl7
in thread A short whishlist of Perl5 improvements leaping to Perl7

It took me ages to understand why and how to use the with keyword in python, until I realized it was an at attempt at recreating block-scoped variables.

I think I already had a similar discussion where LanX pointed out that python variables are lexically scoped as well, but the scope they are lexically bound to is the function, not the block. (perl decided to do block-scoped variables, but you could also imagine limitting the scope to a single expression. For example in push @out, {A => $one, b => $two} while my ($one, undef, $two) = some_function())

Replies are listed 'Best First'.
Re^4: A short whishlist of Perl5 improvements leaping to Perl7
by LanX (Sage) on Nov 24, 2020 at 15:12 UTC
    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.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    °) 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)

      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

      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! :).

        Alternative - yes, better - ???

        Why use a map - "slices forever !!"

        { 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

        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. ;-)

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11124130]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (4)
As of 2021-10-22 21:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My first memorable Perl project was:







    Results (85 votes). Check out past polls.

    Notices?