# Catch without a tag argument

**URL:** <https://www.ruby-forum.com/t/catch-without-a-tag-argument/112732>\
**Category:** Development\
**Created:** [August 22, 2007, 5:34pm UTC](https://www.ruby-forum.com/t/catch-without-a-tag-argument/112732 "2007-08-22T17:34:43Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [August 22, 2007, 5:34pm UTC](https://www.ruby-forum.com/t/catch-without-a-tag-argument/112732/1 "2007-08-22T17:34:43Z")

</div>

matzruby e$B$K$"$k!"0z?t$J$7$Ge(B catch e$B$,8F$Y$k5!G=$Oe(B 1.9  
e$B$K$OF~e(B  
e$B$i$J$$$N$G$7$g$&$+!#e(B

% ./ruby -ve ‘p catch {|t| throw t, 1 }’  
ruby 1.9.0 (2007-04-20 patchlevel 0) [i686-linux] - matz  
1

% ./ruby -ve ‘p catch {|t| throw t, 1 }’  
ruby 1.9.0 (2007-08-22 patchlevel 0) [i686-linux]  
-e:1:in `catch': wrong number of arguments(0 for 1) (ArgumentError) from -e:1:in`’

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [August 23, 2007, 2:36am UTC](https://www.ruby-forum.com/t/catch-without-a-tag-argument/112732/2 "2007-08-23T02:36:34Z")

</div>

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

In message “Re: [ruby-dev:31615] Re: catch without a tag argument”  
on Thu, 23 Aug 2007 08:03:19 +0900, Nobuyoshi N.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

|At Thu, 23 Aug 2007 00:34:12 +0900,  
|Tanaka A. wrote in [ruby-dev:31609]:  
|\> matzruby e$B$K$"$k!"0z?t$J$7$Ge(B catch e$B$,8F$Y$k5!G=$Oe(B 1.9 e$B$K$OF~e(B  
|\> e$B$i$J$$$N$G$7$g$&$+!#e(B  
|  
|e$B$$$m$$$m$HJQ$o$C$F$k$h$&$G$=$N$^$^$G$OF0$-$^$;$s$G$7$?!#e(B

e$BF~$l$J$$M}M3$O$J$$$N$G$9$,!“$=$N$^$^J|CV$7$F$^$7$?!#$J$+$@$5e(B  
e$B$s!”%3%\_%C%H$7$F$/$@$5$$!#e(B

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [August 23, 2007, 1:04am UTC](https://www.ruby-forum.com/t/catch-without-a-tag-argument/112732/3 "2007-08-23T01:04:28Z")

</div>

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

At Thu, 23 Aug 2007 00:34:12 +0900,  
Tanaka A. wrote in [ruby-dev:31609]:

> matzruby e$B$K$"$k!"0z?t$J$7$Ge(B catch e$B$,8F$Y$k5!G=$Oe(B 1.9 e$B$K$OF~e(B  
> e$B$i$J$$$N$G$7$g$&$+!#e(B

e$B$$$m$$$m$HJQ$o$C$F$k$h$&$G$=$N$^$^$G$OF0$-$^$;$s$G$7$?!#e(B

# Index: eval\_jump.ci

— eval\_jump.ci (revision 13128)  
+++ eval\_jump.ci (working copy)  
@@ -6,5 +6,6 @@  
#include “eval\_intern.h”

-NORETURN(static VALUE rb\_f\_throw \_((int, VALUE \*)));  
+NORETURN(static VALUE rb\_f\_throw(int, VALUE \*));  
+int rb\_vm\_catch\_p(VALUE dst, VALUE tag);

/\*  
@@ -24,25 +25,8 @@ rb\_f\_throw(int argc, VALUE \*argv)  
{  
VALUE tag, value;

- rb\_thread\_t \*th = GET\_THREAD();

- struct rb\_vm\_tag \*tt = th-\>tag;

- tag = ID2SYM(rb\_to\_id(tag));

- 
- while (tt) {

- if (tt-\>tag == tag) {

- 

```
 tt->retval = value;

```

- 

```
 break;

```

- }

- tt = tt-\>prev;

- }

- if (!tt) {

- rb\_name\_error(SYM2ID(tag), “uncaught throw `%s’”,

- 

```
     rb_id2name(SYM2ID(tag)));

```

- }

- rb\_trap\_restore\_mask();

- th-\>errinfo = tag;

- JUMP\_TAG(TAG\_THROW);

- rb\_throw\_obj(tag, value);  
#ifndef **GNUC**  
return Qnil; /\* not reached \*/  
@@ -53,14 +37,11 @@ void  
rb\_throw(const char \*tag, VALUE val)  
{

- VALUE argv[2];
- 
- argv[0] = ID2SYM(rb\_intern(tag));
- argv[1] = val;
- rb\_f\_throw(2, argv);

- rb\_throw\_obj(ID2SYM(rb\_intern(tag)), val);  
}

/\*

- call-seq:

- 
  - 

```
catch(symbol) {| | block } > obj

```

- 
  - 

```
catch(symbol) { block } => obj

```

- 
  - 

```
catch() {|tag| block } => obj

```

  - 
  - +catch+ executes its block. If a +throw+ is  
@@ -92,41 +73,22 @@ rb\_throw(const char \*tag, VALUE val)

static VALUE  
-rb\_f\_catch(VALUE dmy, VALUE tag)  
+rb\_f\_catch(int argc, VALUE \*argv)  
{

- int state;
- VALUE val = Qnil; /\* OK \*/
- rb\_thread\_t \*th = GET\_THREAD();
- 
- tag = ID2SYM(rb\_to\_id(tag));
- PUSH\_TAG();

- VALUE tag;

- th-\>tag-\>tag = tag;
- 
- if ((state = EXEC\_TAG()) == 0) {
- val = rb\_yield\_0(1, &tag);
- }
- else if (state == TAG\_THROW && th-\>errinfo == tag) {
- val = th-\>tag-\>retval;
- th-\>errinfo = Qnil;
- state = 0;

- rb\_scan\_args(argc, argv, “01”, &tag);
- if (argc == 0) {
- tag = Qundef;  
}

- POP\_TAG();
- if (state)
- JUMP\_TAG(state);
- 
- return val;  
-}
- 

-static VALUE  
-catch\_i(VALUE tag)  
-{

- return rb\_funcall(Qnil, rb\_intern(“catch”), 1, tag);

- return rb\_catch\_obj(tag, rb\_yield, Qnil);  
}

VALUE  
-rb\_catch(const char \*tag, VALUE (\*func)(), VALUE data)  
+rb\_catch(const char \*tag, VALUE (\*func)(ANYARGS), VALUE data)  
{

- return rb\_iterate((VALUE (\*)\_((VALUE)))catch\_i,  
ID2SYM(rb\_intern(tag)),
- 

```
     func, data);

```

- if (!tag) {
- return rb\_catch\_obj(Qundef, func, data);
- }
- return rb\_catch\_obj(ID2SYM(rb\_intern(tag)), func, data);  
}

@@ -277,5 +239,5 @@ void  
Init\_jump(void)  
{

- rb\_define\_global\_function(“catch”, rb\_f\_catch, 1);

- rb\_define\_global\_function(“catch”, rb\_f\_catch, -1);  
rb\_define\_global\_function(“throw”, rb\_f\_throw, -1);  
rb\_define\_global\_function(“at\_exit”, rb\_f\_at\_exit, 0);  
Index: vm.c  
===================================================================  
— vm.c (revision 13128)  
+++ vm.c (working copy)  
@@ -982,4 +995,76 @@ rb\_iter\_break()  
}

+static inline int  
+catching\_p(VALUE dst, VALUE tag)  
+{

- if (dst == tag) return Qtrue;
- if (SPECIAL\_CONST\_P(dst)) return Qfalse;
- if (BUILTIN\_TYPE(dst) != T\_NODE) return Qfalse;
- if (GET\_THROWOBJ\_STATE(dst) != TAG\_THROW) return Qfalse;
- if (GET\_THROWOBJ\_VAL(dst) != tag) return Qfalse;
- return Qtrue;  
+}
- 

+void  
+rb\_throw\_obj(VALUE tag, VALUE value)  
+{

- rb\_thread\_t \*th = GET\_THREAD();
- struct rb\_vm\_tag \*tt = th-\>tag;
- 
- while (tt) {
- if (catching\_p(tt-\>tag, tag)) {
- 

```
 tag = tt->tag;

```

- 

```
 tt->retval = value;

```

- 

```
 break;

```

- }
- tt = tt-\>prev;
- }
- if (!tt) {
- VALUE argv[2];
- argv[0] = rb\_sprintf(“uncaught throw `%s’”,  
RSTRING\_PTR(rb\_obj\_as\_string(tag)));
- argv[1] = tag;
- rb\_exc\_raise(rb\_class\_new\_instance(2, argv, rb\_eNameError));
- }
- rb\_trap\_restore\_mask();
- th-\>errinfo = tag;
- TH\_JUMP\_TAG(th, TAG\_THROW);  
+#ifndef **GNUC**
- return Qnil; /\* not reached \*/  
+#endif  
+}
- 

+VALUE  
+rb\_catch\_obj(VALUE tag, VALUE (\*func)(ANYARGS), VALUE data)  
+{

- int state;
- VALUE val = Qnil; /\* OK \*/
- VALUE dest = tag;
- rb\_thread\_t \*th = GET\_THREAD();
- 
- if (tag == Qundef) {
- tag = rb\_obj\_alloc(rb\_cObject);
- dest = (VALUE)NEW\_THROW\_OBJECT(tag,  
GC\_GUARDED\_PTR\_REF(\*th-\>cfp-\>dfp),
- 

```
          TAG_THROW);

```

- }
- 
- TH\_PUSH\_TAG(th);
- 
- th-\>tag-\>tag = dest;
- 
- if ((state = EXEC\_TAG()) == 0) {
- val = (\*func)(tag, data);
- }
- else if (state == TAG\_THROW && th-\>errinfo == dest) {
- val = th-\>tag-\>retval;
- th-\>errinfo = Qnil;
- state = 0;
- }
- TH\_POP\_TAG();
- if (state)
- JUMP\_TAG(state);
- 
- return val;  
+}
- 

/\* optimization: redefine management \*/

# Index: include/ruby/ruby.h

— include/ruby/ruby.h (revision 13128)  
+++ include/ruby/ruby.h (working copy)  
@@ -723,5 +723,7 @@ VALUE rb\_rescue2(VALUE(_)(ANYARGS),VALUE  
VALUE rb\_ensure(VALUE(_)(ANYARGS),VALUE,VALUE(_)(ANYARGS),VALUE);  
VALUE rb\_catch(const char_,VALUE(_)(ANYARGS),VALUE);  
+VALUE rb\_catch\_obj(VALUE,VALUE(_)(ANYARGS),VALUE);  
NORETURN(void rb\_throw(const char\*,VALUE));  
+NORETURN(void rb\_throw\_obj(VALUE,VALUE));

VALUE rb\_require(const char\*);
