diff --git a/docs/language/core.rst b/docs/language/core.rst index d655dd3..d0118b1 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -15,6 +15,8 @@ Usage: ``(dec x)`` Return one less than x. Equivalent to ``(- x 1)``. +Raises ``TypeError`` if ``(not (numeric? x))``. + .. code-block:: clojure => (dec 3) @@ -27,6 +29,45 @@ Return one less than x. Equivalent to ``(- x 1)``. 11.3 +.. _emtpy?-fn: + +empty? +------ + +Usage: ``(empty? coll)`` + +Return True if ``coll`` is empty, i.e. ``(= 0 (len coll))``. + +.. code-block:: clojure + + => (empty? []) + True + + => (empty? "") + True + + => (empty? (, 1 2)) + False + + +.. _float?-fn: + +float? +------- + +Usage: ``(float? x)`` + +Return True if x is a float. + +.. code-block:: clojure + + => (float? 3.2) + True + + => (float? -2) + False + + .. _even?-fn: even? @@ -36,6 +77,8 @@ Usage: ``(even? x)`` Return True if x is even. +Raises ``TypeError`` if ``(not (numeric? x))``. + .. code-block:: clojure => (even? 2) @@ -57,6 +100,8 @@ Usage: ``(inc x)`` Return one more than x. Equivalent to ``(+ x 1)``. +Raises ``TypeError`` if ``(not (numeric? x))``. + .. code-block:: clojure => (inc 3) @@ -94,6 +139,24 @@ Return True if x is an instance of CLASS. => (instance? TestClass inst) True +.. _integer?-fn: + +integer? +-------- + +Usage: ``(integer? x)`` + +Return True if x is an integer. For Python 2, this is +either ``int`` or ``long``. For Python 3, this is ``int``. + +.. code-block:: clojure + + => (integer? 3) + True + + => (integer? -2.4) + False + .. _iterable?-fn: @@ -166,6 +229,8 @@ Usage: ``(neg? x)`` Return True if x is less than zero (0). +Raises ``TypeError`` if ``(not (numeric? x))``. + .. code-block:: clojure => (neg? -2) @@ -228,6 +293,28 @@ if the `n` is outside the range of `coll`. => (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2)) 5 +.. _numeric?-fn: + +numeric? +--------- + +Usage: ``(numeric? x)`` + +Return True if x is a numeric, as defined in the Python +numbers module class ``numbers.Number``. + +.. code-block:: clojure + + => (numeric? -2) + True + + => (numeric? 3.2) + True + + => (numeric? "foo") + False + + .. _odd?-fn: odd? @@ -237,6 +324,8 @@ Usage: ``(odd? x)`` Return True if x is odd. +Raises ``TypeError`` if ``(not (numeric? x))``. + .. code-block:: clojure => (odd? 13) @@ -258,6 +347,8 @@ Usage: ``(pos? x)`` Return True if x is greater than zero (0). +Raises ``TypeError`` if ``(not (numeric? x))``. + .. code-block:: clojure => (pos? 3) @@ -290,6 +381,39 @@ Return True if x is zero (0). => (zero? 0) True +.. _second-fn: + +second +------- + +Usage: ``(second coll)`` + +Return the second member of ``coll``. Equivalent to +``(get coll 1)`` + +.. code-block:: clojure + + => (second [0 1 2]) + 1 + + +.. _string?-fn: + +string? +------- + +Usage: ``(string? x)`` + +Return True if x is a string. + +.. code-block:: clojure + + => (string? "foo") + True + + => (string? -2) + False + Sequence Functions ======================= @@ -410,6 +534,27 @@ Return an iterator, skipping the first ``n`` members of ``coll`` => (list (drop 6 [1 2 3 4 5])) [] +.. _drop-while-fn: + +drop-while +----------- + +Usage: ``(drop-while pred coll)`` + +Return an iterator, skipping members of ``coll`` until ``pred`` +is False. + +.. code-block:: clojure + + => (list (drop-while even? [2 4 7 8 9])) + [7, 8, 9] + + => (list (drop-while numeric? [1 2 3 None "a"]))) + [None, u'a'] + + => (list (drop-while pos? [2 4 7 8 9])) + [] + .. _filter-fn: diff --git a/hy/core/language.hy b/hy/core/language.hy index 9768c39..4e9d81a 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -1,8 +1,28 @@ +;; Copyright (c) 2013 Paul Tagliamonte +;; Copyright (c) 2013 Bob Tolbert + +;; Permission is hereby granted, free of charge, to any person obtaining a +;; copy of this software and associated documentation files (the "Software"), +;; to deal in the Software without restriction, including without limitation +;; the rights to use, copy, modify, merge, publish, distribute, sublicense, +;; and/or sell copies of the Software, and to permit persons to whom the +;; Software is furnished to do so, subject to the following conditions: + +;; The above copyright notice and this permission notice shall be included in +;; all copies or substantial portions of the Software. + +;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +;; DEALINGS IN THE SOFTWARE. + ;;;; This contains some of the core Hy functions used ;;;; to make functional programming slightly easier. ;;;; - (defn _numeric-check [x] (if (not (numeric? x)) (raise (TypeError (.format "{0!r} is not a number" x))))) @@ -40,6 +60,20 @@ (catch [StopIteration])) citer)) +(defn drop-while [pred coll] + "Drop all elements of `coll` until `pred` is False" + (let [[citer (iter coll)]] + (let [found false] + (for [val citer] + (if (not (pred val)) + (setv found true)) + (if found + (yield val)))))) + +(defn empty? [coll] + "Return True if `coll` is empty" + (= 0 (len coll))) + (defn even? [n] "Return true if n is an even number" (_numeric-check n) @@ -52,6 +86,10 @@ (if (pred val) (yield val))))) +(defn float? [x] + "Return True if x is float" + (isinstance x float)) + (defn inc [n] "Increment n by 1" (_numeric-check n) @@ -60,6 +98,13 @@ (defn instance? [klass x] (isinstance x klass)) +(defn integer? [x] + "Return True if x in an integer" + (import sys) + (if (< (get sys.version_info 0) 3) + (isinstance x (, int long))) + (isinstance x int)) + (defn iterable? [x] "Return true if x is iterable" (try (do (iter x) true) @@ -128,6 +173,17 @@ (while true (yield (func)))) +(defn second [coll] + "Return second item from `coll`" + (get coll 1)) + +(defn string? [x] + "Return True if x is a string" + (import sys) + (if (< (get sys.version_info 0) 3) + (isinstance x (, str unicode)) + (isinstance x str))) + (defn take [count coll] "Take `count` elements from `coll`, or the whole set if the total number of entries in `coll` is less than `count`." @@ -159,7 +215,9 @@ (_numeric_check n) (= n 0)) -(def *exports* ["cycle" "dec" "distinct" "drop" "even?" "filter" "inc" - "instance?" "iterable?" "iterate" "iterator?" "neg?" +(def *exports* ["cycle" "dec" "distinct" "drop" "drop_while" "empty?" + "even?" "filter" "float?" "inc" + "instance?" "integer?" "iterable?" "iterate" "iterator?" "neg?" "none?" "nth" "numeric?" "odd?" "pos?" "remove" "repeat" - "repeatedly" "take" "take_nth" "take_while" "zero?"]) + "repeatedly" "second" "string?" "take" "take_nth" "take_while" + "zero?"]) diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy index 3bb115b..6e81f39 100644 --- a/tests/native_tests/core.hy +++ b/tests/native_tests/core.hy @@ -1,4 +1,23 @@ -(import time) +;; Copyright (c) 2013 Paul Tagliamonte +;; Copyright (c) 2013 Bob Tolbert + +;; Permission is hereby granted, free of charge, to any person obtaining a +;; copy of this software and associated documentation files (the "Software"), +;; to deal in the Software without restriction, including without limitation +;; the rights to use, copy, modify, merge, publish, distribute, sublicense, +;; and/or sell copies of the Software, and to permit persons to whom the +;; Software is furnished to do so, subject to the following conditions: + +;; The above copyright notice and this permission notice shall be included in +;; all copies or substantial portions of the Software. + +;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +;; DEALINGS IN THE SOFTWARE. ;;;; some simple helpers @@ -62,6 +81,28 @@ (setv res (list (take 5 (drop 2 (iterate inc 0))))) (assert-equal res [2 3 4 5 6])) +(defn test-drop-while [] + "NATIVE: testing drop-while function" + (setv res (list (drop-while even? [2 4 7 8 9]))) + (assert (= res [7 8 9])) + (setv res (list (drop-while pos? [2 4 7 8 9]))) + (assert (= res [])) + (setv res (list (drop-while numeric? [1 2 3 None "a"]))) + (assert (= res [None "a"]))) + +(defn test-empty? [] + "NATIVE: testing the empty? function" + (assert-true (empty? "")) + (assert-false (empty? "None")) + (assert-true (empty? (,))) + (assert-false (empty? (, None))) + (assert-true (empty? [])) + (assert-false (empty? [None])) + (assert-true (empty? {})) + (assert-false (empty? {"a" None})) + (assert-true (empty? (set))) + (assert-false (empty? (set [None])))) + (defn test-even [] "NATIVE: testing the even? function" (assert-true (even? -2)) @@ -92,6 +133,14 @@ (setv res (list (filter none? [1 2 None 3 4 None 4 6]))) (assert-equal res [None None])) +(defn test-float? [] + "NATIVE: testing the float? function" + (assert-true (float? 4.2)) + (assert-false (float? 0)) + (assert-false (float? -3)) + (assert-true (float? -3.2)) + (assert-false (float? "foo"))) + (defn test-inc [] "NATIVE: testing the inc function" (assert-equal 3 (inc 2)) @@ -117,6 +166,15 @@ (assert-true (instance? int 3)) (assert-true (instance? str (str "hello")))) +(defn test-integer? [] + "NATIVE: testing the integer? function" + (assert-true (integer? 0)) + (assert-true (integer? 3)) + (assert-true (integer? -3)) + (assert-false (integer? 4.2)) + (assert-false (integer? None)) + (assert-false (integer? "foo"))) + (defn test-iterable [] "NATIVE: testing iterable? function" ;; should work for a string @@ -213,6 +271,15 @@ (assert-true (none? (nth (iter [1 2 4 7]) -1))) (assert-equal 5 (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2))) +(defn test-numeric? [] + "NATIVE: testing the numeric? function" + (assert-true (numeric? 1)) + (assert-true (numeric? 3.4)) + (assert-true (numeric? 0.0)) + (assert-true (numeric? -1.45)) + (assert-false (numeric? "Foo")) + (assert-false (numeric? None))) + (defn test-odd [] "NATIVE: testing the odd? function" (assert-true (odd? -3)) @@ -262,6 +329,19 @@ (assert-equal (list (take 4 r)) [5 5 5 5]) (assert-equal (list (take 6 r)) [5 5 5 5 5 5])) +(defn test-second [] + "NATIVE: testing second" + (assert-equal 2 (second [1 2])) + (assert-equal 3 (second [2 3 4]))) + +(defn test-string? [] + "NATIVE: testing string?" + (assert-true (string? "foo")) + (assert-true (string? "")) + (assert-false (string? 5.3)) + (assert-true (string? (str 5.3))) + (assert-false (string? None))) + (defn test-take [] "NATIVE: testing the take function" (setv res (list (take 3 [1 2 3 4 5])))