I am making a tic tac toe game and have made a protocol for my Strategy. The game is running fine, so I want to take this opportunity to hone my core.typed skills. I have annotated the protocol (as shown below), but when I run (cf method-name)
or (cf protocol-name)
in the repl, I get this error:
eg:
=> `(cf win)`
clojure.lang.ExceptionInfo: Type Checker: Found 1 error :: {:type-error :top-level-error, :errors (#<ExceptionInfo clojure.lang.ExceptionInfo: Unannotated var tic-tac-toe.protocol/win
Hint: Add the annotation for tic-tac-toe.protocol/win via check-ns or cf {:env {:file "/Users/jessediaz/Documents/workspace/tic-tac-toe/src/tic_tac_toe/protocol.clj", :column 5, :line 47}, :form win, :type-error :clojure.core.typed.errors/tc-error-parent}>)}
I have checked to make sure that the version of protocol is in fact core.typed/protocol. The console barked at me when I used protocol> saying the syntax was deprecated. I have also looked through the documentation on both the github page and clojure-doc.org. This is how I learned that there is an optional :methods
keyword that I can use to map methods to types. I feel that this might remove a lot of repetition from my code, but I haven't been able to find any examples of its usage. the main strategy methods in the protocol all have side effects and return nil
. The validation methods either return nil
or the original Strategy
methods that they validating. I am not sure I have the syntax right there, but the code is evaluating fine in LightTable, with or without the Fn
signature, and they the core.typed wiki implies that it is not always necessary.
I feel like I am on the cusp here in learning this amazing library and would appreciate any insightful advice that could help my understanding.
protocol.clj file:
(ns tic-tac-toe.protocol
(:require [clojure.core.typed :refer :all]))
(ann-protocol Strategy
win (Fn [Strategy -> nil])
block (Fn [Strategy -> nil])
fork (Fn [Strategy -> nil])
block-fork (Fn [Strategy -> nil])
take-center (Fn [Strategy -> nil])
take-opposite-corner (Fn [Strategy -> nil])
take-corner (Fn [Strategy -> nil])
take-side (Fn [Strategy -> nil])
can-win? (Fn [Strategy -> (U nil (Fn [Strategy -> nil]))])
can-block? (Fn [Strategy -> (U nil (Fn [Strategy -> nil]))])
can-fork? (Fn [Strategy -> (U nil (Fn [Strategy -> nil]))])
can-block-fork? (Fn [Strategy -> (U nil (Fn [Strategy -> nil]))])
can-take-center? (Fn [Strategy -> (U nil (Fn [Strategy -> nil]))])
can-take-corner? (Fn [Strategy -> (U nil (Fn [Strategy -> nil]))])
can-take-side? (Fn [Strategy -> (U nil (Fn [Strategy -> nil]))]))
(defprotocol Strategy
"Strategy methods update the Tic-tac-toe board when they are called"
;; strategies
(win [_] "wins the game by filling an open space to get 3 in a row")
(block [_] "blocks an opponents win by filling an open space")
(fork [_] "creates a two way win scenario guaranteeing victory")
(block-fork [_] "prevents an opponent from forking")
(take-center [_] "takes center")
(take-opposite-corner [_] "takes a corner opposite to one the computer already has")
(take-corner [_] "takes an avaiable corner")
(take-side [_] "takes an available side")
;; tests
(can-win? [_])
(can-block? [_])
(can-fork? [_])
(can-block-fork? [_])
(can-take-center? [_])
(can-take-opposite-corner? [_])
(can-take-corner? [_])
(can-take-side? [_]))
I suspect you need to
check-ns
the current namespace before querying it withcf
. Evaluation of typed code does not trigger type checking or annotation collection.The
ann-protocol
is not needed here,clojure.core.typed/defprotocol
supports inline annotation.Try something like: