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

I need to make few scripts for tasks I do often manually, but last time
I programmed something was almost 20 years ago in high school, we used
some BASIC dialect. Since no one uses BASIC nowdays, I decided to give a
try to Ruby (I also tried Python, but it’s strict indentation is driving
me insane).

I watched Ruby Essentials Video from Lynda.com (twice), and I pretty
much understand almost all of it, but still, I’m having trouble to adapt
how to structure my programs (without using of GOTO)

Here’s a simple example written in FreeBASIC (it works)

Dim As Integer strKeyPress

menu_00:

CLS
PRINT “what do you desire:”
PRINT
PRINT “1 - open menu_01”
PRINT “2 - open menu_02”
PRINT “3 - open menu_03”
PRINT “4 - open menu_04”
PRINT “q - Quit”

REM is comment line, same as ’ … code for Q is 81, q = 113

Do
strKeyPress = GetKey
Loop Until strKeyPress <> 0

'49 represents number 1 on a keybord, and so on

if strKeyPress = 49 THEN
goto menu_01
elseif strKeyPress = 50 THEN
goto menu_02
elseif strKeyPress = 51 THEN
goto menu_03
elseif strKeyPress = 52 THEN
goto menu_04
elseif strKeyPress = 81 or strKeyPress = 113 THEN
goto programendshere
else
print
print “Wrong Choice, Try Again!”
sleep 1000

menu_00_endif:
end if

goto menu_00

menu_01:
cls
print
print “menu 01”
sleep 1000
goto menu_00_endif
menu_02:
cls
print
print “menu 02”
sleep 1000
goto menu_00_endif
menu_03:
cls
print
print “menu 03”
sleep 1000
goto menu_00_endif
menu_04:
cls
print
print “menu 04”
sleep 1000
goto menu_00_endif

programendshere:

End 0

So, what would be the best practice to make this work in modern
languages, like Ruby ? Here are some ideas I have, would be nice to know
if it’s good thinking or wrong:

1- make all menues part of a same Class, so I can use instance variables
(I will need to do some calculations)

2- define every menu as separate method, so you travel from root
menu_00 (method) → menu_01 (which is separate method) → … etc go
back and forth … #could this be memory demanding if there is too many
sub-menu branching ???

3- define every menu as separate method, but you DO NOT start new method
from INSIDE of other method. It goes something like this: menu_00
returns value to a loop, that value is name of sub-menu (menu_01,
separate method) … I’d then have to use →
method(name_of_returned_value).call()
This looks better than option #2, but my attempts to make it work so far
failed … not sure if it is even possible to achieve at all

4- every menu is separate method, but they only have puts “enter choice”
lines, no other code, and a $global variable which I will use later in
IF loops to detect inside which menu (method) I am:

if $global == “00” and userInputChoice == “1”
#if you are currently inside root menu 00, and user input is “1”
menu_01()
$global = “01”
… etc

I think this could easily work, though, might not look nice

So basically, I’d like to know which way should I go for, 2,3 or 4, or
there is maybe even something else? And, also is idea #1 ok ?

I hope this wasn’t too long to read for my first question here, starting
something new is always hardest part for me

Stu P. D’naim wrote in post #1097111:

I need to make few scripts for tasks I do often manually, but last time
I programmed something was almost 20 years ago in high school, we used
some BASIC dialect. Since no one uses BASIC nowdays, I decided to give a
try to Ruby (I also tried Python, but it’s strict indentation is driving
me insane).

I watched Ruby Essentials Video from Lynda.com (twice), and I pretty
much understand almost all of it, but still, I’m having trouble to adapt
how to structure my programs (without using of GOTO)

Here’s a simple example written in FreeBASIC (it works)

Dim As Integer strKeyPres

Yes, It has. You can try “catch - throw” in Ruby’s world.

Thanks

Ryan V. 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 : Ruby's catch/throw, goto's little brother - Devalot

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)…

To answer the OP’s question, you’d probably want to first pick up a good
book on Ruby (or one of the many tutorials online). You’re probably
going to want to look into first creating methods where you normally had
headers in your BASIC code and replacing the GOTO declarations with just
the method name. I’d also take a look at the “case…when” syntax to
replace your if statements. Switching to an object oriented language
from BASIC is tough but not impossible, especially if you’re just
replacing some utility scripts. I’m sure there’s a “menu” gem out there
too somewhere.

Hopefully that cleared up at least something,
Ryan V.

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

Ryan V. wrote in post #1097118:

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

OP asked is it there? I have given the reference to him- yes Ruby has. i
didn’t advice him to use that. So please don’t need to stand by. You
didn’t aware what Ruby has, so now you got it. That’s good.

chill…

Be careful saying “no one uses BASIC nowdays”. I have no doubt there is
a subset of people out there still using BASIC. =)

There is no one way to replace GOTO. GOTO is at the heart of many
structured control structures. What you need to do is think about what
you are trying to do and where you are trying to go when you are done.

In your code, you have: “goto menu_01”. After the sequence of
statements starting at the menu_01 label, you have: “goto
menu_00_endif”. If you returned from your sequence to the goto, you
would have a subroutine. I’m not familiar with FreeBASIC, but in
Commodore BASIC, you could replace your GOTO with GOSUB and the GOTO at
the end of the sequence with RETURN. That would eliminate the need for
the “menu_00_endif” label. This is a subroutine and can be replaced by
a method in Ruby. I think in FreeBASIC, your sub may be defined as
follows:

’ I think “goto menu_01” may be replaced by
Menu_01()

’ and the subroutine by
Sub Menu_01

End Sub

You also have a “goto menu_00” after the “End If” statement. The
menu_00 and its goto can be replaced with a loop.

Using a while loop would be a good idea. The loop using goto menu_00 is
an infinite loop, but you use “goto programendshere” to exit it. By
setting a condition variable for the loop, you can exit the loop by
changing the variable. I’m taking a guess at the FreeBASIC grammar
here:

stillChoosing = True
Do While stillChoosing
  ...
  ElseIf strKeyPress = 81 Or strKeyPress = 113 Then
    stillChoosing = False
  Else
 ...
Loop

It looks like your code is somewhat structured already. You just need
to learn how control structures are built from gotos and other
statements to properly replace them.

Finally, since all you your menus will have the same structure, it make
sense that you can replace multiple subroutines with just one. You can
pass the text of each menu and return the result. (In Basic, that will
make it a Function rather than a Sub, I believe! But either way, it
would be a Method in Ruby.)

Putting all that together in Ruby might look something like this:

Displays a menu and gets a response back.

def showMenu menuText

Display the menu

puts menuText
puts

Display a prompt

print "What do you desire? "

Get a string as a response. (The user will have to press enter,

unlike your example.)

chomp removes a newline from the end of the string

downcase makes the string lowercase so “Q” and “q” are returned as

“q”
gets.chomp.downcase
end

Here I am putting the menu text in a long string.

menu_00 = %q{menu 00

1 - open menu_01
2 - open menu_02
3 - open menu_03
4 - open menu_04
q - Quit}

The same can be done for these when they are fleshed out

menu_01 = “menu 01”
menu_02 = “menu 02”
menu_03 = “menu 03”
menu_04 = “menu 04”

stillChoosing = true
while stillChoosing do
case showMenu(menu_00)
when “1”
response = showMenu(menu_01)
# do something with response here
when “2”
response = showMenu(menu_02)
# do something with response here
when “3”
response = showMenu(menu_03)
# do something with response here
when “4”
response = showMenu(menu_04)
# do something with response here
when “q”
stillChoosing = false
else
puts “Wrong Choice, Try Again!”
puts
end
end

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

Jamal

Charles Caldwell wrote in post #1097135:

Be careful saying “no one uses BASIC nowdays”. I have no doubt there is
a subset of people out there still using BASIC. =)

Actually I like FreeBASIC, it’s cross-platform, syntax I’m somewhat
familiar with … but it lacks tutorials, books, videos etc … also,
Ruby has
much more string manipulation methods (which I need for my script).

And I know there is not GOTO in Ruby, I was asking for advice how should
I re-write code I posted above in a Ruby way ? Looks like no one read
entire original post :frowning: … (but I don’t blame you, it’s really long)

On Fri, Feb 15, 2013 at 9:49 AM, Stu P. D’naim [email protected]
wrote:

And I know there is not GOTO in Ruby, I was asking for advice how should
I re-write code I posted above in a Ruby way ? Looks like no one read
entire original post :frowning: … (but I don’t blame you, it’s really long)

Baseline - you are certainly free to move to classes or any other
concepts
you want to add on - but this would be a starting point

#!/usr/bin/ruby

def handle1
puts ‘Got 01’
end

def handle2
puts ‘Got 02’
end

def handleq
@cont = 0
end

@cont = 1

while @cont == 1
puts ‘Pick an option’
choice = gets.strip
case choice
when ‘1’
handle1
when ‘2’
handle2
when ‘q’
handleq
end
end

John

P.S. Probably the trickiest thing in there for you is the gets.strip -
ruby
will give you back the newline character when the person hits enter
#strip
removes the last character from the string (newline character).

WILLS, JAMAL A wrote in post #1097138:

def showMenu menuText
puts menuText
puts
print "What do you desire? "

menu_00 = %q{menu 00

1 - open menu_01
2 - open menu_02
3 - open menu_03
4 - open menu_04
q - Quit}

Firstly, I know what are Functions/Methods, but I find GOTO much easier
to follow (and also more powrfull, because I can RETURN wherever I want

  • in GOSUB, and Functions, you always return to the point you started
    from)

Secondly, this is great idea, to put entire menu in one long string. I
wouldn’t have thought of that !! Thanks !

I had idea (as described in original post at #2) to write code something
like this:

class Mymenus

attr_acessor :over100variablesIintendtoUse

def initialize
#initialize every variable
end

def menu_00 #root menu
system(“cls”)
puts “Select something:”
puts
puts “1 - open menu_1”
puts “2 - open menu_2”
puts “3 - open menu_3”
puts “4 - open menu_4”
puts “q - Quit”
end

def menu_1
system(“cls”)
puts “enter choice:”
puts
puts “1 - open menu_11”
puts “2 - open menu_12”
puts “3 - open menu_13”
puts “4 - open menu_14”
puts “b - Back”
end

def menu_2
system(“cls”)
puts “enter choice:”
puts
puts “1 - open menu_21”
puts “2 - open menu_22”
puts “b - Back”
end

… etc … etc

… and then probably put loop, starting with root menu, when you select
number, you call new method (submenu) … but your way seems easier, and
with less methods involved

On Feb 15, 2013, at 08:46 , Ryan V. [email protected] wrote:

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)…

You’re wrong.

Yeah, I realized that…still doesn’t make him right :slight_smile:

-Ryan

On Fri, Feb 15, 2013 at 7:17 PM, Stu P. D’naim [email protected]
wrote:

Firstly, I know what are Functions/Methods, but I find GOTO much easier
to follow (and also more powrfull, because I can RETURN wherever I want

  • in GOSUB, and Functions, you always return to the point you started
    from)

Where’s the difference? With a GOSUB the RETURN will also take you to
the calling site. That’s the whole point of GOSUB vs. GOTO. What
makes GOSUB worse than functions is that you do not get a new scope
and do not have function arguments. So you always risk messing up the
caller’s scope. Granted, more modern dialects of BASIC might have
mechanisms to deal with that (it’s been a while I worked with BASIC -
and I wouldn’t got back unless for experimental purposes).


… and then probably put loop, starting with root menu, when you select
number, you call new method (submenu) … but your way seems easier, and
with less methods involved

I do not know what your menus will do eventually but I would certainly
make this more data driven. In this example the structure of the code
is identical for all menu entries. There is no if else cascade or
case statement. The proper item is just determined via the position
in the Array:

Menu = Struct.new :name, :code

convenience method to create a Menu instance

def menu(name, &b)
Menu.new name, b
end

menus = [
menu(“Configuration”) do
print “Starting configuration…”
sleep 5
puts " done."
end ,

menu(“Reset everything”) do
puts “back to square one”
end,

menu(“Quit”) do
puts “quitting”
exit 0
end,
]

loop do
puts “Enter your choice:”

menus.each_with_index do |m, idx|
printf “%2d %s\n”, idx, m.name
end

print "> "
input = gets.chomp

begin
m = menus[Integer(input)]

if m
  m.code.call
else
  puts "Wrong choice.  Try again"
end

rescue ArgumentError
puts “Not numeric: #{input}”
end
end

Kind regards

robert

Actually this makes him pretty much the definition of right.

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.

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

Hi all,

On 16/02/13 11:16, Ryan V. wrote:

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

hash inside hash menus, interesting, same as Robert K.'s example …
thank you all guys, now I have more than enough ideas how to start my
script