in reply to •Re: Auto-detecting returned or passed variable type
in thread Auto-detecting returned or passed variable type

I think I'm just not explaining myself well.

Here's a rough example...

$result = $obj->functionA($obj->functionB());

I want whatever function B returns to be passed as a reference to function A. I don't know what function B is going to return because that whole line is generated by a Parse::RecDescent grammar which is writing the Perl script based on the parsing of a scripting language I designed.

If I knew functionB was always going to return a list, I could do...

$result = $obj->functionA([ $obj->functionB() ]);

Or if I knew it was going to be a hash...

$result = $obj->functionA({ $obj->functionB() });

I've thought of writing a function which takes in some values and returns a reference to them, whatever they might be...

$result = $obj->functionA($obj->createrightreftype($obj->functionB()));

But I can't think of any way to make createrightreftype do the right thing.

Does that make any more sense? I'm finding it difficult to describe this.

Replies are listed 'Best First'.
•Re^3: Auto-detecting returned or passed variable type
by merlyn (Sage) on Aug 19, 2004 at 21:01 UTC
    $result = $obj->functionA($obj->functionB());
    That's going to be calling method functionB in a list context. Therefore, the one and only answer you can have in Perl is "it is returning a list". Every other thing you think it might be doing is not happening.

    Your statement of "always going to return a list" is therefore true. Your statement of "going to be a hash" is therefore always false.

    I don't see the confusion here. It's the caller that decides what the called routine returns. It's that simple.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      My thinking is that is functionB does...

      return %myhash;

      ...then it's therefore returning a hash. In which case to pass a reference to that to functionA it would have to be...

      $obj->functionA({ $obj->functionB() });

      But if functionB did...

      return @myarray;

      Then I'd have to do...

      $obj->functionA([ $obj->functionB() ]);

      And it functionB did return...

      return $scalar or return \$ref

      Then it would be...

      $obj->functionA($obj->functionB());

      My problem is that I don't know which one of those four possibilities functionB is going to do, and therefore don't know whether to wrap it in braces (for a hash ref) or square brackets (for an array ref) or nothing (for a scalar, or if it's already a reference).

      You have got me thinking however that I should always be doing the square bracket array reference however, because functionA can always find a way to deal with that.

        My thinking is that is functionB does...
        return %myhash;
        ...then it's therefore returning a hash.
        Well, see, that's where your thinking is inconsistent with Perl. In Perl, the last expression evaluated in the subroutine (whether preceded by the keyword return or not) acts as if you had a long-distance assignment operation. For example, if that subroutine were to be called in a scalar context, you get:
        $secret_return_value = %myhash;
        and if called in a list context, you get:
        @secret_return_value = %myhash;
        You wouldn't call the latter "assigning a hash" would you? No. You are merely evaluating a hash in a list context, which by definition flattens it out into a bunch of key/value pairs. Similarly, the scalar context invocation uses the scalar value for a hash name.

        So, again, I can see where your confusion results, but if you can follow my explanation, you'll see that the situations you keep talking about can never occur. And hence, your original question was nonsense.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.