Since Lua is very much a batteries-not-included solution when it comes to “real” OOP, it would be interesting to hear from folks who had adopted some ad-hoc standard (or even non-standard) coding approach for it. I’ve had a look through the norns apps and while a lot of them use object libraries, none seems to implement objects over and above simple encapsulation of values and functions into tables.
I’m pretty much following the pattern for inheritance from the official programming guide here, including the explicit-self-as-metatable trick which enables inheritance, although so far monkey-patching new methods is tidier than attempting inheritance in this manner. Also, I notice that this mechanism only works for default values which are scalar, since there’s a reliance on __index to lift it by copying from the prototype, which feels a bit fragile.
Lua programs I’ve seen in the wild seem to come down 50-50 in favour of Class.new() vs. Class:new(); the latter is needed for sub-classes to get the metatable in the right place for inheritance to work.
After rolling my own based on the Lua programming guide for the last few years I switched to using Class:new(...) new last week when I was in search of the ability to subclass. In the process of looking at other Lua projects I stumbled on an object abstraction that I liked enough that I just pulled it into my repo. Specifically:
The original author rxi has some fairly nice code at least to my eye.
I’ve been following the guide style & setting up inheritance systems with pretty good success. I actually quite like doing OOP in lua. proving the batteries means lots of flexibility, you can make pretty cool APIs with nontraditional syntax
Glad to hear it. I’m liking the flexibility but find the permissiveness of the language makes it rather fragile, so I’m doing a lot of unit testing. (But that’s probably pretty good practice in any case.)
But there are tutorials presenting techniques to tighten up the error checking on bindings and environments, so perhaps I should experiment with those.
share them here if you find them ! I’m only sort of a semi-professional programmer and haven’t gotten deep into testing practices yet (a topic for another time tho)
My 2c, and take it with a grain of salt, but I enjoy using a factory approach with Lua. Might be years of javascript work beating Classical OOP out of me, but a functional approach has definitely lighted the mental load for me. The other thing I’ll say is to use params:add/get for everything you can. It makes universal getting & setting way easier, you get some flavour of type safery and you have a much easier time saving presets.
Yeah, I’m a node developer and don’t have extensive experience with OOP, but I get the impression it sometimes adds unnecessary complexity, especially when you’re dealing with a small script that doesn’t need to be scaled up to some massive application.
I could be totally wrong of course. Whatever the project calls for (and you’re most comfortable with) is probably best.
I sorta mix paradigms, but generally prefer a functional style. Still figuring out the best architecture for big scripts though. Norns development feels very different from the day job.
I was looking through the Lua OOP wiki last night since I’m rewriting one of my scripts in a very object-oriented style. Lua is flexible enough that I can just do whatever is most convenient at the time, but judging by the wiki there’s been a lot of thought put into making it more robust.
It would be nice to have a “house style” for OOP in norns, it would probably make reading other peoples’ code a bit faster.
It’s fun to be able create bi-directional relationships though.
One or two comments… Firstly, on reflection I’m not convinced that any kind of “house style” is necessary or desirable at this stage; it’s more healthy to see variations and combinations of styles in creative coding, especially if (getting all Sapir-Whorf here) variations lead to interesting musical applications. It’s not as if we have large dev. teams working on mission-critical enterprise apps. (For norns internals and OS-level tools, different rules probably apply.)
Secondly, I’m not a massive OOP fan despite (or perhaps because of) having done quite a bit of heavyweight Java development in the past, and a reasonable amount of C++ and Python (and a smattering of Ruby). The accidental aliasing risk is too great beyond a certain level of complexity (so, I’m not against OOP with immutable data, which seems to work well). By preference I’m more full-on functional, and spend a lot of time in Clojure. If Lua had a good performative immutable data library I might well go that way instead - there are so many benefits.
But I’m also fine with simplicity (despite my occasional tendency to over-engineer); while I’m going OOP for this app, it doesn’t look like it needs inheritance since it’s clearer to just monkey-patch in the virtual methods.
Object Orientation isn’t a panacea. It’s really exciting when you first discover it. After a bit you realise everything isn’t an object. Take the canonical example - yes your teapot and kettle and cup ARE objects but making a cup of tea is a process and if you start introducing the “visitor pattern” you deserve everything you get ;-). There is a reason every codebase you have ever worked on has a “utils” class/module/library/package
like @cassiel if I was being forced into someones paradigm - and I’ve spent enough time in my life torturing code to make it fit in bloody paradigms - then I’d go functional too at this stage of my life
anyway this is all moot. It’s hard enough to enforce coding standards let alone styles with a paid team who all have time allocated to code reviews and a process and a reason to all adhere to the standards and automation to help enforce it. Good luck with a bunch of creative people who do it for fun and actually aren’t sharing a lot of code
On 1: When I teach OOP I give my students a task to build a car and then remove one wheel. They are rather taken aback when all the wheels fall off. Also, in my experience, objects breed frameworks, whereas FP tends to breed libraries.
On 3: We’re here to be creative and have fun, not earn paycheques in back-end dev. teams. Having said that, I’m still a big believer in unit tests…
Oh - totally random & marginally off topic suggestion.
I gave in and bought the latest Lua book (a mix of feeling guilty and being fed up with always having to navigate the website) - it’s much better than the one on the website - I’d say it is probably worth it. Also it covers things in a little more depth
Oh, and that’s the other thing I was going to say: tools trump language. Much as I love Clojure, we would have had some serious domestic arguments by now were it not for Emacs, the REPL, parenthesis-based editing, specifications, and so on. (It’s still not great for multi-file projects.) Java coding was enjoyable because Eclipse is so amazing - though that could be a trap obscuring OOP pitfalls. The norns web interface is a good solid piece of work: as sophisticated as it needs to be to do the job well, and no more.
part of my motivation in having norns use lua is that i wanted something that could be potentially as approachable as teletype (ie, for non-programmers) but also powerful enough to do more complex things.
so, on one end of the spectrum— i wanted someone to be able to have a half-page of code which sets up softcut in a particular way, maps some encoders or midi, and shows something musically helpful on the screen. maybe extend it with some tables for musical purposes… ie, everyone has their own sequencer. at this level the code functions more like a composition, in a sense.
but i also set a precedent for big complicated scripts that are more like tools and less like compositions (ie mlr). and these big scripts could possibly use some OOP effectively. but to be honest i’m rewriting mlr from scratch and still not bothering with OOP— it feels overkill.
but where it is more often needed is in the core libraries. so maybe this is a good moment to set out a request: from all the smart people in this thread, we’d happily welcome contributions to the core library. for example— when norns started, there was no concept of “parameters” and that grew over time. i’d like to find situations where the core libs can address basic recurring needs, so where possible user scripts can be as short as possible and leverage existing patterns.
that said, things like the param system don’t accommodate every need— and there’s a point where overbuilding that system has diminishing returns. it’s very easy to make a custom param-menu-like thing… because it’s lua.
ps. the scripting docs (particularly the libs) are in desperate need of an overhaul, and a vision towards it. which will likely also suggest some sort of syntax unification… which is maybe what is meant by house style.
I think this kind of cookbook approach can really work & agree having off the shelf library components makes the creative lift of new ideas much easier
While not in anyway claiming to be “a smart person” - My Kria port has got a new output module which makes midi/crow output easier to shove into a script - I’d like to see how it goes down with people but if I get a positive response will submit it for consideration
Lua is indeed a good fit here - relatively simple out-of-the-box, but with the flexibility to be exploratory without being verbose. Sam Aaron went for Ruby with Sonic Pi for a similar reason, I think, though the simplicity there is a bit more syntactic: play 60 and you’re away.
Regarding the core library… well, FWIW shado is now up and running, though it needs a bunch of example apps and a push on the documentation. I’m not sure it’s quite ready to ship as a built-in component until it’s been stress-tested for performance.
There’s been a couple mentions of functional programming here, and I’m a fan of it too. It’d be nice to see some development of FP in the core library. Maybe developing the core lib deserves its on thread. Would be good to get some input on a couple things I want to contribute there.