Merl's Blog

Multi-Methods

For several weeks now I have heard the magic of multi-methods.

I have been focusing so much on completing my work that I have not allowed myself time to learn more and refactor. I have built my code on spaghetti!

Today I will take the small step to learn multi-methods to begin to untangle my code.

(defn board-type [board] (if (two-dimensional? board) :2d :3d))


(defmulti display board-type)


(defmethod display :2d [board]
 (->> board
      rows
      (map separate)
      (str/join "\n")))


(defmethod display :3d [board]
 (->> board
      (partition 9)
      (map display)
      (str/join "\n\n")))

This was my first step. Nice and simple, I have a 3x3 board, a 4x4 board, and now a 3x3x3 board.

I needed to change the display depending on the 1-D board that I passed through. Initially I had a few functions that did not look this nice. I am very pleased.

One last multi-method that I tried today.

(defmulti winner? (fn [board _letter] (board-type board)))


(defmethod winner? :2d [grid letter]
 (or (winning-lines? letter (rows grid))
     (winning-lines? letter (diagonals grid))
     (winning-lines? letter (columns grid))))


(defmethod winner? :3d [grid letter]
 (let [faces (partition 9 grid)]
   (or
     (some #(winner? % letter) faces)
     (some #(winning-combo? grid % letter) edge-cases-3d)
     (winning-lines? letter (same-space-all-faces grid))
     (winning-lines? letter (back-diagonal-through grid))
     (winning-lines? letter (back-diagonal-across grid))
     (winning-lines? letter (front-diagonal-across grid))
     (winning-lines? letter (front-diagonal-through grid)))))


It is a multi-dimensional kind of day.

I have been focusing on providing my board and providing the winning conditions based on if the board is 2-D or 3-D.

These were great beginner ways to get started on multi-methods!

Best,

Merl