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

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&gt;

···

On Sat, Feb 16, 2013 at 4:49 AM, WILLS, JAMAL A <jw1496@att.com> wrote:

I think GOTO gets a bad rap. Actually, I find the COMEFROM command far
more terrifying. It's mentioned in the comments...

Jamal

-----Original Message-----
From: Ryan Victory [mailto:ryan@raptormail.net]
Sent: Friday, February 15, 2013 12:03 PM
To: ruby-talk ML
Subject: Re: so, what's the proper way to replace funcionality of GOTO ?

I did consider jokingly showing the "enable jokes" compiler flag that
turned on the __goto__ method...I'm actually slightly horrified that
Ruby has anything resembling goto for hopping around in code. I'll
concede that I did not know about this, however I'll stand by the idea
that it's terrible coding practice (except for in very particular
circumstances where goto is the most elegant solution).

Either way, your original suggestion is just bad advice. I'll stand by
that.

-Ryan
On 2/15/13 10:56 AM, Love U Ruby wrote:
> Ryan Victory wrote in post #1097114:
>> Love U Ruby: I'm really not sure what you meant by that response, but
>> it's irrelevant and inaccurate (there is no catch in Ruby, it's
>> rescue)...
>>
> before going to challenge other you should "GOOGLE" - here I did for
> you.
>
> Please read it : http://www.devalot.com/articles/2012/03/ruby-goto
>

When one is implementing a command-line interface like this one, and you don't want to have a dozen of two-line methods, judicious use of throw..catch is a reasonably nice solution.

Hi all,

Well, considering the OP's question was "What's the /proper/ way to
replace functionality of GOTO" (emphasis mine), I'd say that pretty much
any rubyist would agree that a goto like structure doesn't belong in
ruby code unless it truly is the most elegant solution (escaping
multiple nested loops for example). Not that it really matters either
way, this question has been answered by somebody else and I believe the
OP is satisfied.

-Ryan

I just wanted to say that I think Ryan is attempting to steer the OP in the right direction, which is to prefer modern, sensible structures where possible that don't have the numerous drawbacks that GOTO is saddled with.

Reducing it to a car analogy, as all things do, :wink: consider if someone familiar with driving an auto was asking how to make a manual move, and if you accelerated with the same pedal. Someone like Ryan steps in and very wisely says that you might want to figure out the clutch first, since the car isn't going anywhere without changing gears. Someone else points out that the clutch won't move the car at all, and that he is wrong. Sure, that's technically correct, he would be wrong, but the point is that the real problem that should be addressed involves understanding the role the clutch also plays.

I also want to add that I *also* had absolutely *no* idea that Ruby had anything like GOTO and was similarly thrown (pun intended) by the mention of catch/throw. I've not had a need for it yet, myself. It's simultaneously disturbing, interesting, and scary to know this exists. :wink:

I started out software development around a couple of decades ago with BASIC, and then later assembly language, before moving on to Ada, C, and C++. Anyone with a similar background can imagine how much unlearning *that* required. :wink:

Ryan's advice is good, especially for someone in that position. Ryan, like me, just didn't know about Ruby catch/throw. It's still good advice. I just wanted to make sure at least one person has acknowledged this.

Cheers,
Garth

···

On 16/02/13 11:16, Ryan Victory wrote:

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

http://www.ruby-doc.org/core-2.0/Continuation.html

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

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.

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 3:08 PM, Stu <stu@rubyprogrammer.net> wrote:

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

Class: Continuation (Ruby 2.0.0)

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

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

···

On Wed, Feb 20, 2013 at 1:18 AM, Timothy Gregory <tigre7t@gmail.com> wrote:

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