Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why function arguments induce list context?

Tags:

perl

I have a function, which depends on calling context and i wanted to use this function as as argument to other function. Surprisingly i discovered that this second function is called in list context now. I tried force scalar context with +() but it does not work as i expected. So only way was to call it implicitly with scalar.

use 5.010;

say first( 1, second( 'y' ) );
say first( 1, +( second( 'y' ) ) );
say first( 1, scalar second( 'y' ) );

sub first {
  my $x = shift;
  my $y = shift;

  return "$x + $y";
}

sub second {
  my $y = shift;

  if ( wantarray ) {
    qw/ array array /;
  } else {
    'scalar';
  }
}
__END__
1 + array
1 + array
1 + scalar

Arguments to function are treated as list, but does it mean that every argument in that list implies list context too? If yes, then why?

And, using scalar works, but which other ways i have to call this function in scalar context (without intermediate variable)?

like image 719
w.k Avatar asked Jan 11 '14 11:01

w.k


People also ask

What could be the purpose of the arguments inside a function?

In mathematics, an argument of a function is a value provided to obtain the function's result. It is also called an independent variable. , is called a unary function. A function of two or more variables is considered to have a domain consisting of ordered pairs or tuples of argument values.

How function parameters are different from function arguments?

Note the difference between parameters and arguments: Function parameters are the names listed in the function's definition. Function arguments are the real values passed to the function. Parameters are initialized to the values of the arguments supplied.

What is difference between parameters and arguments?

Argument Vs. Parameter : Explore the Major Difference between Argument and Parameter. The values that are declared within a function when the function is called are known as an argument. Whereas, the variables that are defined when the function is declared are known as a parameter.

What is function argument in python?

The terms parameter and argument can be used for the same thing: information that are passed into a function. From a function's perspective: A parameter is the variable listed inside the parentheses in the function definition. An argument is the value that are sent to the function when it is called.


2 Answers

Why function arguments induce list context?

Subroutines accept a variable number of scalars as arguments. What other choice is there?

Arguments to function are treated as list, but does it mean that every argument in that list implies list context too? If yes, then why?

Yes. Because you want to be able to build lists from the contents of hashes and arrays. There's a million reason why that's useful.

%h = (%h, ...);  # Add to a hash
f( $x, @opts );  # Composing argument lists
etc

using scalar works, but which other ways i have to call this function in scalar context (without intermediate variable)?

Kinda.

say first( 1, "".second( 'y' ) );    # Side-effect: stringification
say first( 1, 0+.second( 'y' ) );    # Side-effect: numificatiion
say first( 1, !!second( 'y' ) );     # Side-effect: conversion to boolean

Subrountine prototypes can also enforce scalar context, but they're generally seen as bad for that very reason.

like image 42
ikegami Avatar answered Sep 25 '22 18:09

ikegami


It makes sense that function arguments are evaluated in list context:

  • In Perl, all subroutines map lists to lists.

  • If a sub takes a list, it makes sense to evaluate all arguments in list context, which makes functions composable. Consider map:

    map { ... } 1, 2, 3; # makes sense
    map { ... } foo();   # can we "return 1, 2, 3" for the same effect?
    

    Should the foo() be called in scalar context, this would be equivalent to return 3 when we intended to return the list 1, 2, 3. Using list context enables us to compose list transformations without to many explicit loops. The Schwartzian Transform is a prime example of this:

    my @sorted =
      map  { $_->[1] }
      sort { $a->[0] <=> $b->[0] }
      map  { [make_key($_), $_] }
      @input;
    

There are two ways to evaluate an argument in list context:

  • Use an expression that forces scalar context, like scalar or scalar operations.

  • Use prototypes like ($). This destroys composability of functions, requires your subroutine to be predeclared, can have confusing semantics, and is action at a distance. Prototypes should therefore be avoided.

Your +(...) did not force scalar context because unary plus does not impose context. It is commonly used to disambiguate parens (e.g. used for precedence) from a function application, e.g. map +($_ => 2*$_), 1, 2, 3.

The unary plus is distinct from the binary plus, an arithmetic operator which imposes scalar context on its operands and coerces them to numbers.

like image 78
amon Avatar answered Sep 26 '22 18:09

amon