http://qs321.pair.com?node_id=1231622

pgmer6809 has asked for the wisdom of the Perl Monks concerning the following question:

On Rosetta (https://rosettacode.org/wiki/Continued_fraction#Perl )

there is the perl solution to evaluating Continuous fractions. The code given is: (<===== comments added by me)

sub continued_fraction { my ($a, $b, $n) = (@_[0,1], $_[2] // 100); #<========= what is $_[2] // 100 ?? $a->() + ($n && $b->() / continued_fraction($a, $b, $n-1)); } printf "&#8730;2 &#8776; %.9f\n", continued_fraction do { my $n; sub +{ $n++ ? 2 : 1 } }, sub { 1 }; # <===== Note there is no third arg p +assed printf "e &#8776; %.9f\n", continued_fraction do { my $n; sub { $n++ + || 2 } }, do { my $n; sub { $n++ || 1 } }; # <===== Note there is no + third arg passed printf "&#960; &#8776; %.9f\n", continued_fraction do { my $n; sub { + $n++ ? 6 : 3 } }, do { my $n; sub { (2*$n++ + 1)**2 } }, 1_000; #<== +== Here there is a 3rd arg printf "&#960;/2 &#8776; %.9f\n", continued_fraction do { my $n; sub { + 1/($n++ || 1) } }, sub { 1 }, 1_000; #<==== Here there is a 3rd arg

The output shown on Rosetta is correct

.

My TWO questions are:

1) Why can they pass in two arguments sometimes (two function refs) and three arguments other times (two function refs, and an integer count?

2) What value does the expression $_[2] // 100 assign to $n ?

Replies are listed 'Best First'.
Re: Rosetta Code Error or $n // 100
by GrandFather (Saint) on Mar 24, 2019 at 20:16 UTC

    They are really the same question. Passing only two arguments gets you an undef for the third argument. // is the defined or which returns the left hand argument if it is defined ($_[2] in this case) or the right hand argument if the left is undefined (100 in this case). So the expression returns 100 if the third argument is missing (undef).

    It is commonly used, as in the example code, to provide a default value when a variable or return from a sub may be undefined.

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

      Thanks. Either the code as posted on Rosetta has a typo // instead of || or I misread it. Once I realized that the // should be read as || it all made sense. Thanks again. Those replies were quicker than my thinking process. :(!

        No. || and // are two distinct operators. The first one checks whether its first argument is true, the second one whether it's defined; if not, they return the second argument. The difference becomes apparent with defined false values like 0:
        choroba@still ~ $ perl -wE 'say 0 || 1' 1 choroba@still ~ $ perl -wE 'say 0 // 1' 0

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Rosetta Code Error or $n // 100
by Perlbotics (Archbishop) on Mar 24, 2019 at 20:15 UTC

    When continued_fraction($x,$y,$z) is called, the parameters $x, $y, $z are assigned to the list @_ which is visible locally inside the sub and can be addressed in the usual way like $_[0], $_[1]...
    Here, @_[0,1] is an array-slice equivalent to the list ($_[0], $_[1]).

    BTW: Accessing @_ is "call-by-reference" style. Assigning to i.e $_[0] inside the sub would change callers $x in the example above. Usually, you would create a local copy, i.e. my (@args) = @_;. Accessing @_ might be used here for speed-optimisation or because of bad style?

    Perl historically had no strict function/sub signatures, so you can pass any number of arguments without Perl complaining - that feature was added recently (Perl 5.20, experimental).

    $n = $_[2] // 100; is the same as $n = defined($_[2]) ? $_[2] : 100;
    So, if the third - obviously optional parameter is given, it is used. If not, the default value 100 is assigned to $n.

Re: Rosetta Code Error or $n // 100
by AnomalousMonk (Archbishop) on Mar 24, 2019 at 23:53 UTC

    FYI: The  // (defined-or) operator was added with Perl version 5.10; see perlop.


    Give a man a fish:  <%-{-{-{-<