答案 0 :(得分:5)
如果已设置user
,则不执行任何操作,否则将分配新的User
对象(使用User.new
创建)。
According to David A. Black,“The Well-Grounded Rubyist”的作者:
x || = y表示:x || x = y
不同之处在于,如果x未定义,x || = y不会抱怨, 而如果你键入x || x = y并且范围内没有x,它会。
有关更多详细信息,请参阅parse.y的相关部分:
| var_lhs tOP_ASGN command_call
{
/*%%%*/
value_expr($3);
if ($1) {
ID vid = $1->nd_vid;
if ($2 == tOROP) {
$1->nd_value = $3;
$$ = NEW_OP_ASGN_OR(gettable(vid), $1);
if (is_asgn_or_id(vid)) {
$$->nd_aid = vid;
}
}
else if ($2 == tANDOP) {
$1->nd_value = $3;
$$ = NEW_OP_ASGN_AND(gettable(vid), $1);
}
else {
$$ = $1;
$$->nd_value = NEW_CALL(gettable(vid), $2, NEW_LIST($3));
}
}
NEW_OP_ASGN_OR
在node.h
中定义:
#define NEW_OP_ASGN_OR(i,val) NEW_NODE(NODE_OP_ASGN_OR,i,val,0)
NEW_NODE
看起来像这样:
#define NEW_NODE(t,a0,a1,a2) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
寻找NODE_OP_ASGN_OR
会导致compile.c
,其中有趣的部分如下所示:
case NODE_OP_ASGN_OR:{
LABEL *lfin = NEW_LABEL(nd_line(node));
LABEL *lassign;
if (nd_type(node) == NODE_OP_ASGN_OR) {
LABEL *lfinish[2];
lfinish[0] = lfin;
lfinish[1] = 0;
defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
lassign = lfinish[1];
if (!lassign) {
lassign = NEW_LABEL(nd_line(node));
}
ADD_INSNL(ret, nd_line(node), branchunless, lassign);
}
else {
lassign = NEW_LABEL(nd_line(node));
}
COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
ADD_INSN(ret, nd_line(node), dup);
if (nd_type(node) == NODE_OP_ASGN_AND) {
ADD_INSNL(ret, nd_line(node), branchunless, lfin);
}
else {
ADD_INSNL(ret, nd_line(node), branchif, lfin);
}
ADD_INSN(ret, nd_line(node), pop);
ADD_LABEL(ret, lassign);
COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value);
ADD_LABEL(ret, lfin);
if (poped) {
/* we can apply more optimize */
ADD_INSN(ret, nd_line(node), pop);
}
break;
}
我认为这比我想知道的Ruby中的任务要多,但看起来很有趣。
答案 1 :(得分:3)
它基本上是一个快捷方式:
user = user || User.new
或为了更好地理解:
if user.nil?
user = User.new
end
我打赌你之前看过类似的符号,比如'+'
i += 1
也可以写成:
i = i + 1
答案 2 :(得分:1)
此声明等同于
user = user || User.new
相当于
user = user ? user : User.new
当且仅当User.new
nil 时,才会将user
的值分配给变量user
。如果不是,user
的内容将保持不变。
答案 3 :(得分:1)
相当于user = user || User.new
。
这取决于||
运算符的短路行为。如果表达式的左侧为真,那么右侧将是什么并不重要,整体表达式将为真,因此操作员“短路”并停止评估。而不是返回布尔值“true”,||
运算符返回它评估的最后一个值。
因此,||=
对于分配默认值很有用。如果user
有值,则user || User.new
计算结果为user
,否则评估为User.new
,这是默认值。
等效块将是:
if user
user = user
else
user = User.new
end
答案 4 :(得分:0)
语句将user
设置为自身(如果它已经是现有对象)或User.new
(如果用户为空则将创建新用户)。这是一个逻辑OR,可以避免分配空的用户对象。
代码是
的简写user = user || User.new
如果user为null,则用户将设置为User.new
。