RoR:“用户||= User.new”的含义[重复]
Posted
技术标签:
【中文标题】RoR:“用户||= User.new”的含义[重复]【英文标题】:RoR: Meaning of "user ||= User.new" [duplicate] 【发布时间】:2012-08-11 02:56:59 【问题描述】:可能重复:What does ||= (or equals) mean in Ruby?
Out on the internet 我在 Ruby/Rails 中看到过以下语法:
user ||= User.new
我是新手,我无法解析这个。有人可以向我解释一下“||=" 运算符的作用吗?
【问题讨论】:
啊,对不起。我尝试在 SO 上将 '||=' 放入搜索框中,但没有出现任何结果。也许我的查询被解释为几个布尔运算符而不是字符串?我搜索的方式不对吗? 我不确定 SO 如何处理 ||= 之类的字符。我使用英文单词或等号搜索。 我下次试试。谢谢。 【参考方案1】:语句将user
设置为自身(如果它已经是现有对象)或User.new
(如果user 为null,它将创建一个新用户)。这是一个逻辑或,可以避免分配空用户对象。
代码是简写
user = user || User.new
如果用户为空,那么用户将被设置为User.new
。
【讨论】:
【参考方案2】:如果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 分配的更多信息,但查找它相当有趣。
【讨论】:
x ||= y 表示:x = x ||是的【参考方案3】:它基本上是一个快捷方式:
user = user || User.new
或为了更好地理解:
if user.nil?
user = User.new
end
我敢打赌,你以前见过类似的符号,比如“+”这样的运算符
i += 1
也可以写成:
i = i + 1
【讨论】:
不仅nil
,还有false
。【参考方案4】:
这个语句等价于
user = user || User.new
相当于
user = user ? user : User.new
当且仅当 user
为 nil 时,它会将 User.new
的值分配给变量 user
。如果不是,user
的内容将保持不变。
【讨论】:
这里相同,nil
或 false
,不仅仅是nil
。
我可能是错的,但如果他们不熟悉||=
,我不希望他们熟悉?:
为什么?许多语言都有三元运算符,但并非所有语言都有||=
。
@MichaelKohl 当然你是对的。【参考方案5】:
相当于user = user || User.new
。
这依赖于||
运算符的短路行为。如果表达式的左侧为真,那么无论右侧是什么,整个表达式都为真,因此运算符“短路”并停止计算。 ||
运算符不是返回布尔值“true”,而是返回它评估的最后一个值。
因此,||=
对于分配默认值很有用。如果user
有值,则user || User.new
计算为user
,否则计算为User.new
,这是默认值。
等效的块是:
if user
user = user
else
user = User.new
end
【讨论】:
以上是关于RoR:“用户||= User.new”的含义[重复]的主要内容,如果未能解决你的问题,请参考以下文章
shell脚本中:1>&2 2>&1 &>filename重定向的含义和区别