5 ms·
Maybe I phrased that incorrectly indeed. It's not so much that I want to find a 'better way to implement a message bus', but more 'if I want to re-implement the
by w0utert 6y ago
Maybe I phrased that incorrectly indeed. It's not so much that I want to find a 'better way to implement a message bus', but more 'if I want to re-implement the message bus I already have, how can I use the features of a Lisp-like languate to improve the implementation'.
For the logic in my iOS game I started out with a straighforward imperative system based on objects and explicit state, which quickly devolved in a big mess of if-then-else-but-only-if spaghetti code that was impossible to maintain. I refactored that to a reactive system based on what I call an 'event graph' where each node performs some kind of filtering or processing. For example nodes like 'filter on event type', 'take first 4 events', 'complete when event X received', etc. Game logic is implemented by branching off (subscribing) to nodes, synchronizing stuff by means of attaching a temporary subgraph that waits for a 'completion event' etc. Like I said it's quite similar to ReactiveX but simpler.
The basic concepts behind this are sound, but my feeling is that I need way too much code in to implement something like this in Lua, compared to what I would expect in something like Lisp, which seems more naturally suited for this kind of task. I just find it hard to get started trying to map the solution I already have to a Lisp language, because most of the 'introduction to Lisp'-like resources are so focused on artificial examples that are mostly interesting from a computation-theoretic point of view.
- widdershins 6y agoIn terms of the basic tools available to you, Lisp and Lua are remarkably similar. In both you will rely heavily on closures to get the job you mentioned done. Lua offers the table as its primary data structure, though this can also be used as an array. Lisp offers the list, though this can also be used as a table (associative container, whatever). Where Lisp and Lua differ is that Lisps are infinitely more malleable as languages. You can more-or-less invent new syntax to assist in your problem domain. For example, if you find that constructing your 'event nodes' requires boilerplate in Lua, you can write Lisp macros that make things clear again. Or you might write a little macro DSL to make constructing your graphs easier. I enjoy Lua, but I constantly pine for the flexibility of a Lisp when Lua's clunky syntax annoys me. I find Fennel is a good compromise between the two - especially if you already have Lua code that you want to port over.
- junke 6y agoFor your particular example, it seems you could use a dataflow approach, like the one in Cells (K. Tilton) (see tutorial: http://stefano.dissegna.me/cells-tutorial.html http://stefano.dissegna.me/cells-tutorial.html, and documentation: https://gitlab.common-lisp.net/cells/cells/-/tree/master/doc https://gitlab.common-lisp.net/cells/cells/-/tree/master/doc) (ql:quickload :cells) (defpackage :robot (:use :cl :cells)) (in-package :robot) Define a robot model (class) where command in an input, and velocity is defined by an update rule: (defmodel robot () ((command :accessor command :initform (c-in nil)) (velocity :initform (c? (case (command self) (:left -10) (:right 10) (t 0)))))) Whenever command is modified, velocity is updated accordingly. You can add observers for slot changes: (defun log-change (what from to) (print `(:change ,what :from ,from :to ,to) *debug-io*)) (defobserver velocity ((model robot) new old boundp) (when boundp (log-change `(velocity ,model) old new))) Then, if you instanciate the model, and mutate the command slot: (let ((w (make-instance 'robot))) (setf (command w) :right) (setf (command w) :left) (setf (command w) nil)) The following is logged: (:CHANGE (VELOCITY #<ROBOT {1015D66783}>) :FROM 0 :TO 10) (:CHANGE (VELOCITY #<ROBOT {1015D66783}>) :FROM 10 :TO -10) (:CHANGE (VELOCITY #<ROBOT {1015D66783}>) :FROM -10 :TO 0) Anyway, the book Common Lisp Recipes (E. Weitz) is good for solving actual, pratical problems with Lisp.