Mailing List Archive

Problem with my code for passing block
Good afternoon,

Can you help check my problem with this?

$ cat t1.pl
use strict;

package Myclass;

sub new {
my $self = shift;
bless {},$self;
}

sub run {
my $self = shift;
my $block = shift;
&{$block};
}

1;

package main;

my $obj = Myclass->new;
$obj->run( { "hello world"} );

$ perl t1.pl
Not a CODE reference at t1.pl line 13.


It seems I can't pass a code block to the caller. Where am I doing wrong?

Sorry I have the background of other language, such as in scala I always do:

scala> def strTrans(s:String)(f:String=>String) = f(s)
strTrans: (s: String)(f: String => String)String

scala> strTrans("katorena"){s=>s.reverse}
res0: String = anerotak

scala> strTrans("katorena"){s=>s.take(4)}
res1: String = kato

In above code {s=>s.reverse} and {s=>s.take} are the anonymous func (or
code block) I passed to the caller.

Thank you in advance.
Yamada
Re: Problem with my code for passing block [ In reply to ]
On Tue, 11 Jan 2022, 16:53 Yamada???, <yamoerina@gmail.com> wrote:

> Good afternoon,
>
> Can you help check my problem with this?
>
> $ cat t1.pl
> use strict;
>
> package Myclass;
>
> sub new {
> my $self = shift;
> bless {},$self;
> }
>
> sub run {
> my $self = shift;
> my $block = shift;
> &{$block};
> }
>
> 1;
>
> package main;
>
> my $obj = Myclass->new;
> $obj->run( { "hello world"} );
>
> $ perl t1.pl
> Not a CODE reference at t1.pl line 13.
>
>
> It seems I can't pass a code block to the caller. Where am I doing wrong?
>

Try putting the keyword "sub" in front of the block. You don't pass blocks,
you pass subroutine references. There is special syntaxes to coerce blocks
into sub refs, but they don't apply to method calls and have all kinds of
subtleties so you are better off avoiding them until you are far more
versed in perl.

$obj->run( sub { "hello world"} );

Almost modern perl programmers would not write:

&{$block};

They would write

$block->();

You may want to check out perlmonks for these kinds of questions. This list
is for folks who maintain the various ports of perl not such as a help
forum.

Also see perlsub.

Good luck!
Yves
Re: Problem with my code for passing block [ In reply to ]
Yamada-san,

The value you pass to 'run' is not a code reference, but an hash
reference, i.e. '{}'

A code reference would be: 'sub{}', so do '$obj->run( sub{ "hello
world"} );' instead.

Jacques

On 2022/01/11 17:51, Yamada??? wrote:
> Good afternoon,
>
> Can you help check my problem with this?
>
> $ cat t1.pl <http://t1.pl>
> use strict;
>
> package Myclass;
>
> sub new {
>   my $self = shift;
>   bless {},$self;
> }
>
> sub run {
>    my $self = shift;
>    my $block = shift;
>    &{$block};
> }
>
> 1;
>
> package main;
>
> my $obj = Myclass->new;
> $obj->run( { "hello world"} );
>
> $ perl t1.pl <http://t1.pl>
> Not a CODE reference at t1.pl <http://t1.pl> line 13.
>
>
> It seems I can't pass a code block to the caller. Where am I doing wrong?
>
> Sorry I have the background of other language, such as in scala I
> always do:
>
> scala> def strTrans(s:String)(f:String=>String) = f(s)
> strTrans: (s: String)(f: String => String)String
>
> scala> strTrans("katorena"){s=>s.reverse}
> res0: String = anerotak
>
> scala> strTrans("katorena"){s=>s.take(4)}
> res1: String = kato
>
> In above code {s=>s.reverse} and {s=>s.take} are the anonymous func
> (or code block) I passed to the caller.
>
> Thank you in advance.
> Yamada
>
Re: Problem with my code for passing block [ In reply to ]
Thanks for all your help.
Yes I have made the mistake to think {} is a code reference in perl.
?????????????????


On Tue, Jan 11, 2022 at 5:10 PM Jacques Deguest <jack@deguest.jp> wrote:

> Yamada-san,
>
> The value you pass to 'run' is not a code reference, but an hash
> reference, i.e. '{}'
>
> A code reference would be: 'sub{}', so do '$obj->run( sub{ "hello world"}
> );' instead.
>
> Jacques
>
> On 2022/01/11 17:51, Yamada??? wrote:
>
> Good afternoon,
>
> Can you help check my problem with this?
>
> $ cat t1.pl
> use strict;
>
> package Myclass;
>
> sub new {
> my $self = shift;
> bless {},$self;
> }
>
> sub run {
> my $self = shift;
> my $block = shift;
> &{$block};
> }
>
> 1;
>
> package main;
>
> my $obj = Myclass->new;
> $obj->run( { "hello world"} );
>
> $ perl t1.pl
> Not a CODE reference at t1.pl line 13.
>
>
> It seems I can't pass a code block to the caller. Where am I doing wrong?
>
> Sorry I have the background of other language, such as in scala I always
> do:
>
> scala> def strTrans(s:String)(f:String=>String) = f(s)
> strTrans: (s: String)(f: String => String)String
>
> scala> strTrans("katorena"){s=>s.reverse}
> res0: String = anerotak
>
> scala> strTrans("katorena"){s=>s.take(4)}
> res1: String = kato
>
> In above code {s=>s.reverse} and {s=>s.take} are the anonymous func (or
> code block) I passed to the caller.
>
> Thank you in advance.
> Yamada
>
>
>
Re: Problem with my code for passing block [ In reply to ]
So, I would like to ask another question:
Is it safe to pass function reference to the caller (mostly it's the method
instantized from a class) in mod_perl development env?
Or should I avoid using this style?

Thanks.
Re: Problem with my code for passing block [ In reply to ]
On Tue, 11 Jan 2022 at 10:18, Yamada??? <yamoerina@gmail.com> wrote:

> So, I would like to ask another question:
> Is it safe to pass function reference to the caller (mostly it's the
> method instantized from a class) in mod_perl development env?
> Or should I avoid using this style?
>

Nothing wrong with passing code refs at all. It is common. Some folks
prefer to pass *named* subroutines instead of anoymous ones. Eg:

$thing->method(sub { "whatever" });

might turn into

sub whatever {
"whatever";
}

$thing->method(\&whatever);

this style will produce more comprehensible and easy to debug error
messages. But tons of folks dont bother.

Good luck.

Yves
Re: Problem with my code for passing block [ In reply to ]
demerphq wrote:
: On Tue, 11 Jan 2022 at 10:18, Yamada??? <yamoerina@gmail.com> wrote:
:
: > So, I would like to ask another question:
: > Is it safe to pass function reference to the caller (mostly it's the
: > method instantized from a class) in mod_perl development env?
: > Or should I avoid using this style?
: >
:
: Nothing wrong with passing code refs at all. It is common. Some folks
: prefer to pass *named* subroutines instead of anoymous ones. Eg:
:
: $thing->method(sub { "whatever" });
:
: might turn into
:
: sub whatever {
: "whatever";
: }
:
: $thing->method(\&whatever);
:
: this style will produce more comprehensible and easy to debug error
: messages. But tons of folks dont bother.

(sorry to elaborate further on non-mod_perl topic)

In my opinion - do _not_ use named subroutines unless it is strictly
necessary. Quite on the contrary - anonymous subs are really useful.
For example, it is not easy to do unintentional closure in the nested
named subroutine (see 'Variable "%s" will not stay shared' in perldiag(1)).

Also, it is possible to pass coderef sort- or map-style. Just use
prototypes:

sub my_foreach(&@) {
my ($code, @vals) = @_;
# ... do some safety checks or whatever local magic ...
for my $val (@vals) {
$code->($val);
}
}

my_foreach { say shift; } qw(foo bar baz);

-Yenya

--
| Jan "Yenya" Kasprzak <kas at {fi.muni.cz - work | yenya.net - private}> |
| http://www.fi.muni.cz/~kas/ GPG: 4096R/A45477D5 |
We all agree on the necessity of compromise. We just can't agree on
when it's necessary to compromise. --Larry Wall
Re: Problem with my code for passing block [ In reply to ]
On Tue, 11 Jan 2022 at 11:35, Jan Kasprzak <kas@fi.muni.cz> wrote:

> demerphq wrote:
> : On Tue, 11 Jan 2022 at 10:18, Yamada??? <yamoerina@gmail.com> wrote:
> :
> : > So, I would like to ask another question:
> : > Is it safe to pass function reference to the caller (mostly it's the
> : > method instantized from a class) in mod_perl development env?
> : > Or should I avoid using this style?
> : >
> :
> : Nothing wrong with passing code refs at all. It is common. Some folks
> : prefer to pass *named* subroutines instead of anoymous ones. Eg:
> :
> : $thing->method(sub { "whatever" });
> :
> : might turn into
> :
> : sub whatever {
> : "whatever";
> : }
> :
> : $thing->method(\&whatever);
> :
> : this style will produce more comprehensible and easy to debug error
> : messages. But tons of folks dont bother.
>
> (sorry to elaborate further on non-mod_perl topic)
>
> In my opinion - do _not_ use named subroutines unless it is strictly
> necessary.


This is incredibly bad and irresponsible advice to give to a beginner.
Especially as *every* program that is written in the imperative style can
be expressed using only anonymous subs. The result would be incredibly
difficult to maintain and debug, but it would work. Named subs exist for a
reason. Heck naming subs is so important there are multiple modules on CPAN
exporting utility functions to name your anonymous subs.


> Quite on the contrary - anonymous subs are really useful.


I did NOT say they were not useful. I said they produce shitty error
messages:

$ cat t.pl
use strict;
use warnings;
use Carp qw(confess);

sub callit { $_[0]->(undef) }
sub incr { $_[0]++ }

local $SIG{__DIE__}= \&confess;
eval {
callit(sub { $_[0]++ });
1;
} or warn "anonymous sub failed:\n$@";
eval {
callit(\&incr);
1;
} or warn "named sub failed:\n$@";


$ perl t.pl
anonymous sub failed:
Modification of a read-only value attempted at t.pl line 10.
at t.pl line 10.
main::__ANON__(undef) called at t.pl line 5
main::callit(CODE(0x20c7fb8)) called at t.pl line 10
eval {...} called at t.pl line 9
named sub failed:
Modification of a read-only value attempted at t.pl line 6.
at t.pl line 6.
main::incr(undef) called at t.pl line 5
main::callit(CODE(0x20aed58)) called at t.pl line 14
eval {...} called at t.pl line 13

One tells me the sub incr() threw an error, the other tells me that an
anonymous sub did. If that anonymous sub was constructed at a distance in
an eval or something debugging exactly what is going wrong can be a total
nightmare.

cheers,
yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"