山羊操作员为什么工作? [英] Why does the goatse operator work?

查看:59
本文介绍了山羊操作员为什么工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

数组和列表之间以及列表和标量上下文之间的区别去年在 Perl 社区中进行了很多讨论(实际上每年都如此).我已经阅读了来自 chromium 的文章和 friedo,以及 这个推荐的僧侣节点.我现在正在尝试了解 goatse 运算符,记录在 perlsecret 中.

The difference between arrays and lists and between list and scalar context have been discussed in the Perl community quite a bit this last year (and every year, really). I have read over articles from chromatic and friedo, as well as this recommended monks node. I'm trying now to understand the goatse operator, documented in perlsecret.

这是我用来研究它的一些代码:

Here is some code I used to study it:

# right side gets scalar context, so commas return rightmost item
$string = qw(stuff junk things); 
say $string; # things

# right side gets list context, so middle is list assigned in scalar context
$string = () = qw(stuff junk things);
say $string; # 3

# right side gets list context, so creates a list, assigns an item to $string2, and
# evaluates list in scalar context to assign to $string
$string = ($string2) = qw(stuff junk things);
say $string; # 3
say $string2; # stuff

我想我已经了解了所有列表和标量上下文的工作原理.标量上下文中的逗号运算符返回其右侧,因此第一个示例只是将逗号表达式中的最后一项(不带任何逗号)分配给 $string.在其他示例中,将逗号表达式分配给列表会将其置于列表上下文中,因此会创建一个列表,并且在标量上下文中评估的列表会返回其大小.

I think I have come far enough to understand all of the list and scalar context workings. The comma operator in scalar context returns its right side, so the first example simply assigns the last item in the comma expression (without any commas) to $string. In the other examples, the assignment of the comma expression to a list puts it in list context, so a list is created, and lists evaluated in scalar context return their size.

有两部分我不明白.

首先,列表应该是不可变的.弗里多反复强调了这一点.我猜想通过 = 从列表到列表的分配将分配从一个列表中的项目分配到另一个列表中的项目,这就是为什么在第二个示例中 $string2 得到 'stuff',以及为什么我们可以通过列表赋值来解包 @_.但是,我不明白对空列表 () 的赋值是如何工作的.以我目前的理解,由于列表是不可变的,列表的大小将保持为 0,然后在示例 2 和 3 中将大小分配给 $stuff 将赋予它值 0.列表实际上不是不可变?

First, lists are supposed to be immutable. This is stressed repeatedly by friedo. I guess that assignment via = from list to list distributes assignments from items in one list to items in the other list, which is why in the second example $string2 gets 'stuff', and why we can unpack @_ via list assignment. However, I don't understand how assignment to (), an empty list, could possibly work. With my current understanding, since lists are immutable, the size of the list would remain 0, and then assigning the size to $stuff in examples 2 and 3 would give it the value 0. Are lists not actually immutable?

第二,我读过很多次,列表实际上并不存在于标量上下文中.但是山羊运算符的解释是它是标量上下文中的列表赋值.这不是标量上下文中不存在列表的说法的反例吗?还是这里发生了其他事情?

Second, I've read numerous times that lists don't actually exist in scalar context. But the explanation of the goatse operator is that it is a list assignment in scalar context. Is this not a counter-example to the statement that lists don't exist in scalar context? Or is something else going on here?

更新:在理解了答案之后,我认为额外的一对括号有助于概念化它的工作原理:

Update: After understanding the answer, I think an extra pair of parentheses helps to conceptualize how it works:

$string = ( () = qw(stuff junk things) );

在括号内,= 是对聚合"的赋值,列表赋值运算符也是如此(与标量赋值运算符不同,不应与列表上下文";列表和标量赋值可以发生在列表或标量上下文中).() 没有任何变化.=在Perl中有返回值,列表赋值的结果通过左边的=赋值给$string.对 $string 的赋值为 RHS 提供了标量上下文(括号中的所有内容),在标量上下文中,列表赋值运算符的返回值是 RHS 中的项数.

Inside the parens, the = is an assignment to an 'aggregate', and so is a list assignment operator (which is different from the scalar assignment operator, and which should not be confused with "list context"; list and scalar assignment can happen in either list or scalar context). () does not change in any way. = has a return value in Perl, and the result of the list assignment is assigned to $string via the left =. Assignment to $string gives scalar context to the RHS (everything in the parens), and in scalar context the returned value of the list assignment operator is the number of items in the RHS.

您可以将 RHS 列表分配放入列表上下文中:

You can put the RHS list assignment into list context instead:

($string) = ( () = qw(stuff junk things) );

根据perlop 列表上下文中的列表赋值返回已赋值的左值列表,这里是空的,因为在 () 中没有任何东西可以赋值.所以这里 $string 将是 undef.

According to perlop list assignment in list context returns the list of assigned lvalues, which here is empty since there is nothing to be assigned to in (). So here $string would be undef.

推荐答案

记住,在 Perl 中,赋值是一个表达式,你应该考虑表达式的值(赋值运算符的值)会有所帮助,而不是列表的值".

It helps to remember that in Perl, assignment is an expression, and that you should be thinking about the value of the expression (the value of the assignment operator), not "the value of a list".

表达式 qw(ab) 的值在列表上下文中为 ('a', 'b')'b'在标量上下文中,但表达式 (() = qw(ab)) 的值在列表上下文中为 () 而在标量中为 2语境.(@a = qw(a b)) 的值遵循相同的模式.这是因为 pp_aassign,列表赋值运算符,选择在标量上下文中返回一个计数:

The value of the expression qw(a b) is ('a', 'b') in list context and 'b' in scalar context, but the value of the expression (() = qw(a b)) is () in list context and 2 in scalar context. The values of (@a = qw(a b)) follow the same pattern. This is because pp_aassign, the list assignment operator, chooses to return a count in scalar context:

else if (gimme == G_SCALAR) {
    dTARGET;
    SP = firstrelem;
    SETi(lastrelem - firstrelem + 1);
}

(pp_hot.c 第 1257 行;行号可能会发生变化,但接近 PP(pp_aassign) 的结尾.)

(pp_hot.c line 1257; line numbers are subject to change, but it's near the end of PP(pp_aassign).)

那么,除了赋值运算符的之外,还有赋值运算符的副作用.列表赋值的副作用是将值从其右侧复制到其左侧.如果右侧先用完值,则左侧剩余元素得到undef;如果左侧首先用完值,则不会复制右侧的剩余元素.当给定 () 的 LHS 时,列表分配根本不会复制任何内容.但是赋值本身的值仍然是 RHS 中元素的数量,如代码片段所示.

Then, apart from the value of the assignment operator is the side-effect of the assignment operator. The side-effect of list assignment is to copy values from its right side to its left side. If the right side runs out of values first, the remaining elements of the left side get undef; if the left side runs out of values first, the remaining elements of the right side aren't copied. When given a LHS of (), the list assignment doesn't copy anything anywhere at all. But the value of the assignment itself is still the number of elements in the RHS, as shown by the code snippet.

这篇关于山羊操作员为什么工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆