I Am Puzzled By A Problem With Return

I’m a beginner so maybe I am missing something obvious. Anyone know what the problem is here? (see the capitalized comments) Is it a bug?

  
function next_line_from(sequence, line)  
 local pattern = renoise.song().sequencer.pattern_sequence[sequence]  
 if line == renoise.song().patterns[pattern].number_of_lines then  
 if sequence + 1 > table.getn(renoise.song().sequencer.pattern_sequence) then  
 return "END"  
 else  
 sequence = sequence + 1  
 line = 1  
 end  
 else  
 line = line + 1  
 end  
 return sequence, line  
end  
  
local steps = 1  
  
function next_note_from(sequence, line)  
 local n_sequence, n_line = next_line_from(sequence, line)  
 if n_sequence == "END" then return "END" else  
 if renoise.song().patterns[renoise.song().sequencer.pattern_sequence[n_sequence]].tracks[renoise.song().selected_track_index]:line(n_line).note_columns[renoise.song().selected_note_column_index].is_empty == false then  
 return n_line -- THIS DOES NOT WORK  
-- print(n_line) -- THIS WILL WORK  
 else  
 steps = steps + 1  
 next_note_from(next_line_from(sequence, line))  
 end  
 end  
end  
  
  
function main()  
 print(next_note_from(renoise.song().selected_sequence_index, renoise.song().selected_line_index)) -- THIS DOES NOT WORK  
 -- next_note_from(renoise.song().selected_sequence_index, renoise.song().selected_line_index) -- THIS WILL WORK TOGETHER WITH PRINT ABOVE  
end  
  
main()  
  

It should work the same way this does:

  
function test1()  
 local a = 1  
 return a  
end  
  
function test2()  
 print(test1())  
end  
  
test2()  
  

Any help is much appreciated.

It seems that “return n_line” returns nil, but it is printable before that. Is something strange happening regarding datatypes maybe?

Variables don’t have a fixed datatype in LUA so that would seem a little strange.

Have to admit the Return command is one so far I’ve felt a little ambiguous on though, so have always used local variables (even if local for the entire script) instead on the whole. What are you trying to return the value into? As I can’t see it actually going anywhere… (Although I probably misunderstand.)

But something like:

function power(x,y)
z = x^y
return z
end

As far as I understand it will not generate a variable called z.

If you then went:

fish = power(2,3)

print (fish)

-> 8 – would be outputted.

Or at least that is now I’ve been thinking it works.

Yes. It should work like that but something is jammin in my example.

You misunderstand recursion, I think.

When you call next_note_from() recursively, you are returning to the previous next_note_from() call, not to main().

Change line ~26 from:

  
next_note_from(next_line_from(sequence, line))  
  

To:

  
return next_note_from(next_line_from(sequence, line))  
  

You should add a return value to your else statement, otherwise all function calls that proceed to the else will return nil.

I see that you have a recursive function in the else scope: next_note_from(next_line_from(sequence, line))

This function will execute but it does not override the current functions scope so you should return the executed functions returned value.

More simply return your recursive function:

return next_note_from(next_line_from(sequence, line))

I have not tested this, not enough time atm, but I’m pretty sure it’s your problem. Let us know how it goes.

Thanks a lot guys. Just adding a return helped me. I probably missed something with the scope, and I’m too stupid to fully understand it atm. I was puzzled because print worked but not return.

Here you have a working example, in case anyone will benefit from it :)

  
function next_line_from(sequence, line)  
 local pattern = renoise.song().sequencer.pattern_sequence[sequence]  
 if line == renoise.song().patterns[pattern].number_of_lines then  
 if sequence + 1 > table.getn(renoise.song().sequencer.pattern_sequence) then  
 return "END"  
 else  
 sequence = sequence + 1  
 line = 1  
 end  
 else  
 line = line + 1  
 end  
 return sequence, line  
end  
  
local steps = 1  
  
function next_note_from(sequence, line)  
 local n_sequence, n_line = next_line_from(sequence, line)  
 if n_sequence == "END" then return "END" else  
 if renoise.song().patterns[renoise.song().sequencer.pattern_sequence[n_sequence]].tracks[renoise.song().selected_track_index]:line(n_line).note_columns[renoise.song().selected_note_column_index].is_empty == false then  
 return { n_sequence, n_line, steps }  
 else  
 steps = steps + 1  
 return next_note_from(next_line_from(sequence, line))  
 end  
 end  
end  
  
  
function main()  
 local next_note = next_note_from(renoise.song().selected_sequence_index, renoise.song().selected_line_index)  
 print("The next note is at sequence " .. next_note[1] .. ", line " .. next_note[2] .. ", " .. next_note[3] .. " steps ahead")  
end  
  
main()  
  

Great that it works! Thumbs up to Conner for beating me to the punch.

I find scopes and recursion quite hard to explain. But it’s important to understand.

This is because the function was executed within another function. Each time you execute a function it runs with it’s own scope instance. So your print function was being fired, and actually your return was also being returned but it was not handled in the previous scope.

Consider the following code as a more scope related way to handle recursion:

  
local return_value = next_note_from(next_line_from(sequence, line))  
return return_value  
  

This way you could modify the return_value again within the previous function scope before returning to main().