2014-01-11 23 views
4

我有一個函數,這取決於調用上下文,我想用這個函數作爲其他函數的參數。令人驚訝的是,我發現這個second函數現在在列表環境中被調用。我試圖用+()強制標量上下文,但它不起作用,因爲我預期。所以唯一的方法是用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 

函數的參數被視爲列表,但這是否意味着該列表中的每個參數都意味着列表上下文?如果是,那爲什麼?

而且,使用scalar的作品,但是我有哪些其他方法需要在標量上下文中調用這個函數(沒有中間變量)?

回答

4

爲什麼函數參數會導致列表上下文?

子程序接受可變數量的標量作爲參數。還有什麼其他選擇?

函數的參數被視爲列表,但這是否意味着該列表中的每個參數都意味着列表上下文?如果是,那爲什麼?

是。因爲你希望能夠從哈希和數組的內容構建列表。有一百萬個理由說明這很有用。使用

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

scalar的作品,但我有其他的方式來調用標量上下文中此功能(無中間變量)?

有點。

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原型還可以實施標量上下文,但他們通常被認爲是不好的,正是因爲這個原因。

+0

添加到我的答案。 – ikegami

+0

當然,列表中的每個成員也可能是列表,所以沒有太多選擇。沒想過。謝謝! –

7

這是有道理的函數參數在列表環境進行評估:

  • 在Perl中,所有的子程序列表映射到列表中。

  • 如果子接受一個列表,評估列表上下文中的所有參數是有意義的,這使得函數可組合。考慮map

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

    如若foo()在標量上下文中調用,當我們打算返回列表1, 2, 3這將相當於return 3。使用列表上下文使我們能夠組成列表轉換,而不需要很多顯式循環。該的Schwartzian變換就是一個典型的例子:

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

有評估在列表環境參數兩種方式:

  • 使用強制標量上下文中的表達,像scalar或標量操作。

  • 使用原型($)。這破壞了函數的可組合性,要求你的子程序被預先聲明,可能會產生令人困惑的語義,並且在距離處的動作是。因此應該避免原型。

+(...)沒有強迫標量上下文,因爲一元加不徵收範圍內。它通常用於從函數應用程序中消除歧義(例如用於優先),例如, map +($_ => 2*$_), 1, 2, 3

一元加號不同於二元加號,它是一個算術運算符,它在其操作數上施加標量上下文並將它們強制轉換爲數字。

相關問題