monome / bowery

druid script collection
75 stars 35 forks source link

`clockdiv.lua`: bad argument #2 to 'clock_schedule_sync' (number expected, got nil) error on input 2 updates #14

Closed joshuagoran closed 1 year ago

joshuagoran commented 1 year ago

When attempting to run clockdiv.lua, I am getting this error on any voltage change at input 2:

> r clockdiv.lua                                                       
running clockdiv.lua                                                   
^^pub("_clear")Running: clock divider                                  
bad argument #2 to 'clock_schedule_sync' (number expected, got nil)    
stack traceback:                                                       
  [C]: in function 'clock_schedule_sync'                               
  ?: in function 'clock_resume_handler'                                
  ?: in field 'run'                                                    
  ?: in method 'clock'                                                 
  userscript:26: in function 'init'                                    
^^ready()

I spent some time debugging - as far as I can tell, what is causing the error for me is that windows[win_ix][n] within the newdiv() function is undefined/nil.

I was able to get the script to work by replacing windows[win_ix][n] with public["win" .. win_ix][n], but that feels hacky to me:

--- clock divider
-- in1: clock input
-- in2: division selector (see divs)
-- out1-4: divided outputs

function newdiv()
  for n=1,4 do
    output[n].clock_div = public["win" .. win_ix][n]  -- this is the changed line!
  end
end

-- choose your clock divisions
windows = {
  public{win1 = {5, 7, 11, 13}}:action(newdiv),
  public{win2 = {3, 5, 7 , 11}}:action(newdiv),
  public{win3 = {2, 3, 5 , 7 }}:action(newdiv),
  public{win4 = {2, 4, 8 , 16}}:action(newdiv),
  public{win5 = {4, 8, 16, 32}}:action(newdiv),
}
win_ix = 3

function init()
  input[1].mode('clock',1/4)
  input[2].mode('window', {-3,-1,1,3})
  for n=1,4 do
    output[n]:clock(public.win3[n])
  end
end

input[2].window = function(win, dir)
  win_ix = win
  newdiv(windows[win])
end

can anyone else reproduce this / what is the correct way to fix it?

dndrks commented 1 year ago

hihi! hope all's well :) apologies, this got buried somehow!

it seems like the syntax of public variables when nested inside of a table strips them of their 'magic' and requires a bit of massaging to access -- namely, accessing via the windows[ix].v table. i also think the solution you identified works super well! idk, @trentgill , do you have any guidance / preferences?

here's a v-lookup version that should work:

--- clock divider
-- in1: clock input
-- in2: division selector (see divs)
-- out1-4: divided outputs

function newdiv()
  for n = 1, 4 do
    output[n].clock_div = windows[win_ix].v[n] -- changed line
  end
end

-- choose your clock divisions
windows = {
  public({ win1 = { 5, 7, 11, 13 } }):action(newdiv),
  public({ win2 = { 3, 5, 7, 11 } }):action(newdiv),
  public({ win3 = { 2, 3, 5, 7 } }):action(newdiv),
  public({ win4 = { 2, 4, 8, 16 } }):action(newdiv),
  public({ win5 = { 4, 8, 16, 32 } }):action(newdiv),
}
win_ix = 3

function init()
  input[1].mode("clock", 1 / 4)
  input[2].mode("window", { -3, -1, 1, 3 })
  for n = 1, 4 do
    output[n]:clock(public.win3[n])
  end
end

input[2].window = function(win, dir)
  win_ix = win
  newdiv(windows[win])
end
dndrks commented 1 year ago

tha above is confirmed working through our support inbox, so i'll push the changes and close this ticket :)