Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: coderef for 1 .. 2?

by kcott (Archbishop)
on Nov 01, 2017 at 07:59 UTC ( [id://1202498]=note: print w/replies, xml ) Need Help??


in reply to coderef for 1 .. 2?

G'day Ronald,

That's the range operator. See "perlop: Range Operators" for details.

The for loop will set $_ to each of the values, e.g.

$ perl -E 'say for 1 ..2' 1 2

That's equivalent to this:

$ perl -E 'for (1 .. 2) { say }' 1 2

In the context you show, it's not passing $_ to your coderef (that would be $fetch->($_)). Here's a longer example, showing your posted statement exactly:

$ perl -E 'my $fetch = sub { say "fetching ..." }; $fetch->() for 1 .. +2' fetching ... fetching ...

— Ken

Replies are listed 'Best First'.
Re^2: coderef for 1 .. 2?
by ronstudio (Novice) on Nov 01, 2017 at 10:08 UTC
    Hi Ken,

    Many thanks for your reply and also the reference link as well.

    May I ask a bit further regarding the example code?

    my $fetch; $fetch = sub { # Stop if there are no more URLs return unless my $url = shift @urls; # Fetch the next title my $end = $delay->begin; $ua->get($url => sub { my ($ua, $tx) = @_; say "$url: ", $tx->result->dom->at('title')->text; $end->(); # Next request $fetch->(); }); }; # Process two requests at a time $fetch->() for 1 .. 2; $delay->wait;
    From the above code example, I believe this is an example of recursion.
    There is condition to exit (return unless my $url = shift @urls;) and $fetch is calling itself within the sub $fetch.

    I can understand the part with range operators to call how many times of $fetch.
    But why if the range operator has been removed, i.e.
    $fetch->(); $delay->wait;
    Shouldn't the code process 1 request at a time until all the @urls have been processed?
    But from my testing, it will only process the first url and then stop. Could you tell me more about this part?

    Thanks,
    Ronald
      "From the above code example, I believe this is an example of recursion. There is condition to exit (return unless my $url = shift @urls;) and $fetch is calling itself within the sub $fetch."

      Yes, that's recursion. An exit stategy is a standard feature; all recursive functions should have this: without it, they will recurse infinitely (or, at least, to the extent system resources or configuration allow).

      "... if the range operator has been removed ... Shouldn't the code process 1 request at a time until all the @urls have been processed?"

      Yes, that's what I would have expected. I ran a few tests and all URLs are processed with any of these:

      $fetch->() for 1 .. 2; # or $fetch->() for 1 .. 3; # or $fetch->() for 1 .. 4; # or $fetch->(); $fetch->();

      But only one was processed with these:

      $fetch->() for 1 .. 1; # or $fetch->();

      I did some investigating. I will point out that I'm in no way a Mojo* expert; in fact, I wrote a very tiny application using Mojolicious::Lite about a month or so ago (and, until today, that was my only exposure to this family of modules).

      I added lots of additional code to that cookbook example; mostly printing variable values or indications of where the code had got to. Eventually, I tracked this down to "delay" related code. After commenting out these two lines, a single "$fetch->()" processed all URLs:

      ### my $end = $delay->begin; ... ### $end->();

      I was using Perl 5.26.0 and Mojolicious 7.46. Although the latter had only been installed about a month ago, I noticed that there had been five updates since then and 7.51 is the latest; the Changes file showed a number of delay-related comments, so I attempted to install the latest via cpan (I only got 7.50, but 7.51 is only a little over 24 hours old, so probably hasn't reached my CPAN mirror sites yet). I retested, with and without those two lines commented, and got the same results as before.

      I checked the bug reports; none really seemed to address this issue; "Remove finish and error events from Mojo::IOLoop::Delay" looked like it was the only one that was related to delays.

      I can't really spend any more time on this. The next place to look would probably be Mojo::IOLoop::delay(). There are others here with far more experience with the Mojo* modules; they may be able to provide much better answers than I have.

      In the spoiler below, I've added my code with all the debug statements (and some additional code). You may find it interesting to track the process or for further investigations.

      — Ken

      By the way, that code has a memory leak (cyclic reference ($fetch contains a reference to a closure which captures $fetch)).

      Replace

      my $fetch; $fetch = sub { ... $fetch->(); ... }; ... $fetch->(); ...

      with

      use feature qw( current_sub ); my $fetch = sub { ... __SUB__->(); ... }; ... $fetch->(); ...

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (8)
As of 2024-04-26 08:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found