Ruby's (new) Bizarre Operator(s)

e$B$J$+$@$G$9!#e(B

http://www.rubyist.net/~matz/20070806.html#p01

?.e$B$O$$$m$$$m$H$+$V$k$N$G!"e(B.?e$B$He(B.&e$B$K$7$F$_$^$7$?!#e(B

e$B$G$be(Bsafe navigatione$B$C$FMQ8l$,$$$^$$$A$o$+$j$K$/$$$+$b!#e(B

Index: compile.c

— compile.c (revision 13073)
+++ compile.c (working copy)
@@ -3496,4 +3496,5 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_
break;
}

  •  case NODE_SAFENAV:
     case NODE_CALL:
     case NODE_FCALL:
    

@@ -3509,4 +3510,5 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_
VALUE argc;
unsigned long flag = 0;

  • LABEL *end_label = 0;
    VALUE parent_block = iseq->compile_data->current_block;
    iseq->compile_data->current_block = Qfalse;
    @@ -3566,5 +3568,5 @@ iseq_compile_each(rb_iseq_t iseq, LINK_
    #endif
    /
    reciever */
  • if (type == NODE_CALL) {
  • if (type == NODE_CALL || type == NODE_SAFENAV) {
    COMPILE(recv, “recv”, node->nd_recv);
    }
    @@ -3582,4 +3584,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_

    ADD_SEQ(ret, recv);

  • if (type == NODE_SAFENAV) {

  •  end_label = NEW_LABEL(nd_line(node));
    
  •  ADD_INSN(ret, nd_line(node), dup);
    
  •  ADD_INSNL(ret, nd_line(node), branchunless, end_label);
    
  • }
    ADD_SEQ(ret, args);

@@ -3598,4 +3605,15 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_
argc, parent_block, LONG2FIX(flag));

  • if (end_label) {
  •  ADD_LABEL(ret, end_label);
    
  • }
  • if (poped) {
  •  ADD_INSN(ret, nd_line(node), pop);
    
  • }
  • break;
  •  }
    
  •  case NODE_METHOBJ:{
    
  • COMPILE(ret, “recv”, node->nd_recv);
  • ADD_INSN1(ret, nd_line(node), methobj, ID2SYM(node->nd_mid));
    if (poped) {
    ADD_INSN(ret, nd_line(node), pop);
    Index: insns.def
    ===================================================================
    — insns.def (revision 13073)
    +++ insns.def (working copy)
    @@ -1199,4 +1199,18 @@ finish
    }

+/**

  • @c method/iterator
  • @e return Method object
  • @j Method e$B%*%V%8%'%/%H$r:n$ke(B
  • */
    +DEFINE_INSN
    +methobj
    +(VALUE mid)
    +(VALUE recv)
    +(VALUE val)
    +{
  • val = rb_obj_method(recv, mid);
    +}

/*********************************************************/
/
deal with control flow 3: exception */
Index: parse.y

— parse.y (revision 13073)
+++ parse.y (working copy)
@@ -373,4 +373,6 @@ static NODE new_yield_gen(struct parser
static NODE new_not_gen(struct parser_params,NODE
);
#define new_not(node) new_not_gen(parser, node)
+static NODE new_safenav_gen(struct parser_params,NODE*,ID,NODE*);
+#define new_safenav(r, m, a) new_safenav_gen(parser, r, m, a)

static NODE gettable_gen(struct parser_params,ID);
@@ -682,4 +684,6 @@ static void ripper_compile_error(struct
%token tAMPER /* & /
%token tLAMBDA /
/
+%token tSAFENAV /
.? /
+%token tMETHOBJ /
.& /
%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG
tQWORDS_BEG
%token tSTRING_DBEG tSTRING_DVAR tSTRING_END tLAMBEG
@@ -702,4 +706,5 @@ static void ripper_compile_error(struct
%left tOROP
%left tANDOP
+%left tSAFENAV
%nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
%left ‘>’ tGEQ ‘<’ tLEQ
@@ -708,5 +713,5 @@ static void ripper_compile_error(struct
%left tLSHFT tRSHFT
%left ‘+’ ‘-’
-%left '
’ ‘/’ ‘%’
+%left '’ ‘/’ ‘%’ tMETHOBJ
%right tUMINUS_NUM tUMINUS
%right tPOW
@@ -1305,4 +1310,24 @@ command : operation command_args
%
/
}

  • | primary_value tSAFENAV operation2 command_args %prec tLOWEST
  •    {
    
  •    /*%%%*/
    
  •  $$ = new_safenav($1, $3, $4);
    
  •  fixpos($$, $1);
    
  •    /*%
    
  •  $$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
    
  •    %*/
    
  •    }
    
  • | primary_value tSAFENAV operation2 command_args cmd_brace_block
  •    {
    
  •    /*%%%*/
    
  •  $$ = new_safenav($1, $3, $4);
    
  •  block_dup_check($4, $5);
    
  •  fixpos($$, $1);
    
  •    /*%
    
  •  $$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
    
  •  $$ = dispatch2(iter_block, $$, $5);
    
  •    %*/
    
  •   }
    
    | keyword_super command_args
    {
    @@ -1996,4 +2021,12 @@ arg : lhs ‘=’ arg
    %*/
    }
  • | arg tMETHOBJ operation2
  •    {
    
  •    /*%%%*/
    
  •  $$ = NEW_METHOBJ($1, $3);
    
  •    /*%
    
  •  $$ = dispatch3(binary, $1, ID2SYM('%'), $3);
    
  •    %*/
    
  •    }
    
    | tUMINUS_NUM tINTEGER tPOW arg
    {
    @@ -3403,4 +3436,14 @@ method_call : operation paren_args
    %*/
    }
  • | primary_value tSAFENAV operation2 opt_paren_args
  •    {
    
  •    /*%%%*/
    
  •  $$ = new_safenav($1, $3, $4);
    
  •  fixpos($$, $1);
    
  •    /*%
    
  •  $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
    
  •  $$ = method_optarg($$, $4);
    
  •    %*/
    
  •    }
    
    | keyword_super paren_args
    {
    @@ -3431,4 +3474,16 @@ method_call : operation paren_args
    %*/
    }
  • | primary_value tSAFENAV ‘[’ aref_args ‘]’
  •    {
    
  •    /*%%%*/
    
  •  if ($1 && nd_type($1) == NODE_SELF)
    
  •      $$ = logop(NODE_AND, $1, NEW_FCALL(tAREF, $4));
    
  •  else
    
  •      $$ = NEW_SAFENAV($1, tAREF, $4);
    
  •  fixpos($$, $1);
    
  •    /*%
    
  •  $$ = dispatch2(aref, $1, escape_Qundef($4));
    
  •    %*/
    
  •    }
    
    ;

@@ -6115,5 +6170,6 @@ parser_yylex(struct parser_params *parse
case ‘.’:
lex_state = EXPR_BEG;

  • if ((c = nextc()) == ‘.’) {
  • switch (c = nextc()) {
  • case ‘.’:
    if ((c = nextc()) == ‘.’) {
    return tDOT3;
    @@ -6121,4 +6177,11 @@ parser_yylex(struct parser_params *parse
    pushback(c);
    return tDOT2;
  • case ‘&’:
  •  if (peek('(')) break;
    
  •  lex_state = EXPR_DOT;
    
  •  return tMETHOBJ;
    
  • case ‘?’:
  •  lex_state = EXPR_DOT;
    
  •  return tSAFENAV;
    
    }
    pushback(c);
    @@ -7963,4 +8026,14 @@ new_args_gen(struct parser_params *parse
    }

+static NODE*
+new_safenav_gen(struct parser_params *parser, NODE *r, ID m, NODE *a)
+{

  • if (a && nd_type(a) == NODE_BLOCK_PASS) {
  • a->nd_iter = NEW_SAFENAV(r,m,a->nd_head);
  • return a;
  • }
  • return NEW_SAFENAV(r,m,a);
    +}

static void
local_push_gen(struct parser_params *parser, int inherit_dvars)
Index: include/ruby/node.h

— include/ruby/node.h (revision 13073)
+++ include/ruby/node.h (working copy)
@@ -240,4 +240,8 @@ enum node_type {
NODE_OPTBLOCK,
#define NODE_OPTBLOCK NODE_OPTBLOCK

  • NODE_SAFENAV,
    +#define NODE_SAFENAV NODE_SAFENAV
  • NODE_METHOBJ,
    +#define NODE_METHOBJ NODE_METHOBJ
    NODE_LAST
    #define NODE_LAST NODE_LAST
    @@ -436,4 +440,5 @@ enum ruby_node_flags {
    #define NEW_FCALL(m,a) NEW_NODE(NODE_FCALL,0,m,a)
    #define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0)
    +#define NEW_SAFENAV(r,m,a) NEW_NODE(NODE_SAFENAV,r,m,a)
    #define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a)
    #define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0)
    @@ -471,4 +476,5 @@ enum ruby_node_flags {
    #define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0)
    #define NEW_OPTBLOCK(a) NEW_NODE(NODE_OPTBLOCK,a,0,0)
    +#define NEW_METHOBJ(r,m) NEW_NODE(NODE_METHOBJ,r,m,0)

#define NOEX_PUBLIC 0x00

e$B%P%s%5%s$G$9!#e(B

Matzにっき(2007-08-06)

?.e$B$O$$$m$$$m$H$+$V$k$N$G!“e(B.?e$B$He(B.&e$B$K$7$F$$^$7$?!#e(B
e$B!Ve(B.?e$B!W$O!Ve(B?.e$B!W$h$jFI$
$d$9$$$H;W$$$^$9!#e(B
e$B!Ve(B?e$B!W$O$b$&%V!<%j%”%s%a%=%C%I$N:G8e$KIU$$$F$k$s$8$c$J$$$G$9$+!#e(B
e$B!Ve(B?.e$B!W$@$H$7$?$i!Ve(Bobject.method1?.method2e$B!W$C$F$I$&$$$&0UL#$K$J$k$s$G$7$g$&!)!Ve(Bobject
. method1
(?.) method2e$B!W$=$l$H$b!Ve(Bobject . method1? .
method2e$B!W!)!Ve(Bmethod1e$B!W<!Bh$K$OA[A|$G$-$k$+$bCN$l$^$;$s$,!Ve(B.?e$B!W$@$H$7$?$i$b$C$H4JC1$K$o$+$l$k$H;W$$$^$9!#e(B

e$B$G$be(Bsafe navigatione$B$C$FMQ8l$,$$$^$$$A$o$+$j$K$/$$$+$b!#e(B

e$B!Ve(Bsafe calle$B!W$NJ}$,$$$$$s$8$c$J$$$G$9$+!)e(B

e$B%P%s%5%s$G$9!#e(B

e$B!Ve(B.&e$B!W$O7k9=M_$7$$5$$,$7$^$7$?!#B>$N?M$O$I$&;W$&$s$G$7$g$&$+!#e(B
e$B$5$i$KJ8K!$rJ#;($K$9$k$3$H$X$NDq9346$OM}2r$G$-$^$9!#e(B

e$B$3$N!Ve(B.&e$B!W$O!Ve(BObject#methode$B!W$K$h$/;w$F$^$9$M!#e(BGroovye$B$NNc$K$h$k$H!"0c$$$O$3$&!'e(B
e$B!v!Ve(B.&e$B!W$O:G=i$KDj5A$5$l$?%a%=%C%I$r%j%?!<%s$9$k!#e(B
e$B!v!Ve(BObject#methode$B!W$O:#Dj5A$5$l$F$$$k%a%=%C%I$r%j%?!<%s$9$k!#e(B
e$B$=$&$$$&;v$G$9$h$M!#e(B

e$B!Ve(B.&e$B!W$,Lr$KN)$D;v>p$O$h$/$o$+$j$^$;$s$,!"?7$?$J1i;;;R$r;H$&I,MW$O$J$$$H;W$$$^$9!#e(BObjecte$B$N%a%=%C%I$NJ}!Je(BObject#first_method_definitione$B$H$+!K$,3Z$J$s$8$c$J$$$G$9$+!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:31448] Ruby’s (new) Bizarre Operator(s)”
on Fri, 17 Aug 2007 06:27:07 +0900, Nobuyoshi N.
[email protected] writes:

|Matzにっき(2007-08-06)
|
|?.e$B$O$$$m$$$m$H$+$V$k$N$G!"e(B.?e$B$He(B.&e$B$K$7$F$_$^$7$?!#e(B

e$B$3$&$7$F$_$k$H!"e(Bsave
navigatione$B$C$Fe(BRubye$BE*$K$O$I$&$J$s$G$7$ge(B
e$B$&$M!#e(B

a.?b(args)

e$B$O!"$b$7$+$9$k$He(B

((a == nil) ? nil : a.b(args))

e$B$h$j$be(B

a.b(args) rescue nil

e$B$NJ}$,;H$$$d$9$$$+$b$7$l$^$;$s!#$"!“C1$J$ke(Brescuee$B$@$He(B
NameErrore$B$r=&$o$J$$$+!#$^!”$=$NJU$OE,Ev$K!#e(B

e$B!Ve(B.&e$B!W$O7k9=M_$7$$5$$,$7$^$7$?!#B>$N?M$O$I$&;W$&$s$G$7$g$&$+!#e(B
e$B$5$i$KJ8K!$rJ#;($K$9$k$3$H$X$NDq9346$OM}2r$G$-$^$9!#e(B

On Sun, 19 Aug 2007 12:04:51 +0900
In article [email protected]
[[ruby-dev:31498] Re: Ruby’s (new) Bizarre Operator(s)]
eklerni [email protected] wrote:

From:eklerni

((a == nil) ? nil : a.b(args))
e$B$h$j$be(B

a.b(args) rescue nil

e$B$NJ}$,;H$$$d$9$$$+$b$7$l$^$;$s!#e(B
e$B$D$$$Ke(BRubye$B$G$be(BMaybee$B%b%J%I$,;H$($k$h$&$K!&!&!&e(B
rescuee$B$rMQ$$$k>l9g$b!"e(BNameErrore$B0J30$N%(%i!<$OJdB-$7$J$$$[$&$,$$$$$H;W$$e(B
e$B$^$9!#!J%P%0$N1#JC$,5/$3$k$?$a!Ke(B

NameError e$B$bJdB-$7$J$$J}$,$$$$$H;W$$$^$9!#e(B

b() e$B$NCf$Ge(Btypoe$B$7$F$?$j$7$?$H$-$K$d$C$Q$jNc30$,1#JC$5$l$^$9!De(B

-d e$BIU$-$G5/F0$7$J$$8B$j860x$,$o$+$i$J$/$FG:$`$H$$$&!#e(B

e$B;dE*$K$Oe(B a && a.b(args) e$B$H$$$&I=5-$rB?MQ$7$F$^$9!#e(B

Yuguie$B$H$$$$$^$9!#e(B

07/08/20 e$B$Ke(B Tietew[email protected]
e$B$5$s$O=q$-$^$7$?e(B:

e$B;dE*$K$Oe(B a && a.b(args) e$B$H$$$&I=5-$rB?MQ$7$F$^$9!#e(B

e$B$o$?$7$be(B
obj and obj.method(args)
e$B$J$s$F$N$r$h$/=q$-$^$9$M!#$b$&2?I42s$H=q$$$F$k$G$7$g$&!#e(B
e$B$?$@!“$3$l$r=q$/$H$-$Ke(Bnile$B$,56$KI>2A$5$l$k$3$H$J$s$+$r4^$a$FL$$@$K%3%s%^2?IC$+9M$($k$s$G$9$h$M!#e(Bobje$B$Ne(Bnile$B$He(Bobj.methode$B$NLa$jCM$O0lHL$K$O%I%a%$%s$,0[$J$k$N$Ke(Bobje$B$,e(Bnile$B$G$”$k$3$H$r;H$$$^$o$7$F$$$k$3$H$N0cOB46$KM3Mh$9$k$H;W$$$^$9!#e(B

e$B$=$&$$$C$?$b$?$D$-46$rM^$($FM%$7$$J8K!$r7A:n$k$H$$$&0UL#$G$Oe(B .?
e$B$K$b0U5A$,$"$k$N$+$b$7$l$^$;$s!#e(B

e$B0lJ}!“e(B.&e$B$K4X$7$F$OK\Ev$Ke(BObject#methode$B$NF15A8l$G$”$k$J$i$P0UL#$,$"$k$H;W$($J$+$C$?$j$7$^$9!#e(B

From:eklerni

NameError e$B$bJdB-$7$J$$J}$,$$$$$H;W$$$^$9!#e(B

be$B%a%=%C%I$,$J$$$H$-$@$1JdB-$9$k$3$H$K$9$k$H!"e(B
((a.respond_to? :b) ? a.b(args) : nil)
e$B$3$s$J46$8$G$9$+$M!#$3$N>l9ge(B
((a == nil) ? nil : a.b(args))
e$B$HHf$Y$k$He(Bnile$B$,H?1~$G$-$k%a%=%C%I!“Nc$($Pe(B nil.?to_s e$B$,e(B
“” e$B$He(B nil e$B$I$C$Ae(B
e$B$rJV$9$+!”$H$$$&0c$$$K$J$j$^$9!#e(B
#e$BAGD>$Ke(B==nile$B$N$[$&$,$o$+$j$d$9$$$+$be(B

e$B;dE*$K$Oe(B a && a.b(args) e$B$H$$$&I=5-$rB?MQ$7$F$^$9!#e(B

e$B%a%=%C%I%A%’!<%s$,=q$-$d$9$/$J$k$N$,$&$l$7$$e(B^^
a.?b(args1).?c(args2).?d(args3)

From:eklerni

((a == nil) ? nil : a.b(args))
e$B$h$j$be(B

a.b(args) rescue nil

e$B$NJ}$,;H$$$d$9$$$+$b$7$l$^$;$s!#e(B
e$B$D$$$Ke(BRubye$B$G$be(BMaybee$B%b%J%I$,;H$($k$h$&$K!&!&!&e(B
rescuee$B$rMQ$$$k>l9g$b!"e(BNameErrore$B0J30$N%(%i!<$OJdB-$7$J$$$[$&$,$$$$$H;W$$e(B
e$B$^$9!#!J%P%0$N1#JC$,5/$3$k$?$a!Ke(B
e$B!Ve(B.&e$B!W$O7k9=M_$7$$5$$,$7$^$7$?!#B>$N?M$O$I$&;W$&$s$G$7$g$&$+!#e(B
e$B$5$i$KJ8K!$rJ#;($K$9$k$3$H$X$NDq9346$OM}2r$G$-$^$9!#e(B

e$B%P%s%5%s$G$9!#e(B
e$B$3$N!Ve(B.&e$B!W$O!Ve(BObject#methode$B!W$K$h$/;w$F$^$9$M!#e(BGroovye$B$NNc$K$h$k$H!"0c$$$O$3$&!'e(B
e$B!v!Ve(B.&e$B!W$O:G=i$KDj5A$5$l$?%a%=%C%I$r%j%?!<%s$9$k!#e(B
e$B!v!Ve(BObject#methode$B!W$O:#Dj5A$5$l$F$$$k%a%=%C%I$r%j%?!<%s$9$k!#e(B
e$B$=$&$$$&;v$G$9$h$M!#e(B

e$BNc$G$O8e$H$+@h$H$+$G$O$J$/!“e(Bmethode$B%a%=%C%I$H!”$=$l$HF1L>$N%W%m%Q%F%#$rDje(B
e$B5A$7$F$$$k$@$1$G$O$J$$$G$7$g$&$+!)e(B
e$B!Je(B.&e$B$O%a%=%C%I%/%m!<%8%c!<$NJ}$rJV$9!Ke(B

e$B:#9M$($F$$$ke(B(Rubye$B$Ne(B).&e$B$Oe(BObject#methode$B$NJLL>!JCV492DG=$J$b$N!K$@$HG’<1$7e(B
e$B$F$$$k$N$G$9$,!“e(B
e$B$”$C$F$$$k$G$7$g$&$+!)e(B >e$B$^$D$b$H$5$se(B
e$B4JJX$5$O7k9=%"%C%W$9$k$H;W$&$N$G$9$,!“e(B
e$B%a%=%C%I$X%W%m%C%/$rEO$90z?t$N5-K!e(B &proc
e$B$H$NHyL/$J:90[$,:.Mp$r>7$-$=$&e(B
e$B$G$9!#e(B
*
&proce$B$@$He(B"e$B%W%m%C%/%%V%8%’%/%H$KJQ49$7$F%9%?%C%/$K>h$C$1$ke(B"e$B$J$N$Ke(B
a.&methode$B$@$He(B"e$B%a%=%C%I%
%V%8%’%/%H$rJV$9e(B”

  • method(self.&foo) e$B$He(B method(&foo)
    e$B$,!J8+$?L$KH?$7$F!K0c$&$b$N$r$"$i$o$9!#e(B
  • e$B%a%=%C%I0z?t$Ke(B &a.&method e$B$H=q$/$H$3$m$re(B a.&method
    e$B$H$+e(B &a.method e$B$H=qe(B
    e$B$$$F$7$^$$$=$&!#e(B

e$B$J$+$@$G$9!#e(B

At Mon, 20 Aug 2007 18:38:09 +0900,
Yugui wrote in [ruby-dev:31523]:

e$B0lJ}!“e(B.&e$B$K4X$7$F$OK\Ev$Ke(BObject#methode$B$NF15A8l$G$”$k$J$i$P0UL#$,$"$k$H;W$($J$+$C$?$j$7$^$9!#e(B

e$B%*!<%P!<%i%$%IITG=$G$"$k!"$H$$$&0UL#$O$"$k$H;W$$$^$9!#e(B

e$B$J$+$@$G$9!#e(B

At Mon, 20 Aug 2007 19:53:02 +0900,
eklerni wrote in [ruby-dev:31526]:

NameError e$B$bJdB-$7$J$$J}$,$$$$$H;W$$$^$9!#e(B

be$B%a%=%C%I$,$J$$$H$-$@$1JdB-$9$k$3$H$K$9$k$H!"e(B
((a.respond_to? :b) ? a.b(args) : nil)
e$B$3$s$J46$8$G$9$+$M!#$3$N>l9ge(B
((a == nil) ? nil : a.b(args))
e$B$HHf$Y$k$He(Bnile$B$,H?1~$G$-$k%a%=%C%I!“Nc$($Pe(B nil.?to_s e$B$,e(B “” e$B$He(B nil e$B$I$C$Ae(B
e$B$rJV$9$+!”$H$$$&0c$$$K$J$j$^$9!#e(B

e$B$I$C$A$,$$$$$G$7$g$&$M!#e(Brespond_to?e$B$r;H$&$J$i0lJ8DI2C$9$k$@$1$Ge(B
e$B$9$,!#e(B

e$B;dE*$K$Oe(B a && a.b(args) e$B$H$$$&I=5-$rB?MQ$7$F$^$9!#e(B

e$B%a%=%C%I%A%’!<%s$,=q$-$d$9$/$J$k$N$,$&$l$7$$e(B^^
a.?b(args1).?c(args2).?d(args3)

e$B0l;~JQ?t$r;H$o$:$K$9$`$h$&$K$9$k$N$,L\E*$G$9$+$i!#e(B

From:eklerni

e$B$HHf$Y$k$He(Bnile$B$,H?1~$G$-$k%a%=%C%I!“Nc$($Pe(B nil.?to_s e$B$,e(B “” e$B$He(B nil e$B$I$C$Ae(B
e$B$rJV$9$+!”$H$$$&0c$$$K$J$j$^$9!#e(B

e$B$I$C$A$,$$$$$G$7$g$&$M!#e(Brespond_to?e$B$r;H$&$J$i0lJ8DI2C$9$k$@$1$Ge(B
e$B$9$,!#e(B

e$B8e$+$i5$$E$$$?$s$G$9$,!"e(B Xtal e$B$G$Oe(B respond_to?
e$B7A<0!J$N$h$&$J$b$N!K$r:Ne(B
e$BMQ$7$F$$$k$h$&$G$9$M!#e(B

e$B$I$C$A$,$$$$$+$O$J$s$H$b$$$($^$;$s$,!"e(B

a.b(args) rescue nil

e$B$NJ}$,;H$$$d$9$$$+$b$7$l$^$;$s!#$"!“C1$J$ke(Brescuee$B$@$He(B
NameErrore$B$r=&$o$J$$$+!#$^!”$=$NJU$OE,Ev$K!#e(B

respond_to? e$B7A<0$Oe(B rescue
e$B7A<0$Ne(B"e$B;H$$$d$9$5e(B"e$B$r$"$kDxEY4^$s$G$$$k$h$&$K;We(B
e$B$($^$9!#!J1~MQHO0O$N9-$5$H$$$&0UL#$G!Ke(B