0

重複の可能性:
Rubyで|| =(または等しい)とはどういう意味ですか?

インターネット上で、Ruby/Railsで次の構文を見ました。

user ||= User.new

私は初心者で、これを解析することはできません。「||=」演算子の機能を誰かに説明してもらえますか?

4

5 に答える 5

5

がすでに設定されている場合、これは何もしません。そうでない場合は、新しいオブジェクト(で作成された)userを割り当てます。UserUser.new

「TheWell-GroundedRubyist」の著者であるデビッド・A・ブラックによると、

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での割り当てについて知りたかった以上のことだと思いますが、これを調べるのはかなり面白かったです。

于 2012-08-14T18:46:01.590 に答える
3

これは基本的に次のショートカットです。

user = user || User.new

またはより良い理解のために:

if user.nil?
    user = User.new
end

'+'のような演算子で以前に同様の表記法を見たことがあると思います

i += 1

これは、次のように書き出すこともできます。

i = i + 1
于 2012-08-14T18:46:58.163 に答える
1

このステートメントは、

user = user || User.new

これは

user = user ? user : User.new

nilの場合にのみ、の値をUser.new変数に割り当てます。そうでない場合、の内容は変更されません。useruseruser

于 2012-08-14T18:47:48.213 に答える
1

と同等user = user || User.newです。

||これは、オペレーターの短絡動作に依存しています。式の左側がtrueの場合、右側が何であるかは関係ありません。式全体がtrueになるため、演算子は「短絡」して評価を停止します。また、ブール値の「true」を返すのではなく、||演算子は評価した最後の値を返します。

したがって、||=デフォルト値を割り当てるのに役立ちます。に値がある場合userは、にuser || User.new評価されます。userそれ以外の場合User.newは、デフォルト値に評価されます。

同等のブロックは次のようになります。

if user
    user = user
else 
    user = User.new
end 
于 2012-08-14T18:51:37.543 に答える
0

ステートメントuserはそれ自体に設定されます(既存のオブジェクトの場合)またはUser.new(ユーザーがnullの場合は新しいユーザーを作成します)。これは、nullユーザーオブジェクトが割り当てられないようにする論理ORです。

コードはの省略形です

user = user || User.new

userがnullの場合、userはに設定されUser.newます。

于 2012-08-14T18:45:49.867 に答える