diff --git a/spec/primitives.sx b/spec/primitives.sx index 70cf5177..4cf7dd56 100644 --- a/spec/primitives.sx +++ b/spec/primitives.sx @@ -43,35 +43,35 @@ "+" :params (&rest (args :as number)) :returns "number" - :doc "Sum all arguments." + :doc "Sum all arguments. Returns integer iff all args are exact integers (float contagion)." :body (reduce (fn (a b) (native-add a b)) 0 args)) (define-primitive "-" :params ((a :as number) &rest (b :as number)) :returns "number" - :doc "Subtract. Unary: negate. Binary: a - b." + :doc "Subtract. Unary: negate. Binary: a - b. Float contagion: returns integer iff all args are integers." :body (if (empty? b) (native-neg a) (native-sub a (first b)))) (define-primitive "*" :params (&rest (args :as number)) :returns "number" - :doc "Multiply all arguments." + :doc "Multiply all arguments. Float contagion: integer result iff all args are exact integers." :body (reduce (fn (a b) (native-mul a b)) 1 args)) (define-primitive "/" :params ((a :as number) (b :as number)) - :returns "number" - :doc "Divide a by b." + :returns "float" + :doc "Divide a by b. Always returns inexact float." :body (native-div a b)) (define-primitive "mod" :params ((a :as number) (b :as number)) :returns "number" - :doc "Modulo a % b." + :doc "Modulo a % b. Returns integer iff both args are integers." :body (native-mod a b)) (define-primitive @@ -108,26 +108,26 @@ (define-primitive "floor" :params ((x :as number)) - :returns "number" - :doc "Floor to integer.") + :returns "integer" + :doc "Floor toward negative infinity — returns exact integer.") (define-primitive "ceil" :params ((x :as number)) - :returns "number" - :doc "Ceiling to integer.") + :returns "integer" + :doc "Ceiling toward positive infinity — returns exact integer.") (define-primitive "round" :params ((x :as number) &rest (ndigits :as number)) :returns "number" - :doc "Round to ndigits decimal places (default 0).") + :doc "Round to ndigits decimal places (default 0). Returns integer when ndigits is 0.") (define-primitive "truncate" - :params (((x :as number))) - :returns "number" - :doc "Truncate toward zero.") + :params ((x :as number)) + :returns "integer" + :doc "Truncate toward zero — returns exact integer.") (define-primitive "remainder" @@ -143,30 +143,30 @@ (define-primitive "exact?" - :params (((x :as number))) + :params ((x :as number)) :returns "boolean" - :doc "True if x is exact (integer-valued).") + :doc "True if x is an exact integer (not an inexact float).") (define-primitive "inexact?" - :params (((x :as number))) + :params ((x :as number)) :returns "boolean" - :doc "True if x is inexact (non-integer).") + :doc "True if x is an inexact float (not an exact integer).") ;; -------------------------------------------------------------------------- ;; Core — Comparison ;; -------------------------------------------------------------------------- (define-primitive "exact->inexact" - :params (((x :as number))) - :returns "number" - :doc "Convert exact to inexact (identity for float tower).") + :params ((x :as number)) + :returns "float" + :doc "Convert exact integer to inexact float. Floats pass through unchanged.") (define-primitive "inexact->exact" - :params (((x :as number))) - :returns "number" - :doc "Convert inexact to nearest exact integer.") + :params ((x :as number)) + :returns "integer" + :doc "Convert inexact float to nearest exact integer (truncates). Integers pass through unchanged.") (define-primitive "make-vector" @@ -374,8 +374,20 @@ "number?" :params (x) :returns "boolean" - :doc "True if x is a number (int or float)." - :body (= (type-of x) "number")) + :doc "True if x is any number — exact integer or inexact float." + :body (or (= (type-of x) "number") (integer? x))) + +(define-primitive + "integer?" + :params (x) + :returns "boolean" + :doc "True if x is an exact integer, or a float with no fractional part (e.g. 1.0).") + +(define-primitive + "float?" + :params (x) + :returns "boolean" + :doc "True if x is an inexact float (Number type). Does not match exact integers.") (define-primitive "string?"