Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

abstract expect call

by georgecarlin (Acolyte)
on Oct 25, 2013 at 21:15 UTC ( [id://1059757]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I'm a perl beginner and trying to improve the re-usability of my code

I have a question regarding expect.pm, specifically how to create an abstract expect call.
Take this example:

@expectthese = ("pattern1", "pattern2", "pattern3"); @sendthese = ("string1", "string2", "string3"); $exp->expect($timeout, [qr/$expectthese[0]/, sub { select(undef, undef, undef, 0.25); $exp->send("$sendthese[0]"); do_stuff...} ], [qr/$expectthese[1]/, sub { $exp->send("$sendthese[1]"); select(undef, undef, undef, 0.25); do_other_stuff...} ], [qr/$expectthese[2]/, sub { $exp->send("$sendthese[2]"); select(undef, undef, undef, 0.25); do_this_stuff...} ], );

In this example expect simultaneously waits for 3 patterns to occur and then the respective stuff is done... How would I go about creating an abstract Block that would work in above way for @expectthese and @sendthese without pre-defining the amount of elements these arrays have and consequently without knowing how many [qr//,sub {do_stuff;}], blocks are needed?

Thanks in advance

Replies are listed 'Best First'.
Re: abstract expect call
by kcott (Archbishop) on Oct 26, 2013 at 03:58 UTC

    G'day georgecarlin,

    The select(undef, undef, undef, $float_seconds); construct was a Perl4 (and earlier) solution for sleeping for fractional seconds.

    The usleep() function of Time::HiRes has been available since 1996 (earliest CPAN reference I could find: Time::HiRes v1.02) and has been part of the Perl distribution since Perl v5.8.0 (perl58delta - what is new for perl v5.8.0). It should be available for your immediate use without requiring any installation or other activity on your part. If you're using an earlier version of Perl (perl -v on the command line will tell you), I'd recommend upgrading: v5.18.1 is the current version.

    Add this line near the top of your code:

    use Time::HiRes qw{usleep};

    The usleep() function takes an argument in microseconds, so replace instances of

    select(undef, undef, undef, 0.25);

    with

    usleep 250000;

    You can do this in your current code, the ++solution provided by smis (above) or in whatever other solution you might choose.

    [Update: Oops! I wrote "microseconds" and then provided a number in milliseconds: s/250/250000/]

    -- Ken

      Thank you for pointing this out to me. Version is 5.8.4, so I have replaced all corresponding occurences in the script.
Re: abstract expect call
by smls (Friar) on Oct 25, 2013 at 22:33 UTC

    A perfect use-case for closures!

    You can use a loop to dynamically generate the callback subs passed to expect():

    my @actions = ( [qr/pattern1/, "response1", sub { dostuff.. } ], [qr/pattern2/, "response2", sub { do_other_stuff.. }], [qr/pattern3/, "response3", sub { do_this_stuff.. } ], ); $exp->expect($timeout, map { my ($pattern, $response, $code) = @$_; [ $pattern, sub { select(undef, undef, undef, 0.25); $exp->send($response); $code->(); } ]; } @actions);

    In Perl, every subroutine which uses lexical variables that were declared outside of it, will use the version of those variables from the time the sub was created. The technical way of saying it, is that the subroutine becomes a "closure" - for an in-depth explanation see e.g. Closure on Closures.

    So in this case, each copy of the "sub {...}" callback created inside the "map {...}" loop, will remember the corresponding values of $response and $code.

    Update: If you want, you can replace  $code->();  with  goto &$code;  to avoid the nested function call, and thus gain a tiny performance increase. The down-side is that you must remember not to add any additional commands to the closure after that line, because the goto will never return. (See the bottom two paragraphs of goto for an explanation.)

      This is not only exactly what I was looking for, it is very well explained for a beginner like me and with further documentation linked. Thank you very much for taking the time and esp. for such a great response!
Re: abstract expect call
by stonecolddevin (Parson) on Oct 25, 2013 at 21:48 UTC

    Can you provide a tangible example? This is really hard to follow.

    Three thousand years of beautiful tradition, from Moses to Sandy Koufax, you're god damn right I'm living in the fucking past

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (4)
As of 2024-03-28 16:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found