1. 16

Feel free to tell what you plan on doing this weekend and even ask for help or feedback.

Please keep in mind it’s more than OK to do nothing at all too!

    1. 14

      Trying to remember how to relax again. XD

    2. 4

      I’ve been having a blast making a tiny game for a game jam using raylib! Will likely continue doing that, apart from a trip to enjoy some time with friends :)

      1. 1

        I ran across Raylib two years ago, and it has been a joy to use. I love how the lib handles typical use cases by giving you ‘on rails’ solutions, and allows you to dig deeper into the lib if you have special needs.

    3. 3

      I’ve had an idea kicking around my brain for a while now of a way to implement a more powerful and flexible macro system than defmacro for languages with lots of parentheses, but I’ve been too busy working on a book to actually try to implement it. But the book is out now! So I’m going to try to mock it up in Janet and see how it feels in practice, and then (hopefully) write a blog post if it goes well.

      1. 4

        That sounds awesome! I read a lot of the literature on syntax-case last month[1], have been loving reading Janet for Mortals in my downtime, and haven’t reached your chapter on macros yet but think it’s a particularly interesting language for prototyping your idea because of eg. the behavior you discovered in “Making a Game Pt. 3” (which isn’t necessarily portable). I’d be interested in any ideas you have in this area (even if they’re not merit-ful or focused on hygiene), and will be looking forward to the post c:

        [1]: Not all of which was correct: there is a a false ambiguity on the surface, and true undefined “implementation-dependant” behavior deep in the bowels of the spec.

        1. 2

          Hey thanks! Glad you’re liking the book. Here’s a quick sketch of my macro idea: https://github.com/ianthehenry/macaroni

          I can’t find any prior art for this but I have no idea what to search for or call it.

          1. 3

            Spent some time considering prior art, and the closest I could get was what Guile calls Variable Transformers.

            In eg. Common Lisp and Elisp, Generalized Variables can extended by defining a dedicated macro which set! or setf finds and invokes (via a global map, symbol properties, etc).

            In Guile, you can create a macro which pattern-matches on the semantics of it’s call-site:

            • use as an applicative operator
            • use as an identifier
            • use as the second argument of a set! form

            Because it needs to be used as an identifier it can’t define set!-able sexps like Common Lisp or Elisp would allow, but neither can macaroni. It’s not a first class object, short of being a normal function under the hood. Finally it’s handicapped by only being passed its parent’s form in the third situation, essentially still at set!’s discretion (not sure about the exact mechanism in use). Definitely the only other example I could find of an identifier-bound macro receiving the form it is invoked within.

            Stayed up too late to think any more, but love the idea, that’s awesome

            1. 2

              Hey thanks! I had seen something very similar to this in Racket before – I guess it’s a general scheme thing.

              You actually can make settable sexps with the macaroni approach, by returning a first-class macaron that checks the context it appears in – https://github.com/ianthehenry/macaroni/blob/master/test/settable.janet

              (The downside explained there tells me that I should spend some more time thinking about controlling the order of expansion… which would also make it easier to define infix operators with custom precedence…)

              1. 3

                Ooo, I can see how I’d have missed that on the way out, nice! Found Racket’s Assignment Transformers, and they (bless the docs!) explain that they are indeed just sugar over a variant of the “set! + symbol-props” approach. I wonder if this approach (ie. returning an anonymous or gensym’ed identifier macro) could be retrofitted in to that model, but it feels clear to me that macarons more cleanly solve and generalize what has always been a messy situation in Lisp implementations.

                As another exploratory question, are we limited (in practice or theory) to the immediate context of the parent form? Aside from that dispatching on grandparent or cousin forms feels kinda cursed. I wonder what use cases pull sibling sexps into play.

                Funny how having to dispatch on the set literal kinda resembles the limitations of a system invoked by set itself, but it’s progress! Re: expansion order, my gut feeling is that they ought to be compatible with other extensions that don’t explicitly macro expand their arguments (ie. until the set form is established), but haven’t really dug into how janet/this all works and need more coffee first

                1. 2

                  Theoretically you can rewrite forms anywhere, but I’m having a hard time coming up with a situation where you’d want to. But here’s a nonsensical “grandparent” macaron:

                  (defmacaron sploot [& lefts1] [& rights1]
                    (macaron [& lefts2] [& rights2]
                      (macaron [& lefts3] [& rights3]
                        ~(,;lefts1 ,;lefts2 ,;lefts3 ,;rights1 ,;rights2 ,;rights3))))
                  
                  (test-macaron (foo (bar (sploot tab) 1) 2)
                    (bar foo tab 1 2))
                  

                  You could also write a recursive macaron that rewrites an arbitrarily distant ancestor.

                  Here’s an example of a potentially interesting “cousin” macaron:

                  (defmacaron ditto [& lefts] [& rights]
                    (def index (length lefts))
                    (macaron [& parent-lefts] [& parent-rights]
                      (def previous-sibling (last parent-lefts))
                      (def referent (in previous-sibling index))
                      [;parent-lefts [;lefts referent ;rights] ;parent-rights]))
                  
                  (test-macaron
                    (do
                      (print "hello")
                      (print ditto))
                    (do
                      (print "hello")
                      (print "hello")))
                  

                  Is that useful? I dunno, maybe? It’s like !$ in shell, but copies the element at the exact previous position.

                  Actually $! is even easier to write:

                  (defmacaron !$ [& lefts] [& rights]
                    (macaron [& parent-lefts] [& parent-rights]
                      [;parent-lefts [;lefts (last (last parent-lefts)) ;rights] ;parent-rights]))
                  
                  (test-macaron
                    (do
                      (print "hello" "there")
                      (print !$))
                    (do
                      (print "hello" "there")
                      (print "there")))
                  

                  You could also rewrite both expressions into a single gensym’d let expression so that the argument only actually gets evaluated once.

                  (defn drop-last [list]
                    (take (- (length list) 1) list))
                  
                  (defmacaron !$ [& lefts] [& rights]
                    (macaron [& parent-lefts] [& parent-rights]
                      (def previous-sibling (last parent-lefts))
                      (def up-to-previous-sibling (drop-last parent-lefts))
                      (def referent (last previous-sibling))
                      (with-syms [$x]
                        ~(,;up-to-previous-sibling
                          (let [,$x ,referent]
                            (,;(drop-last previous-sibling) ,$x)
                            (,;lefts ,$x ,;rights))
                          ,;parent-rights))))
                  
                  (test-macaroni
                    (do
                      (print "hello" "there")
                      (print !$))
                    (do
                      (let
                        [<1> "there"]
                        (print "hello" <1>)
                        (print <1>))))
                  

                  I think this is pretty interesting? Maybe possibly even useful, to add debugging output or something?

                  At the repl Janet assigns _ to the result of the previous expression – you could do that in arbitrary code; implicitly surrounding the previous expression with (def _ ...) if you use _ in an expression. Hmm. Not super useful…

                  Funny how having to dispatch on the set literal kinda resembles the limitations of a system invoked by set itself, but it’s progress

                  Yeah, but it allows you to “extend” the behavior of set without set having to know anything about your custom extension (or even knowing that it is itself extensible!). But the evaluation order is problematic. Hmm.

    4. 3

      Probably some hiking/road biking.

      1. 2

        Update: ticked off both from the list.

    5. 2

      Maybe continue messing around with reverse engineering Emperor: Battle for Dune. I’m trying to piece together enough useful patches to get a few multiplayer games going with some friends over the internet. I have kinda-working high res support (it works, but 4:3 only, with black bars), fixed the frame rate to 60 to prevent various things from breaking, and managed to lock the cursor to the window so edge scrolling works properly. I also found and reenabled a “compiled out” debug log function, that was fun. Thinking I might try to hack the lan lobby chat to allow connect via ip next.

    6. 1

      So far, some quality of life improvements to prosodyctl shell (together with @MattJ) and tried out a new fixed F1.4 lens (mmmm such blurrrrr).

    7. 1

      It’s the start of a week off, so for this Easter bank holiday it’s starting to relax after a busy few months going through - but being safe from - redundancies at my company.

      I’ll be hacking a bit on https://dmd.tanna.dev, a set of Go tooling for working out how Open Source + private internal libraries are used across your organisation

    8. 1

      Testing out ChatGPT Plus by implementing a password reset on my site. So far it has been good but I feel my brain is less “in it” when using code generation, so I am afraid I might miss an edge case.

      Besides that I’m going to watch UFC, do a qigong class, and do something nice for my dog.

    9. 1

      Watching the Revision stream and planning our next demo.

    10. 1

      Turns out I’m retiring FCP and learning Davinci Resolve. Also relearning how to walk.

      And some general chocolate egg stuff.

    11. 1

      Taking some much-needed time away from coding to look at my various personal projects from a higher level for planning and prioritization. And also some editing of photos I took at Capitol Reef earlier this week.

    12. 1

      As little as possible, from now on. Currently settling on the sofa to rest & watch School of Rock, after wearing myself out dinghy sailing earlier.

      Will practice guitar and maybe explore making a simple site with the Clojure Duct framework. I wrote the core of a non-trivial board game I love months ago, and want to see if I can build an html frontend for it. (It’s not public, as that would probably be a copyright violation.)

    13. 1

      I’ll probably spend a little time in the evening giving a go to adding a game element to the GPT-based city building I’ve been doing. There’s a bunch of pieces to get together, but I have this feeling there will be a gestalt moment once it’s together with GPT running a lot of the core game logic with a lot of the canonical data being in natural language. Like a typical game has rules that are highly reductive, so that higher-level concepts (relationships, objects, ownership, mutual exchanges) have to be represented in terms of a small number of core quantitative concepts or strict relationships. But when it runs on natural language maybe all that depth doesn’t have to be compressed into a small number of attributes.

      Anyway, I don’t know if it’ll really work out like I hope but I think it could.