One property of cl-series is that it generates native lisp (if you made certain implementation errors, it has a fallback mode that papers over your mistakes with non-native cl, but in general you end up with pure lisp). This is suitable for our software-individuals KRF which only wants new actions in terms of its own abilities and pure lisp.
This devlog goes at a gallop because of the pressure of me-taking-an-extra-day-for-my-jam-submission out of time I do not really have.
Raymond Toy (rtoy) updated / modernised the series documentation here for us particularly yesterday.
(setq inferior-lisp-program "sbcl")
(slime)
(setq eepitch-buffer-name "*slime-repl sbcl*")
(lisp-implementation-type)
And, as expected
CL-USER> (lisp-implementation-type)
"SBCL"
(require "series")
Series /installs/ generates pure lisp and then /uninstalls/ so there is nothing but pure lisp left. I guess it is an uncommon idiom otherwise. (I do this in sbcl only).
(series::install)
The sane package (default) for series is the current package, so CL-USER
currently has series installed in it which we will later remove.
I think my sensor regions can always be found by collecting a sequence of symbols from a rectangle (dr1 dr2 dc1 dc2), relative to a target (row, col).
(let ((sensor
(lambda (target sequence row col
dr1 dr2 dc1 dc2)
(let* ((S (scan (cadr sequence)))
(nos (scan-range))
(lists (#Mcadr S)))
;;okay, let's actually stop here.
(collect
(#Mcons nos lists))))))
(apply sensor nil '(seq& ((seq& (a b c))
(seq& (d e f))))
NA NA
'(NA NA NA NA)))
As expected, this returns ((0 A B C) (1 D E F))
while being written in an endearing and declarative tone.
It turns out I cannot install series
into a software-individual because of name conflicts, so we will have to do a small tribute to Nicholas Martyanoff by namespacing all the series macros (he always namespaces absolutely everything).
(let ((sensor
(lambda (target sequence row col
dr1 dr2 dc1 dc2)
(series::let*
((S (series::scan (cadr sequence)))
(nos (series::scan-range))
(mask1 (#M<= (series::series
(+ row dr1))
nos))
(mask2 (#M< nos
(series::series
(+ row dr2))))
(lists (#Mcadr S))
(sublists (#Msubseq
lists
(series::series
(+ col dc1))
(series::series
(+ col dc2)))))
(series::collect
(series::choose
(#Mand mask1 mask2 nos)
(#Mcons nos sublists)))))))
(print
(apply sensor nil '(seq& ((seq& (a b c))
(seq& (d e f))))
0 1
'(1 2 0 2)))
(yes-or-no-p "Are things great"))
((1 e f))
as we may have thought. Note my use of LET* to build declarations on prior declarations, sequentially. Series guarantees a tight in-order traversal version (of your valid declarations). It is a miracle in a can.
(setq eepitch-buffer-name "*slime-repl clisp<2>*")
put sequence-rectangle type lispdef
addmember (get board contents) sequence-rectangle
writefil board
this creates a stub where we can define our function in #p"~/leocommunity/plant-insect-bird/demus/Game/board.leo"
:
---------------------------------------------------------
-- sequence-rectangle
[: type lispdef]
[: latest-rearchived nil]
Series has a design principle that you must always directly show people the series macro itself that is happening with no obfuscation or “help” (obviously you can define multiple functions). (And obviously never show people the long-form generated low-level lisp code).
Here is my internal-lisp-only function. I had it poke us for a yes-or-no (did this seem to work) when the loadk board
happens, which I will turn off.
---------------------------------------------------------
-- sequence-rectangle
[: type lispdef]
[: latest-rearchived nil]
(prog ()
(require "asdf")
(require "series")
(let ((sensor
(lambda (target sequence row col
dr1 dr2 dc1 dc2)
(series::let*
((S (series::scan (cadr sequence)))
(nos (series::scan-range))
(mask1 (#M<= (series::series
(+ row dr1))
nos))
(mask2 (#M< nos
(series::series
(+ row dr2))))
(lists (#Mcadr S))
(sublists (#Msubseq
lists
(series::series
(+ col dc1))
(series::series
(+ col dc2)))))
(series::collect
(series::choose
(#Mand mask1 mask2 nos)
(#Mcons nos sublists)))))))
(print
(apply sensor nil '(seq& ((seq& (a b c))
(seq& (d e f))))
0 1
'(1 2 0 2)))
(yes-or-no-p "Are things great")
(defun apply-sensor (&key
target sequence
row col
dr1 dr2 dc1 dc2)
(apply sensor
(list target sequence row col
dr1 dr2 dc1 dc2)))))
I can happily use series inside my software-individuals’ internal lisp functions. I will do some more beginner-focused series articles in the future (if you search, you can probably already find some by me in past places).
See everybody on the mastodon to talk about it ;p.