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

Should this work or am I relying on any unspecified behavior? I ask because I was surpised that strict did not throw an error when using the dynamically created functions even though they are lexically before the call that creates them.

#implements something like "do" notation for the Identity monad. #bound variables become subs in the main namespace #add_var thunks the subs to get laziness with sharing sub add_var { my ($name, $fn) = @_; *{"main::$name"} = sub{ my $ret = $fn->(@_); *{"main::$name"}= sub{$ret}; return $ret }; return 1; } use strict; sub mdo { while (scalar @_ > 1) { my $name = shift; my $fn = shift; add_var($name,$fn); } my $fn = shift; return $fn->(); } my $f = sub { print "a: ", a(), " b: ", b(), "\n";}; mdo( a => sub{1} , b => sub{ a() + 5} , $f ); mdo( a => sub{2} , b => sub{ a() * 5} , $f );
a: 1 b: 6
a: 2 b: 10

Replies are listed 'Best First'.
Re: strict, typeglobs, and evaluation order
by tobyink (Canon) on Oct 11, 2013 at 07:35 UTC

    No, that's all fine. The reason strict doesn't care about this:

    my $f = sub { print "a: ", a(), " b: ", b(), "\n";};

    ... is because you've used parentheses for the argument lists. This means that the sub calls are not syntactically considered barewords. use strict "subs" only cares about barewords.

    I wouldn't necessarily consider it an especially elegant technique, but everything should work. Personally I'd at least try to clean up the subs that add_var installed at the end of mdo:

    sub mdo { my @to_be_cleaned; while (scalar @_ > 1) { my $name = shift; my $fn = shift; add_var($name,$fn); push @to_be_cleaned, $name; } my $fn = shift; my $return = $fn->(); require namespace::clean; namespace::clean->clean_subroutines('main', @to_be_cleaned); return $return; }
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: strict, typeglobs, and evaluation order
by choroba (Cardinal) on Oct 11, 2013 at 07:40 UTC
    add_var is defined out of the scope of strict. Also, strict does not mean you can only use subroutines defined by the classical sub name {...} (cf. AUTOLOAD). It means you cannot use barewords for undeclared subroutines - try removing the parentheses when calling the subroutines.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: strict, typeglobs, and evaluation order (strict on top)
by Anonymous Monk on Oct 11, 2013 at 07:32 UTC
    Move use strict; at the top of the file and try that :)