RoR:“user || = User.new”的含义

可能重复:
什么|| =(或等于)在Ruby中意味着什么?

在互联网上,我在Ruby / Rails中看到了以下语法:

user ||= User.new 

我是新手,我不能解析这个。 有人可以向我解释“|| =”运算符的作用吗?

如果user已设置, User.new执行任何操作,否则将分配新的User对象(使用User.new创建)。

根据 “The Well-Grounded Rubyist”的作者David A. Black的说法:

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_ORnode.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中的赋值更多,但是看起来很有趣。

它基本上是一个快捷方式:

 user = user || User.new 

或者为了更好地理解:

 if user.nil? user = User.new end 

我打赌你以前见过类似的符号,比如’+’这样的运算符

 i += 1 

也可以写成:

 i = i + 1 

这个陈述相当于

 user = user || User.new 

相当于

 user = user ? user : User.new 

当且仅当usernil时,它才会将User.new的值User.new变量user 。 如果不是,则user的内容将保持不变。

它等同于user = user || User.new user = user || User.new

这取决于||的短路行为 运营商。 如果表达式的左侧为真,那么右侧将是什么并不重要,整体表达式将为真,因此操作员“短路”并停止评估。 而不是返回布尔“真”, || operator返回它评估的最后一个值。

因此, ||=对于分配默认值很有用。 如果user有值,则user || User.new user || User.new计算到user否则它将评估为User.new ,这是默认值。

等效块将是:

 if user user = user else user = User.new end 

该语句将user设置为自身(如果它已经是现有对象)或User.new (如果用户为null,则将创建新用户)。 这是一个逻辑OR,可以避免分配空的用户对象。

代码是一个简写

 user = user || User.new 

如果user为null,则user将设置为User.new