Don't check the type of arguments to inc, odd?, etc.

This allows them to be used with numeric types that aren't built in, such as NumPy arrays. Because Python uses duck typing, there's generally no way to know in advance whether a given value will accept a given operator. Of course, things like `(inc "hello")` will still raise a `TypeError`, because so does `(+ "hello" 1)`.
This commit is contained in:
Kodi Arfer 2016-10-11 14:04:50 -07:00
parent 11481aba78
commit 4b0296d257
2 changed files with 16 additions and 54 deletions

View File

@ -39,10 +39,6 @@
(import [hy.lex [LexException PrematureEndOfInput tokenize]])
(import [hy.compiler [HyASTCompiler]])
(defn _numeric-check [x]
(if (not (numeric? x))
(raise (TypeError (.format "{0!r} is not a number" x)))))
(defn butlast [coll]
"Returns coll except of last element."
(drop-last 1 coll))
@ -66,7 +62,6 @@
(defn dec [n]
"Decrement n by 1"
(_numeric-check n)
(- n 1))
(defn disassemble [tree &optional [codegen false]]
@ -170,7 +165,6 @@
(defn even? [n]
"Return true if n is an even number"
(_numeric-check n)
(= (% n 2) 0))
(defn every? [pred coll]
@ -239,7 +233,6 @@
(defn inc [n]
"Increment n by 1"
(_numeric-check n)
(+ n 1))
(defn instance? [klass x]
@ -325,7 +318,6 @@
(defn neg? [n]
"Return true if n is < 0"
(_numeric-check n)
(< n 0))
(defn none? [x]
@ -347,7 +339,6 @@
(defn odd? [n]
"Return true if n is an odd number"
(_numeric-check n)
(= (% n 2) 1))
(def -sentinel (object))
@ -364,7 +355,6 @@
(defn pos? [n]
"Return true if n is > 0"
(_numeric_check n)
(> n 0))
(defn rest [coll]
@ -415,7 +405,6 @@
(defn zero? [n]
"Return true if n is 0"
(_numeric_check n)
(= n 0))
(defn read [&optional [from-file sys.stdin]

View File

@ -33,6 +33,11 @@
(defn assert-nil [x]
(assert (is x nil)))
(defn assert-requires-num [f]
(for [x ["foo" [] None]]
(assert-true (try (do (f x) False)
(except [e [TypeError]] True)))))
(defn test-coll? []
"NATIVE: testing coll?"
(assert-true (coll? [1 2 3]))
@ -66,12 +71,7 @@
(assert-equal 0 (dec 1))
(assert-equal -1 (dec 0))
(assert-equal 0 (dec (dec 2)))
(try (do (dec "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (dec []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (dec None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num dec))
(defn test-setv []
"NATIVE: testing setv mutation"
@ -173,12 +173,7 @@
(assert-true (even? -2))
(assert-false (even? 1))
(assert-true (even? 0))
(try (even? "foo")
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (even? [])
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (even? None)
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num even?))
(defn test-every? []
"NATIVE: testing the every? function"
@ -263,12 +258,11 @@
"NATIVE: testing the inc function"
(assert-equal 3 (inc 2))
(assert-equal 0 (inc -1))
(try (do (inc "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (inc []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (inc None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num inc)
(defclass X [object]
[__add__ (fn [self other] (.format "__add__ got {}" other))])
(assert-equal (inc (X)) "__add__ got 1"))
(defn test-instance []
"NATIVE: testing instance? function"
@ -394,24 +388,13 @@
(assert-true (neg? -2))
(assert-false (neg? 1))
(assert-false (neg? 0))
(try (do (neg? "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (neg? []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (neg? None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num neg?))
(defn test-zero []
"NATIVE: testing the zero? function"
(assert-false (zero? -2))
(assert-false (zero? 1))
(assert-true (zero? 0))
(try (do (zero? "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (zero? []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (zero? None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-true (zero? 0)))
(defn test-none []
"NATIVE: testing for `is None`"
@ -463,12 +446,7 @@
(assert-true (odd? -3))
(assert-true (odd? 1))
(assert-false (odd? 0))
(try (do (odd? "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (odd? []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (odd? None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num odd?))
(defn test-partition []
"NATIVE: testing the partition function"
@ -500,12 +478,7 @@
(assert-true (pos? 2))
(assert-false (pos? -1))
(assert-false (pos? 0))
(try (do (pos? "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (pos? []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (pos? None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num pos?))
(defn test-remove []
"NATIVE: testing the remove function"