# About Extending Systax

**URL:** <https://www.ruby-forum.com/t/about-extending-systax/102067>\
**Category:** Ruby\
**Created:** [February 7, 2006, 6:53pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067 "2006-02-07T18:53:56Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 7, 2006, 6:53pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/1 "2006-02-07T18:53:56Z")

</div>

Hi!

A friend of mine challenged me with Smalltalk.  
He’s a big fan of Smalltalk.  
He asked me what I can do if I want to add “try ~ finally ~” systax in  
Ruby.  
Yes, we already have “begin ~ ensure ~”.  
But he asked me whether Ruby is flexible enough to extend such a thing  
without changing the language itself.  
He said that Smalltalk doesn’t have “try ~ finally ~” in the language  
but can be defined without changing the language.

Personally, I don’t think such flexibility is really needed.  
However, I want to defend Ruby.  
How would you react such an attack?

Disclaimer: This post is not for language flame war but for better  
understanding of Ruby.

Thanks.

Sam

---

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 7, 2006, 7:23pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/2 "2006-02-07T19:23:23Z")

</div>

Sam K. wrote:

> Hi!
> 
> A friend of mine challenged me with Smalltalk.  
> He’s a big fan of Smalltalk.  
> He asked me what I can do if I want to add “try ~ finally ~” systax in  
> Ruby.  
> Yes, we already have “begin ~ ensure ~”.  
> But he asked me whether Ruby is flexible enough to extend such a thing  
> without changing the language itself.  
> He said that Smalltalk doesn’t have “try ~ finally ~” in the language  
> but can be defined without changing the language.
> 
> Personally, I don’t think such flexibility is really needed.  
> However, I want to defend Ruby.  
> How would you react such an attack?

There are several ways this could be done … here is one:

class TryFinally  
def initialize(block)  
@block = block  
end  
def finally  
@block.call  
ensure  
yield  
end  
end

def try(&block)  
TryFinally.new(block)  
end

Usage:

try {  
puts “Trying”  
fail “oops”  
}.finally {  
puts “Always printed”  
}

It is a bit little easier in Smalltalk because of the use of keywords in  
an argument list, but still quite doable in Ruby.

–  
– Jim W.

---

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 7, 2006, 7:41pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/3 "2006-02-07T19:41:17Z")

</div>

DÅ?a Utorok 07 FebruÃ¡r 2006 18:53 Sam K. napÃ­sal:

> but can be defined without changing the language.
> 
> Personally, I don’t think such flexibility is really needed.  
> However, I want to defend Ruby.  
> How would you react such an attack?

Well, my first reply would be that noone really understands how the hell  
Smalltalk exceptions really work anyway - last time I played around with  
ST,  
I remember an ifCurtailed: method (remembered because I have no idea  
what  
“curtailed” means), some four variants on that one, and then at least  
two  
more basic ifSomething: methods plus variants that had something to do  
with  
exception handling. The second reply would be that custom syntax  
features are  
only marginally useful in production code and tend to be rather  
confusing.

And of course to top the whole thing off, yes, you can implement  
something  
like custom extension handling syntax.

As to the actual implementation, I can at best think of a solution that  
wraps  
around begin / rescue / ensure - you still have to have some support for  
nonlocal exits from the runtime, and ruby doesn’t quite let you  
manipulate  
the interpreter at runtime as you can a Smalltalk one. And I don’t feel  
like  
learning interpreter hacking just for this example to make myself some  
low  
level access to the interpreter stack.

Yaaanyways, here cometh the (probably incorrect and definately flaky)  
code:

```
def try_catch_finally(try_block, catch_block, finally_block)
	begin
		try_block[]
	rescue => ex
		catch_block[ex]
	ensure
		finally_block[]
	end
end

try_catch_finally proc {
	puts "foo"
	raise
},
proc { | ex |
	puts "bar"
	puts ex.class.name
},
proc {
	puts "quux"
}

```

If that’s not enough, accuse your friend of being a nitpick 😜

---

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 7, 2006, 8:55pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/4 "2006-02-07T20:55:03Z")

</div>

nice

Jim W. wrote:

> Sam K. wrote:
> 
> > Hi!

[snip]

---

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 7, 2006, 7:58pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/5 "2006-02-07T19:58:08Z")

</div>

Quoting David V. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> As to the actual implementation, I can at best think of a  
> solution that wraps around begin / rescue / ensure - you still  
> have to have some support for nonlocal exits from the runtime,

You could use continutations. Although they’re more general, you  
can still use them in much the same fashion as you would  
setjmp/longjmp in C.

-mental

---

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 7, 2006, 9:38pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/6 "2006-02-07T21:38:22Z")

</div>

On Wed, Feb 08, 2006 at 03:54:39AM +0900, removed\_email\_address@domain.invalid wrote:

> You could use continutations.

Indeed. With continuations you can build your own try/finally that  
doesn’t use the built in ruby begin/rescue at all:

$cc\_stack = []

# takes two procs

def my\_try(body, finally)  
if callcc {|cc| $cc\_stack \<\< cc}  
body.call  
$cc\_stack.pop  
end  
finally.call  
end

def my\_throw  
$cc\_stack.pop.call  
end

You could play some tricks to get a nicer syntax, but that’s the  
general idea.

-Ed

---

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 7, 2006, 10:06pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/7 "2006-02-07T22:06:18Z")

</div>

Jim W. wrote:

> > He said that Smalltalk doesn’t have “try ~ finally ~” in the language  
> > @block = block  
> > end  
> > It is a bit little easier in Smalltalk because of the use of keywords in  
> > an argument list, but still quite doable in Ruby.

This is nice.  
But my intention is not to make a new syntax that does the same thing.  
Let’s assume that there’s no _ensure_ syntax in Ruby.

Sam

---

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 8, 2006, 1:10am UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/8 "2006-02-08T01:10:48Z")

</div>

Dave T. et al have discussed this back in 2001,  
[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/20991](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/20991)

they use ‘ensure’ in their solution, but it’s an interesting read  
anyway.

---

<div class="post-metadata">

**Author:** ![ssk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/82dd89/32.png) [@ssk](https://www.ruby-forum.com/u/ssk)\
**Post date:** [February 7, 2006, 11:19pm UTC](https://www.ruby-forum.com/t/about-extending-systax/102067/9 "2006-02-07T23:19:58Z")

</div>

Here’s another go at it using continuations:

% cat try\_catch\_throw.rb  
class Flow  
def initialize(parent = nil)  
@exceptions = []  
@parent = parent  
@uncaught\_exception = nil  
end  
def try(&block)  
@try\_block = block  
end

def throw(exception)  
caught = @exceptions.each do |key, value|  
if key === exception  
value.call(exception)  
break true  
end  
end

```
 unless caught == true
   if @parent
     @parent.throw(exception)
   else
     @uncaught_exception = exception
   end
 end
 @cc.call

```

end

def finally(&block)  
@finally = block  
self  
end

def catch(exception, &block)  
@exceptions \<\< [exception, block]  
self  
end  
def go  
callcc { |@cc| @try\_block.call }  
if @finally  
@finally.call  
end  
if @uncaught\_exception  
STDERR.puts “Uncaught exception: #{@uncaught\_exception}”  
exit(1)  
end  
end

end

% cat test\_flow.rb  
require ‘try\_catch\_throw’

handling2 = Flow.new  
handling2.try {  
handling3 = Flow.new(handling2)  
handling3.try {  
puts “Nested try”  
handling3.throw “ERROR! in handling3”  
}  
handling3.go  
}

handling2.catch(String) do |exception|  
puts “handling2 Caught exception: #{exception}”  
end

handling2.go

handling = Flow.new

handling.try {  
puts “Hello”  
handling.throw “ERROR!”  
puts “World”  
}  
handling.finally {  
puts “Finally”  
}

handling.go

% ruby test\_flow.rb  
Nested try  
handling2 Caught exception: ERROR! in handling3  
Hello  
Finally  
Uncaught exception: ERROR!

At first I tried to do it without continuations but I couldn’t think  
of a way to do so. Also the nesting is explicit which has the  
advantage of not using global vars and the disadvantage of excessive  
typing.
