Specifications for function definitions

Specifications for the function definitons can be defined, using the specifications previously defined where relevant.

A function specification can contain a specification for the arguments, the return values and the relationship between the two.

Function definitions

The card game application has three functions to start with.

(defn regulation-card-deck
  "Generate a complete deck of playing cards"
  [{:keys [::deck ::players] :as game}]
  (apply + (count deck)
         (map #(-> % ::delt-hand count) players)))

At the start of function design, the algorithm may still be undefined. Using the specifications and generators mock data can be returned as a placeholder.

(defn deal-cards
  "Deal cards to each of the players
   Returns updated game hash-map"
  (spec-gen/generate (spec/gen ::game)))
(defn winning-player
  "Calculate winning hand by comparing each players hand
  Return winning player"
  (spec-gen/generate (spec/gen ::player)))

Function specification

(spec/fdef deal-cards
  :args (spec/cat :game ::game)
  :ret ::game
  :fn #(= (regulation-card-deck (-> % :args :game))
          (regulation-card-deck (-> % :ret))))
(spec/fdef winning-player
  :args (spec/cat :players ::players)
  :ret ::player)

Instrument functions

Instrumenting functions will wrap a function definition and check the arguments of any call to the instrumented function.

(spec-test/instrument `deal-cards)

Ignore the Warning message in the result, this is an issue with the REPL implementation used in this page.

Calling the deal-cards function with an incorrect argument will return an error, detailing where in the specification the error occured.

(deal-cards "fake game data")

Error in an easier to read format

ERROR: #error
 {:message "Call to #'practicalli.card-game/deal-cards did not conform to spec:\n\
 "fake game data\" - failed:
 map? in: [0] at: [:args :game] spec: :practicalli.card-game/game\n",
 :data {:cljs.spec.alpha/problems
 [{:path [:args :game],
   :pred cljs.core/map?,
   :val "fake game data",
   :via [:practicalli.card-game/game :practicalli.card-game/game],
   :in [0]}],
 :cljs.spec.alpha/spec #object[cljs.spec.alpha.t_cljs$spec$alpha17968],
 :cljs.spec.alpha/value ("fake game data"),
 :cljs.spec.alpha/args ("fake game data"),
 :cljs.spec.alpha/failure :instrument}}

results matching ""

    No results matching ""