view 6-Clojure/bearings.clj @ 93:39084e2b8744

Add a function for word-aware text wrapping Potentially hugely inefficient because we iterate through the string character by character, but then splitting it first and iterating over words still needs to iterate over the string to know where to split.
author IBBoard <dev@ibboard.co.uk>
date Tue, 18 Jun 2019 21:05:00 +0100
parents eccc649d49a2
children
line wrap: on
line source

; Based on Compass
(def directions [:north :east :south :west])

; Define a "fixed movement" protocol - "m" is effectively "this"
(defprotocol FixedMovement
    (direction [m]) ; Find your current direction
    (left [m]) ; turn left one position
    (right [m])) ; turn right one position

; Define an implementation with a single field (not a parameter - although it's defined the same)
(defrecord CompassBearings [bearing]
    ; Specify which protocol we're implementing
    FixedMovement
    ; And define the methods
    (direction [_] (directions bearing)) ; Look-up our index in the list
    ; Clojure uses immutable values, so these functions create new CompassBearing objects
    (left [_] (CompassBearings. (mod (- bearing 1) (count directions)))) ; Create a new instance (ClassName.) with a value from rotating one slot left
    (right [_] (CompassBearings. (mod (+ bearing 1) (count directions))))
    ; And we can specify more
    Object
    (toString [this] (str "[" (direction this) "]")) ; Presumably we could also call (directions bearing) directly.
    ; We have to pass something to (direction) because we're doing functions and so can't do "obj.function()" to keep the reference to what we're getting directions of.
    )

; Define a thing that has bearings - e.g. an actor in a scene
; It'd be nice if we could do an automated default so that we're not passing in magic numbers
(def actor (CompassBearings. 0))
(println actor) ; Prints default internal format
(println (:bearing actor)) ; Access a field using the keyword as a function. Because keywords with meaning happen EVERYWHERE in Clojure!
(println (str actor)) ; Uses our toString method
(println (str (left actor)))
(println (str (right (right actor))))