/lib development

@jlmitch5 @crim FYI I’ve been looking at a more “power user” way of editing scripts using a remote editing setup.


It’s currently mainly focused on working on scripts but the same idea could also be applied to core libs of course.

I figured most the people interested in this would be on GitHub and chime in there but maybe we should create a topic for this as well? I’d like to get some feedback on what does and doesn’t work to determine what should be improved.

2 Likes

My object-oriented grid lib initially kicked off about ten years ago (Java, over OSC, for the original binary grid) and I now have the Lua port working; I’m hard at work on demos and docs right now. GitHub repo. with various READMEs is here - would be interesting to compare/contrast with yours.

3 Likes

Everything is on GitHub, so I have a repo. of the code on the Mac, for general Lua development and unit testing, and a repo. on the norns. I’ll edit via maiden for actual for on-the-box testing, then when I want to sync I mount the norns via SMB for the git client. (I suppose command-line Git would work fine directly on the norns as well, but I’ve never tried it.)

EDIT: Just tried it now. Command-line Git on norns is fine, with norns-generated SSH key on GitHub, and with ssh-agent running to avoid excessive password typeage.

I just had a quick peek but they look pretty darn different ?

mine has a lot more to do with laying out interaction patterns, display-wise it doesn’t do much of anything fancy

I’m not sure what you mean by interaction patterns - could you explain?

I’ve basically implemented a scene graph for grids/arcs: you create a stack of layers each of which contains LED patterns of varying brightness and opacity, and they’re rendered onto a device. You then shift them around, alter visibility etc. to animate an interface. There’s also some smart-ish press management machinery which ensures that any object receiving a button press will get the release at the same local coordinates, no matter how things shift around in the meantime.

I have a few self-made table functions that might be useful to other people. append, take, drop, and rotate. Did a quick rewrite so that they could fit in tabutil.

function tab.append(t1, t2)
  local new_t = {}
  local i = 1
  for j = 1,  tab.count(t1) do
    new_t[i] = t1[j]
    i = i + 1
  end
  for j = 1, tab.count(t2) do
    new_t[i] = t2[j]
    i = i + 1
  end
  return new_t
end

function tab.take(t, n)
  local new_t = {}
  local len = tab.count(t)
  if n > len then n = len end
  for i=1, n do
    new_t[i] = t[i]
  end
  return new_t
end

function tab.drop(t, n)
  local new_t = {}
  local len = tab.count(t)
  if n > len then return new_t end
  for i=1, len do
    new_t[i] = t[i+n]
  end
  return new_t
end

function tab.rotate(t, n)
  local len = tab.count(t)
  local mod = n % len
  local imod = len - mod
  if mod == 0 then return t end
  local t1 = tab.drop(t, imod)
  local t2 = tab.take(t, imod)
  return tab.append(t1, t2)
end
2 Likes

it is worthwhile to become familiar with lua’s standard table library, in particular unpack and move.

most of the functions in table operate in place. {table.unpack(t)} is a quick-and-dirty method to clone a (flat) table if you want to return a copy.

here’s how i might implement those operations using the standard library.

t_print = function(t) for i,v in ipairs(t) do print(i, v) end print('') end 

t = {'foo', 'bar', 'baz', 'zip', 'zap', 'rap' }

z = {'one','two','three'}

-- return first `n` entries
function t_take(t, n)
    return table.pack(table.unpack(t, 1, n))
end

t_print(t_take(t, 3))

  --- return the last 'n' entries
function t_drop(t, n)
    return table.pack(table.unpack(t, #t - n + 1, #t))
end

t_print(t_drop(t, 3))

-- add contents of `t2` to end of `t1`
function t_append(t1, t2)
    local t_new = {table.unpack(t1)}
    return table.move(t2, 1, #t2, #t1+1, t_new)
  end

t_print(t_append(t, z))

-- remove the first `n` elements of `t` and add them to the end
  function t_rotate(t, n)
    local t_new = {table.unpack(t)}
    for i=1,n do
        table.insert(t_new, table.remove(t_new, 1))
    end
    return t_new
  end   

t_print( t_rotate(t, 2) )

in general, using the table library is more efficient than doing the same things in lua code. (the lib is implemented in c and avoids extra allocations, rehashings &c)

4 Likes

Thanks for the tip. I think t_rotate could be kept as appending drop and take, because it handles negative n without extra cases.

-- this
function tab.rotate(t,n)
  local len = tab.count(t)
  local mod = len - (n % len)
  return tab.append(tab.drop(t, mod), tab.take(t, mod))
end

-- vs something like this
function tab.rotate2(t, n)
  local t_new = {table.unpack(t) }
  if n > 0 then
    for i=1,n do
      table.insert(t_new, 1, table.remove(t_new, #t_new))
    end
  else
    for i=1,n do
      table.insert(t_new, #t_new, table.remove(t_new, 1))
    end
  end
  return t_new
end

I can see myself using tab.rotate and tab.append often. Wondering what peoples thoughts are on manipulating the table in place, versus returning a new table.

xs = {1,2,3}
ys = {4,5,6}

xs = tab.append(xs, ys)

vs

tab.append(xs, ys)
1 Like

a Set type would be really handy for many applications too.

1 Like