[32408] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 3675 Volume: 11

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Mon Apr 23 18:14:23 2012

Date: Mon, 23 Apr 2012 15:14:10 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Mon, 23 Apr 2012     Volume: 11 Number: 3675

Today's topics:
    Re: Using symbolic references to invoke package methods <rweikusat@mssgmbh.com>
    Re: Using symbolic references to invoke package methods <ben@morrow.me.uk>
    Re: Using symbolic references to invoke package methods <rweikusat@mssgmbh.com>
    Re: Using symbolic references to invoke package methods <ben@morrow.me.uk>
    Re: Why does this code works without cat ? <ben@morrow.me.uk>
        WWW::Mechanize and 3rd party APIs (Google) <justin.1203@purestblue.com>
    Re: WWW::Mechanize and 3rd party APIs (Google) (Randal L. Schwartz)
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Mon, 23 Apr 2012 14:10:06 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Using symbolic references to invoke package methods - good or bad practice?
Message-Id: <87wr56y4pd.fsf@sapphire.mobileactivedefense.com>

Ben Morrow <ben@morrow.me.uk> writes:
> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>> Ben Morrow <ben@morrow.me.uk> writes:
>> >
>> > Are you looking for ->can? This resolves the method and returns a
>> > coderef: it's effectively the equivalent of \&foo for methods. (And,
>> > just like \&foo, it will under some circumstances return a stub, which
>> > may or may not turn out to resolve to a real method when you call
>> > it.)
>> 
>> As addition to the already posted code (tested on 5.10.1):
>> 
>> -------------
>> # nor this
>> #'
>> eval {
>>     $c->can($_)->() for qw(blubb blah);
>> };
>> print("$@");
>
> This isn't supposed to work: the coderef returned by can does not
> include an implicit invocant, you have to provide one explicitly.

There is no such thing as 'an invocant' in perl. A class is a package
and a method is nothing but a subroutine located in a specific way (by
looking at the package the 'invocant' was blessed into in order to
determine where to start search for a sub of the given name). Provided
such subroutine was found, it is then called with the 'invocant' as
$_[0] and the remaining arguments following after it. Since can is
supposed to do a method search, there's no need for doing another
method search: The result is a sub reference which can be called like
any other sub reference. Since neither of the two looks at @_, there's
no need to pass any arguments to it.

That was the technical explanation. Replacing the (correct) code I was
using with the kind of code you believe to be correct, namely,

-----------
# nor this
#'
eval {
        for (qw(blubb blah)) {
                $m = $c->can($_);
                $c->$m();
        }
};
print("$@");
----------

leads to the exact same result:

Blubb!
Undefined subroutine &Child::blah called at a.pl line 48.

NB: The $c->$m() can also be written as $m->($c).

[...]

>>     $c->$_() for map { Child->can($_); } qw(blubb blah);

[...]

>> NB: At least with Perl 5.10.1, using map in this way together with for
>> is not a good idea: At the implementation level, this is a two pass
>> algorithm which first iterates over all of the 'input' values in order
>> to create the list returned by map and then loops over this list,
>> executing the actual loop body.
>
> It is in principle a little less efficient than a streaming
> implementation, yes, though for a list of two elements (or, indeed, 200)
> this is extremely unlikely to be visible in practice. Trying to avoid
> temporary lists means effectively avoiding 'for' altogether, and it's
> far too useful for that.

You seem to have missed the point of my text: I wasn't writing about
'temporay lists' but about a two-pass algorithm: The for ... map is
compiled to code which executes two loops instead of one (at least on
Perl 5.10.0). And this implies that the mapping step should rather be
done as part of the loop body. It would be nice if perl could do this
conversion (or something which accomplished the same thing)
implicitly.


------------------------------

Date: Mon, 23 Apr 2012 15:39:52 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Using symbolic references to invoke package methods - good or bad practice?
Message-Id: <o66g69-l9m.ln1@anubis.morrow.me.uk>


Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> 
> -----------
> # nor this
> #'
> eval {
>         for (qw(blubb blah)) {
>                 $m = $c->can($_);
>                 $c->$m();
>         }
> };
> print("$@");
> ----------
> 
> leads to the exact same result:
> 
> Blubb!
> Undefined subroutine &Child::blah called at a.pl line 48.

No it doesn't. If I run

    #!/usr/bin/perl

    $\ = "\n";

    {
        package Parent;
        sub new { bless [], $_[0] }
        sub blah { print "blah" }
    }

    {
        package Child;
        our @ISA = "Parent";
        sub blubb { print "blubb" }
    }

    my $c = Child->new;

    eval {
        for (qw(blubb blah)) {
            $m = $c->can($_);
            $c->$m();
        }
    };
    print("$@");

I get

    blubb
    blah


(with an extra blank line on the end, since $@ was empty). What
*exactly* are you running that gives you something different?

> > It is in principle a little less efficient than a streaming
> > implementation, yes, though for a list of two elements (or, indeed, 200)
> > this is extremely unlikely to be visible in practice. Trying to avoid
> > temporary lists means effectively avoiding 'for' altogether, and it's
> > far too useful for that.
> 
> You seem to have missed the point of my text: I wasn't writing about
> 'temporay lists' but about a two-pass algorithm: The for ... map is
> compiled to code which executes two loops instead of one (at least on
> Perl 5.10.0). And this implies that the mapping step should rather be
> done as part of the loop body. It would be nice if perl could do this
> conversion (or something which accomplished the same thing)
> implicitly.

I understood perfectly: the map runs one loop, which builds a temporary
list, and the for runs another which consumes it. I see the temporary
storage required as more of a 'problem' than the two loops: the two
loops perform the same steps as one would have, they just do them in a
different order. The only issue with running AAAABBBB rather than
ABABABAB is that you need to store the results of all the As somewhere
so you can feed them to the Bs.

Lazy lists are a way of effectively inverting the map loop so it runs
iterations on demand rather than all at once. This means the for loop
can pull one value from the map at a time and process it, without having
to allocate storage for the others.

Ben



------------------------------

Date: Mon, 23 Apr 2012 17:37:56 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Using symbolic references to invoke package methods - good or bad practice?
Message-Id: <87vckqwgij.fsf@sapphire.mobileactivedefense.com>

Ben Morrow <ben@morrow.me.uk> writes:
> From: Ben Morrow <ben@morrow.me.uk>
> Subject: Re: Using symbolic references to invoke package methods - good or bad practice?
> Newsgroups: comp.lang.perl.misc
> Date: Mon, 23 Apr 2012 15:39:52 +0100
>
>
> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>> 
>> -----------
>> # nor this
>> #'
>> eval {
>>         for (qw(blubb blah)) {
>>                 $m = $c->can($_);
>>                 $c->$m();
>>         }
>> };
>> print("$@");
>> ----------
>> 
>> leads to the exact same result:
>> 
>> Blubb!
>> Undefined subroutine &Child::blah called at a.pl line 48.
>
> No it doesn't.

It does. The code is the one I originally posted with some appended/
modified parts. In this case the reason for the error message was
that it contained a \&Child::blah before the can invocation. This
effectively kills the inheritance mechanism for blah because it creates
an 'undefined' Child::blah sub which exists in the symbol table of
Child. Trying to invoke the method in the usual way also won't work
afterwards. 

[...]

>> You seem to have missed the point of my text: I wasn't writing about
>> 'temporay lists' but about a two-pass algorithm: The for ... map is
>> compiled to code which executes two loops instead of one (at least on
>> Perl 5.10.0). And this implies that the mapping step should rather be
>> done as part of the loop body. It would be nice if perl could do this
>> conversion (or something which accomplished the same thing)
>> implicitly.
>
> I understood perfectly: the map runs one loop, which builds a temporary
> list, and the for runs another which consumes it. I see the temporary
> storage required as more of a 'problem' than the two loops:
>
> the two loops perform the same steps as one would have, they just do
> them in a different order.

[...]

They don't. That was what I was writing about. The additional steps
are the operations required to perform the second loop. This implies
that using map in this way has twice the looping overhead of a loop
which does the transformation 'inline'.


------------------------------

Date: Mon, 23 Apr 2012 22:05:17 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Using symbolic references to invoke package methods - good or bad practice?
Message-Id: <dpsg69-sap.ln1@anubis.morrow.me.uk>


Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> Ben Morrow <ben@morrow.me.uk> writes:
> > Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> >> 
> >> -----------
> >> # nor this
> >> #'
> >> eval {
> >>         for (qw(blubb blah)) {
> >>                 $m = $c->can($_);
> >>                 $c->$m();
> >>         }
> >> };
> >> print("$@");
> >> ----------
> >> 
> >> leads to the exact same result:
> >> 
> >> Blubb!
> >> Undefined subroutine &Child::blah called at a.pl line 48.
> >
> > No it doesn't.
> 
> It does. The code is the one I originally posted with some appended/
> modified parts. In this case the reason for the error message was
> that it contained a \&Child::blah before the can invocation.

Oh, yes, that makes sense. I couldn't see what you could have done which
was breaking it :).

> >> You seem to have missed the point of my text: I wasn't writing about
> >> 'temporay lists' but about a two-pass algorithm: The for ... map is
> >> compiled to code which executes two loops instead of one (at least on
> >> Perl 5.10.0). And this implies that the mapping step should rather be
> >> done as part of the loop body. It would be nice if perl could do this
> >> conversion (or something which accomplished the same thing)
> >> implicitly.
> >
> > I understood perfectly: the map runs one loop, which builds a temporary
> > list, and the for runs another which consumes it. I see the temporary
> > storage required as more of a 'problem' than the two loops:
> >
> > the two loops perform the same steps as one would have, they just do
> > them in a different order.
> 
> They don't. That was what I was writing about. The additional steps
> are the operations required to perform the second loop. This implies
> that using map in this way has twice the looping overhead of a loop
> which does the transformation 'inline'.

Oh, I see; yes, I suppose that's true, but if you've got to the point of
worrying about the overhead of the for or map loop itself you shouldn't
be writing in Perl any more. If you need that level of efficiency, you
need to do it in C.

Ben



------------------------------

Date: Mon, 23 Apr 2012 15:48:15 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Why does this code works without cat ?
Message-Id: <fm6g69-l9m.ln1@anubis.morrow.me.uk>


Quoth Eric Pozharski <whynot@pozharski.name>:
> 
> And zsh wins!

Define 'wins'. If you mean 'produces a confusing and unexpected result
as a consequence of trying to be too clever', then yes, I agree.

(And yes, I am aware clpmisc constitutes something of a glass house in
that regard... :).)

> 	{6617:23} [0:0]% bash
> 	{1:1} [0:0]$ perl -wle 'print -s STDIN' </etc/passwd </etc/group
> 	1006
> 	{26:2} [0:0]$ perl -nle '$aa++; END { print $aa }' </etc/passwd </etc/group
> 	68

Well, what else would you expect? Redirections in shish shells are
processed in order, from left to right, and each one overwrites any
previous assignment to that file descriptor. Otherwise things like

    foo 3>&2 2>&1 >&3 3>&- | bar

wouldn't work properly.

Ben



------------------------------

Date: Mon, 23 Apr 2012 14:41:18 +0100
From: Justin C <justin.1203@purestblue.com>
Subject: WWW::Mechanize and 3rd party APIs (Google)
Message-Id: <uo2g69-sue.ln1@zem.masonsmusic.co.uk>

I'm trying to mechanize a site which returns data
depending the location you enter into a form, and a
distance from that location (selected from a
drop-down). I was completing the form and submitting
it, as I would in a browser, but not getting the
result I expected.

On further investigation it appears that the site
sends the location information to GoogleMaps
(JavaScript), which returns a location that gets
substituted into the form before it is submitted.

Has anyone automated a site like this before? Can you
offer any suggestion as to how I interact with
Google's API?

   Justin.

-- 
Justin C, by the sea.


------------------------------

Date: Mon, 23 Apr 2012 08:54:05 -0700
From: merlyn@stonehenge.com (Randal L. Schwartz)
To: Justin C <justin.1203@purestblue.com>
Subject: Re: WWW::Mechanize and 3rd party APIs (Google)
Message-Id: <86y5pm30ma.fsf@red.stonehenge.com>

>>>>> "Justin" == Justin C <justin.1203@purestblue.com> writes:

Justin> Has anyone automated a site like this before? Can you
Justin> offer any suggestion as to how I interact with
Justin> Google's API?

Yes.  Please follow Google's API guidelines at
https://developers.google.com/ and don't try to subvert them with
WWW::Mechanize.

print "Just another Perl hacker,"; # the original

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.posterous.com/ for Smalltalk discussion


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests. 

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V11 Issue 3675
***************************************


home help back first fref pref prev next nref lref last post