2020-06-21

Golfrun reloaded in lisp?

Currently I’m mainly trying to learn more about electronics and hardware, beyond the basic things I already knew (also opened a new Italian blog to dump whatever related — everything indeed begins from my dad’s death and his stuffs). But I never stop to try and learn other things, especially in the software field where I feel more comfortable.

It isn’t good — they say — not to focus on one topic per time: instead, you should put all your efforts in one thing until you master it, and then proceed. I feel overwhelmed by all the things I don’t know but that I would like to know; maybe I think that going straight could make me spend an infinite time on something, because you can’t really hit the bottom: there’s no definite depth, you can’t reach the bottom in a life-time. Hence I tend to erratically jump, or zigzag, from an argument to another, from a path to another. No good, again, also because this way you can’t really master anything. On the other hand, maybe the purpose isn’t to master everything (impossible) but to have a better view of the immensity of things we don’t know and we’ll never know for real. And the purpose could be to have a taste of as many things as possible.

Thus, yes I’m studying about electronics (and exploring software tools to help with that, too), but it is just another new allocated time slot in my limited time — that’s another problem, unfortunately. New slots keep being allocated, reducing the amount of time spent in each slot… Moreover my scheduling algorithm is very chaotic.

Another time slot was recently created for LISP — the computer language. My obsession for (human and computer) languages can’t make me drop all language-related-activities for a new topic. Never been a fan of that family of languages: I’ve played with some scheme and racket, but I don’t really like them. Nonetheless, it’s an importat family of languages and I’ve decided to take a deeper look into it.

So it happened that I’m reading about CLOS and multimethods — LISP has multiple dispatch. And the abandoned golfrun entered my brain as a memory again. In case you want to refreh you memory or learn the relationship between multiple dispatching and Golfrun:

Do not focus on how the feature is called. It doesn’t matter once you get what’s the feature about.

What about the relationship with Golfrun? If you look closely, you can deduce it. In order to avoid wasting your time, here it is: Golfrun has operators heavely overloaded; a + is sum between two numbers, concatenation of two strings, or a concatenation of an integer (converted to string) and a string, or viceversa.

In the first messy, discontinued C implementation all this gave origin to a lot of code I thought to get rid of some of that code using C++ instead of C. But C++ does not support dynamic dispatching on more than one argument: it doesn’t support multiple dispatch, hence I couldn’t write code like this:

  execute_plus(stack.pop(), stack.pop())

leaving to the multiple dynamic dispatching mechanism the duty of selecting the appropriate execute_plus implementation.

In lisp, I could. My first experiment looks like this:

(defgeneric grop-plus (a b)
  (:documentation "Implements +"))

(defmethod grop-plus ((a integer) (b integer))
  (+ a b))

(defmethod grop-plus ((a string) (b string))
  (string-concat a b))

(defmethod grop-plus ((a integer) (b string))
  (string-concat (write-to-string a) b))

The last defmethod must be written also with those two arguments swapped. This opens the road to the use of the lisp macro system: I imagine a macro which defines two methods with the role of arguments swapped.

So far I came up with this:

(defmacro gen-sym-op (op-name arg-a arg-b trasf-a trasf-b comb)
  `(progn
     (defmethod ,op-name (,arg-a ,arg-b)
       (,comb (,trasf-a ,(first arg-a))
              (,trasf-b ,(first arg-b))))
     (defmethod ,op-name (,arg-b ,arg-a)
       (,comb (,trasf-b ,(first arg-b))
              (,trasf-a ,(first arg-a))))))

It’s still work-in-progress, but the first test seems promising. (The macro likely is fragile, though).

(gen-sym-op grop-plus
            (a integer) (b string)
            write-to-string
            identity
            string-concat)

(format t "~a~%" (grop-plus 5 "hello"))
(format t "~a~%" (grop-plus "hello" 5))

The output looks good…

No comments:

Post a comment