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

时间:2012-08-14 18:42:13

标签: ruby-on-rails ruby

  

可能重复:
  What does ||= (or equals) mean in Ruby?

Out on the internet我在Ruby / Rails中看到了以下语法:

user ||= User.new

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

5 个答案:

答案 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_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中的任务要多,但看起来很有趣。

答案 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