Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Contextual::Return blocks: can they be made to return the actual result?

by wanna_code_perl (Pilgrim)
on Jul 13, 2013 at 13:36 UTC ( #1044154=perlquestion: print w/ replies, xml ) Need Help??
wanna_code_perl has asked for the wisdom of the Perl Monks concerning the following question:

Instead of returning the value I want, Contextual::Return returns a Contextual::Return::Value, an opaque inside-out object, that allows polymorphic access to the returned value. Suppose I have this:

use Contextual::Return; sub foo { my $blah = bless { name => shift }, 'whatever'; return VOID { croak "Useless use of foo() in void context" } STR { $blah->{name} } OBJREF { $blah } DEFAULT { $blah } } my $foo = foo('Boris');

Suppose I have some other code expecting a certain object type. Now ref($foo) is completely meaningless. Sure, I can do $foo->isa, but I still can't access my underlying data directly: $foo->{name} blows up:

DEFAULT block did not return a suitable reference to the hash dereference at ...

The only way I've been able to find to get at the HASH ref is with some awful incantation like eval $foo->Contextual::Return::DUMP(), which of course does not contain the original references.

These are just a couple of the issues for example's sake. I could work around them, but suffice to say it's making my life harder, not easier. Did I miss the point of this module? Can the C::R blocks be made to return the actual references within them, instead of the C::R::Value objects? I thought the FIXED modifier might do this, but it didn't seem to make a difference.

Comment on Contextual::Return blocks: can they be made to return the actual result?
Select or Download Code
Re: Contextual::Return blocks: can they be made to return the actual result?
by Corion (Pope) on Jul 13, 2013 at 13:42 UTC

    If you have code that uses ref to check the input parameters, you won't have luck using Contextual::Return. The easy approach would be to remove the ref checks in the receiving code.

    Out of curiosity, what does Contextual::Return provide to you that "normal" Perl code does not? Do you reallly make so much use of overloaded stringification that using overload is too much hassle?

    Personally, I find most of DCONWAYs modules very interesting but of little practical use.

      Out of curiosity, what does Contextual::Return provide to you that "normal" Perl code does not? Do you reallly make so much use of overloaded stringification that using overload is too much hassle?

      wantarray and caller have worked for almost everything I've ever needed, and I need them rarely, at that. In the current case, I was partly exploring C::R's capabilities, to enforce stricter usage of some subs--beyond the typical croak on void context.

      Truthfully, even if it would have worked flawlessly, I likely would have ended up removing the module dependency once the bulk of development was done and I had unit tests that took over.

Re: Contextual::Return blocks: can they be made to return the actual result?
by moritz (Cardinal) on Jul 13, 2013 at 13:54 UTC

    In my opinion, the whole approach of Contextual::Return is misguided. Either return an object that has a rich API (so that you can use it as a string, for example. See overload), or let the caller tell you what kind of return value it wants.

    Everything that goes beyond the simple void/scalar/list context distinction is guesswork, and guessing shouldn't be used for such fundamental things as return values.

      Agreed. Unfortunately, I went from "wow, this is cool!", to "how is this bit supposed to work?", to "how is any of this supposed to work?" Too bad, it's a module I really wanted to like.

Re: Contextual::Return blocks: can they be made to return the actual result?
by tobyink (Abbot) on Jul 13, 2013 at 15:53 UTC

    No; Contextual::Return always returns a Contextual::Return::Value object in scalar context. That's part of the mechanism that allows it to work; when the function is running it can't predict, say, whether the result will be used as a string or a boolean, so it returns an object that overloads both.

    If $foo is an object, you shouldn't be peeking at $foo->{name} anyway; write an accessor so that you can do $foo->name.

    If you're after wantarray-on-crack, then Want might be more to your liking.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
      If $foo is an object, you shouldn't be peeking at $foo->{name} anyway; write an accessor so that you can do $foo->name.

      Funny you should mention that. That's precisely what I was trying to do when I first saw the "DEFAULT block did not return a suitable reference to the hash dereference at ...". I decided it wasn't worth it a short time later, but it was starting to look like I'd have to implement most of the class inside one of Contextual::Return's METHOD { ... } blocks.

      You're spot on, though. If I use anything, it'll probably be Want.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (15)
As of 2014-08-27 21:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (253 votes), past polls