[from BASIC to Ruby] so, what's the proper way to replace funcionality of GOTO?

people, people.

Every time your code takes a branch, loops the loop, takes an early
return, etc, it’s executing a “goto”.

Commonly used goto-es:
next
continue
break
return

The switch from a semi-unstructured language to a high-structured,
quasi functional, oo language can be as difficult as learning
idiomatic 15th century classical French for some.

The heart of a text-based, menu-driven task system is the
Read-Eval-Print loop (REPL). The basic arrangement for this in most
every structured language is so:

#!/usr/bin/env ruby

Read-Eval-Print Loop basic command processor

def show_menu
puts “some menu”
end

def get_response
:done
end

def perform(request)
puts request.to_s
request
end

loop do
show_menu
request = get_response
result = perform(request)
break if result == :done
end

The next vital part of the tiny app will be how you want to link your
menu items, valid responses, and tasks. Thinking data structures here.
The simplest thing I can think of is a hash, where the key is the
response, and the value is a hash containing an entry for the menu
item, and an entry for the procedure/method to execute.

@commands = {
‘1’ => {
:menu => “Thing 1”,
:action => lambda {thing1}},
‘2’ => {
:menu => “Thing 2”,
:action => lambda {thing2}},
‘0’ => {
:menu => “Quit”,
:action => lambda { :done }}

}

@commands” is an /instance variable/ with the scope of the current
instance, in this case of the global class Object. We’re not actually
doing anything OO here, but using ruby idioms to get something done.
In this context, where there are no classes, it acts pretty much like
a global.

“lambda” defines an anonymous procedure, which will be handy when we
get to fleshing out the perform method from above.

“thing1” and “thing2” are going to be where you build your tasks. For
now, they’re just place-holder methods:

def thing1
puts “THING ONE RULES!!”
end

def thing2
puts “THING TWO FTW!”
end

The last menu option merely returns the symbol value “:done”, which is
used to exit your REPL.

Now we can look at how to show the menu. Given the above @commands
data structure, this becomes trivial:

def show_menu
@commands.each do |key, value|
puts “#{value[:menu]} - Press #{key}”
end
end

This says to loop through each of the hash’s members, and using the
key and value, display the action, which is in the value’s :menu item,
and the input needed, which is the entry’s key.

Getting the response is also rather trivial:

def get_response
gets.chomp.downcase
end

This retrieves a line from input (user types the appropriate choice
and presses return), then removes the trailing white space, and
converts it to lower case. In Ruby, the last thing evaluated by a
method is what gets returned as the result of that method.

Now, however, we need to add something more to our REPL. What happens
if the user type “XyZzY!!” ? The program as it stands will give some
kind of error and die. Instead, we need to validate what the user
typed in and give an appropriate response if we don’t recognize it.

So, to our REPL, we add:

loop do
show_menu
request = get_response
if valid?(request)
result = perform(request)
else
puts “Unknown request #{request}. Try again”
result = nil
end

break if result == :done
end

And the associated “valid?” method:

def valid?(response)
@commands.keys.include?(response)
end

Which returns true if the value passed in, “response” is included in
the array of keys in @commands. This sort of thing is called
“chaining” in Ruby, and can be quite expressive, and is what gives
Ruby some of it’s functional programming flavour.

Okay, now we should have a complete program:

#!/usr/bin/env ruby

Read-Eval-Print Loop basic command processor

@commands = {
‘1’ => {
:menu => “Thing 1”,
:action => lambda {thing1}},
‘2’ => {
:menu => “Thing 2”,
:action => lambda {thing2}},
‘0’ => {
:menu => “Quit”,
:action => lambda { :done }}

}

def thing1
puts “THING ONE RULES!!”
end

def thing2
puts “THING TWO FTW!”
end

def show_menu
@commands.each do |key, value|
puts “#{value[:menu]} - Press #{key}”
end
end

def get_response
gets.chomp!.downcase
end

def valid?(response)
@commands.keys.include?(response)
end

def perform(request)
@commands[request][:action].call
end

loop do
show_menu
request = get_response
if valid?(request)
result = perform(request)
else
puts “Unknown request #{request}. Try again”
result = nil
end

break if result == :done
end

If you load this into irb, you can see how it works:

1.9.3-head :010 > load ‘repl.rb’
Thing 1 - Press 1
Thing 2 - Press 2
Quit - Press 0
1
THING ONE RULES!!
Thing 1 - Press 1
Thing 2 - Press 2
Quit - Press 0
1
THING ONE RULES!!
Thing 1 - Press 1
Thing 2 - Press 2
Quit - Press 0
2
THING TWO FTW!
Thing 1 - Press 1
Thing 2 - Press 2
Quit - Press 0
2
THING TWO FTW!
Thing 1 - Press 1
Thing 2 - Press 2
Quit - Press 0
1
THING ONE RULES!!
Thing 1 - Press 1
Thing 2 - Press 2
Quit - Press 0
2
THING TWO FTW!
Thing 1 - Press 1
Thing 2 - Press 2
Quit - Press 0
0
=> true
1.9.3-head :011 >

The one thing I can see missing from your original BASIC version is
that this one does not do a clear-screen at the top of each loop. That
actually gets a bit more complicated, because you have to mess with
terminal control sequences. That’s beyond my knowledge.

On Sat, Feb 16, 2013 at 2:03 PM, Stu P. D’naim [email protected]
wrote:

hash inside hash menus, interesting, same as Robert K.'s example …

There is one difference: I created a class while the other example
uses nested Hashes. Frankly, since with Ruby it is so easy to create
classes, I do not understand why people go about to suggest creating
nested structures of Hash and Array combinations. Look at this
example:

On Sat, Feb 16, 2013 at 8:30 AM, tamouse mailing lists
[email protected] wrote:

}

It shows quite obviously that there are “things” which always have a
“menu” (or rather a name) and an “action”. Why then not just create a
class for that?

Thing = Struct.new :menu, :action

etc.

thank you all guys, now I have more than enough ideas how to start my
script

Good!

Kind regards

robert

i recall the Amiga thrived on tons of GOTO 's
thrashed to the point where it was almost every third word on the page

there is a bunch of goto’s in ruby-parse.y lines 10203-10250 on github
parse.y#L10203 https://github.com/ruby/ruby/blob/trunk/parse.y#L10203

On Sat, Feb 16, 2013 at 8:20 AM, Robert K.
[email protected] wrote:

[email protected] wrote:

thank you all guys, now I have more than enough ideas how to start my
script

Good!

Kind regards

robert

All very true. My initial thought was to refrain from jumping directly
Classes, but it’s probably just as well.

callcc is one way to do a functional programming style goto statement

Though it’s obvious that goto is considered a taboo at the current
state of the art. There are always another way to deal with
conditional to executed code. goto statements became obsoleted by
simply calling a function which could almost be viewed as a bookmark.
This removed the code from the data which goto relied on line number
for procedural representation over function verb.

None the less I enjoyed creating infinite loops on my apple ][e as a
child. Also recall the ? would expand to PRINT which I believe is now
simply a easter egg of modern visual basic.

]LIST

10 PRINT “HELLO, WORLD!”
20 GOTO 10

OP your going to love ruby. It really brings back the old “joy of
programming” we had 20 years ago =).

~Stu

hey thanks for the heads up
i really like ruby you can read it and tell what it is intended to do

On Wed, Feb 20, 2013 at 1:18 AM, Timothy G. [email protected]
wrote:

hey thanks for the heads up
i really like ruby you can read it and tell what it is intended to do

You can also teach it to read and parse what you intend it to do.