Goto vs. Return

Again, I am definitely a newbie to Codea/LUA, and in my research and failed attempts I am trying to figure out how to return based on a conditional to a prior line.

What I am trying to do:


function Example()

a = math.random(10)
If a = 1 then goto Example()

Or in the days of coding with line numbers


10 Label1

20 a = int(rnd*10)+1
30 If a = 1 then goto 10

I am sure there is an easy solution, but I am having a hard time figuring this one out.

Thanks,
Munkie

Perhaps you can help further as now I am having an odd outcome…

When I add a function like the code below I get all zeroes for the random number.

function runGames()
    for sc = 1, 4 do
        scores[sc][1] = math.random(30)
        print(scores[sc][1])
    end
end

when I remove the function I get the random number to display properly. Any idea what I might be doing wrong?

Thanks,
Munkie

You had it right - remove the “goto”. (it’s really “gosub”, if you go back to basic…)

In general - goto isn’t necessary; it’s use is replaced by looping structures (for, while)

10 a=1
20 a=a+1
30 print "Excelcior!"
40 if a<5 goto 10

Becomes

For a=1,5 do
   Print("Excelcior!")
End

Thanks for the quick response, but what if I want to break out to another section of code based on another criteria, i.e.:

10 a=1
20 a=a+1
25 if a=3 then gosub 60
30 print "Excelcior!"
40 if a<5 goto 10

60 print "Longfellow!"
65 <Do some other codey stuff here>
70 end

Apologies in advance if this is pitched at the wrong level…

It looks like you’ll want to be using functions. Something like:

function blah()
    a = a + 1
    if a == 3 then
        longFellow()
    end
    print "Excelsior!"
    if a < 5 then
        blah()
    end
end

function longFellow()
    print "Longfellow!"
    -- do other things
end

You can use functions to encapsulate sections of code and then run them by ‘calling’ the method using its name.

You can also pass in parameters and return values from functions:

print sayHello("James")

function sayHello(name)
    return "Hello " + name
end

@frosty Thanks much, once I get my iPad charged I will give it a go. I think it is at the right level as I understood it… I think. :slight_smile:

I will let ya know what comes of it.

Munkie

do you mean when you print it directly?

Try adding “scores[sc] = {}” before you assign the random number. Lua doesn’t auto-vivify tables (which is a fancy way of saying that the [1] array won’t exist to have a value set until you create it)

if that fails, show us the code where you set up the scores variable.

@Bortels … Below is the full code that deals with the creation of the table and population.


    for sc = 1, 4 do
        scores[sc] = {}
            for y=1, 10 do
            scores[sc][y] = 0
            end
    end   
    
    -- populate weekly info table - run games
    -- 1=score, 2=has played (1=yes/0=no)

function runGames()
    for sc = 1, 4 do
        scores[sc][1] = math.random(30)
      --  print(scores[sc][1])
    end

Thanks again,

Do you, at some point, actually call runGames() to populate the array?

If its just the code above, runGames() never actually gets called.

But assuming you do, the above should be fine.

The following works for me:

function setup()

scores = {}

    for sc = 1, 4 do
        scores[sc] = {}
            for y=1, 10 do
            scores[sc][y] = 0
            end
    end   
    
    -- populate weekly info table - run games
    -- 1=score, 2=has played (1=yes/0=no)
    
    runGames()
end

function runGames()
    for sc = 1, 4 do
        scores[sc][1] = math.random(30)
        print(scores[sc][1])
    end
end

function draw()
end

I suspect you may be running into problems by not using setup()?

I am going to try this again as I am still having an issue understanding, and you all seem to have oodles of patience…

What I am try to do is pick two random teams from a pool of 4. The one criteria is that they have not been picked before, hence the flag for number 2 “has played”. The problem I am having is that when the if statement fails I want to go back to the random statement above and pick another random team and do this until I get one that has the flag as zero, not played.

And @bortels, I guess I don’t truly understand what belongs in setup when talking about tables. Should the creation of the table, for all tables? Should I be creating additional dimensions to table in setup? Should I be populating the table with real data in setup?

Thanks again for your patience as I muddle through the learning process.

Munkie

   -- populate weekly info table - run games
    -- 1=score, 2=has played (1=yes/0=no)
    tm1 = math.random(4)
    if scores[tm1][2] == 1 then goto <the line above>
    scores[tm1][2] = 1
    
    tm2 = math.random(4)
    if scores[tm2][2] == 1 then goto <the line above>
    scores[tm2][2] = 1
    
    scores[tm1][1] = math.random(30)
    scores[tm2][1] = math.random(30)

The key is to understand how Codea interprets what you have - TLL, feel free to correct me if I get this wrong…

The first thing that happens when you hit play is all of your code is executed, in order. The thing here is that most of this is probably going to be defining and setting up various functions, including setup() and draw(). This means you can put code outside of functions. Having said that, I personally think it’s a bad idea; the order of execution isn’t strictly defined, and you may have issues with code referring to things that haven’t yet been defined. So - unless you want to make pain for yourself, avoid putting code outside of a function definition.

Once your program is parsed, Code calls setup() once, then calls draw() over and over, forever. The draw() function is your de-facto main loop - you do things here that you want to happen forever (like “paint the screen” or “interpret touches”).

So - while you don’t have to do it this way, good practice is to define all of your global variables, including tables, in setup(), then use them in draw(). (you may want to avoid globals and use local variables, but that’s something you’ll be more concerned about if you’re writing libraries or classes for others to use, or are making something really huge - for smaller stuff, I wouldn’t worry).

In this case, I’d have “scores = {}” in setup() for sure; where it gets populated depends on where the teams and scores are coming from. Maybe that’s literal code in setup, maybe it’s randomly generated, maybe it’s from persistent storage (and you store results after every matchup), maybe it comes from the internet (soon!).

Back to your example. Here’s how I’d do what you’re trying to do on a first whack (we’ll assume I’ve created and populated the table elsewhere):

tryagain = true
while (tryagain) do
   tryagain = false
   tm1 = math.random(4)
   tm2 = tm1 -- start with them the same
   while (tm1 == tm2) do
      tm2 = math.random(4) -- pick a random team
   end
   -- at this point, we have tm1 and tm2, both unique
   -- but, if one of them has played, pick again randomly
   if (scores[tm1][2] == 1) then tryagain = true end
   if (scores[tm2][2] == 1) then tryagain = true end
end

Now - I wouldn’t do it that way, because if all teams have played (for example), you’d endlessly loop - non deterministic code is a good way to get bit.

Instead, I’d first make a new table of teams who haven’t played, then I’d choose one randomly from the table, then choose the second (and if they collided, I’d simply increment the second team rather than guessing again). Writing that is left as an exercise to the reader. :slight_smile:

@Bortels just one thing: the order of execution is defined. It is left to right tab, top to bottom. Nonetheless I agree that in Codea you should reduce code outside of functions to a minimum because things you assumed about functions or variables beind defined might change if for some reason you change the order of your tabs. @Munkie Basically you should only do constant things outside of functions, like initializing variables to constant values (not function calls). Other things like the proposed call to set the display mode should only be done in your main file, otherwise you might end up doing it multiple times and weird things could happen.

One function that should be called in global scope is supportedOrientations() if you wish to lock your project to a particular set of orientations.

It should be called as follows, in Main

supportedOrientations( PORTRAIT_ANY )

function setup() end

function draw() end

This is due to a limitation — we can’t constrain the supported orientations of the view after it is displayed. By the time setup() is called it’s too late to do that.

Mmmm… I’d call that “accidental”, not defined. The behavior could change in future releases, although I admit that’s not likely now because some people depend on it. The problem there is you don’t know that someone who cut-and-pasted your code is going to end up with the right tab order; better to not leave things to chance. If you do all of your work in functions, you get to choose execution order, not fate…

@simeon - is the main tab always first, or is in strict left-to-right order?

I disagree on the “accidential” part. Consider classes: what you perceive as a class declaration is basically a definition of a variable in the global scope, initialized with a function call. So, in order to use a class, the variable holding the class needs to be defined. And in order to guarantee that, you will need to have a defined execution order of your files. So basically, codea itself relies on this order of execution. Plus, the code for loading the tabs does look purposeful as well :wink: But nonetheless, I did agree, don’t do too much at global scope.

@Bortels it’s always left-to-right. We looked at ways to automatically decide order-of-execution, but because Lua is a completely dynamic language it’s just too hard. Class declarations are the main thing that rely on the execution order (sub-class tabs must come after their base classes).