in reply to Re^14: If you believe in Lists in Scalar Context, Clap your Hands
in thread If you believe in Lists in Scalar Context, Clap your Hands

What happens there is a clever trick of prototypes in Perl 5. It doesn't pass a variable by reference, but passes a reference to the variable that was an argument. There is a difference. It also sidesteps the fact that any aggregate object passed into a subroutine by the default call-by-value would otherwise be flattened to a list. This flattening by the default variable passing mechanism is evidence against calling Perl aggregates first-class objects.

If what happened was really "pass by reference" in a classical sense, one would be able to operate on the passed variable by the lexical or localized variable's name without regard for the reference, only it would effect the original. That's not what happens. You can force the subroutine, via the prototype mechanism, to take a reference to the argument but you still have to treat it as a reference.

sub foo (\@) { print pop @{$_[0]}; }; @bar = qw( foo bar ); foo @bar;

BTW, lists are not precluded from being first-class simply by not being named, either, as JavaFan pointed out as a disqualification earlier. Anonymous lists, anonymous functions, and anonymous closures are first-class objects in some languages.

As I said before, what constitutes a first-class value can vary by language. In Perl, one could consider arrays and hashes as first-class, but one could make arguments against that classification as well.

Replies are listed 'Best First'.
Re^16: If you believe in Lists in Scalar Context, Clap your Hands
by JavaFan (Canon) on Oct 29, 2008 at 18:38 UTC
    By your argument, C doesn't have first class integer variables either, as you either pass a copy of the value to a function, or the address of the variable.
      That's a completely inaccurate statement.

      In C, passing an integer variable by value results in the same integer value being assigned to the argument.

      Passing an array in Perl by value does not any more end up with the same "array value" inside the sub than passing a bare, anonymous list ends up with the same "list value" inside the sub. In fact, the bare, anonymous list is more likely to be preserved in its entire identity (only because it has less identity to lose) than the array is. All that gets passed are multiple scalars in order.

      When passing a pointer to a variable in C, you are not passing anything by reference at all. You are passing a pointer by value, and must use the pointer inside the function as a pointer and not as the variable. This is the same as taking a reference to a variable in Perl and passing that in. The technique of using the prototype feature to force the taking of the reference is syntactic sugar.

      An aside... K&R call passing a pointer into a function "pass by pointer", because it is pass-by-value but buys you some of the benefits of pass-by-reference when you really need them. The possibility of using pointers is part of what convinced Dennis M. Ritchie that C should be pass-by-value, because with them pass-by-reference's additional caveats are only necessary when you choose to emulate pass-by-reference and not the rest of the time.

      If you really want to see what pass-by-reference is, take a look at the pseudocode below.

      foo = 1; bar = 5; function inc_dec( x, y ) { x++; y--; return( x, y ); } res1, res2 = inc_dec( foo, bar );
      If this was a pass-by-value language, foo would be 1, bar would be 5, res1 would be 2, and res2 would be 4. If it was pass-by-reference, res1 would still be 2 and res2 would still be 4. Yet with pass-by-reference our imaginary language here would produce foo with a value of 2 and bar would have a value of 4. No dereferencing within the function is necessary. That's pass-by-reference.

      Update: s/bar have a value/bar would have a value/