Repository: hylang/hy

Issue:
Unary `cut` is inconsistent with `slice` and `itertools.islice`
```
=> (setv s "abcdefg")
=> (get s (slice 2))
'ab'
=> (import [itertools [islice]])
=> (.join "" (islice s 2))
'ab'
=> (cut s 2)
'cdefg'
```


Discussion:

Resolving patch:
diff --git a/hy/compiler.py b/hy/compiler.py
--- a/hy/compiler.py
+++ b/hy/compiler.py
@@ -865,6 +865,12 @@ def c(e):
             ret[0] += self.compile(e)
             return ret[0].force_expr
 
+        if upper is None:
+            # cut with single index is an upper bound,
+            # this is consistent with slice and islice
+            upper = lower
+            lower = Symbol('None')
+
         s = asty.Subscript(
             expr,
             value=c(obj),


Test patch:
diff --git a/tests/native_tests/comprehensions.hy b/tests/native_tests/comprehensions.hy
--- a/tests/native_tests/comprehensions.hy
+++ b/tests/native_tests/comprehensions.hy
@@ -84,9 +84,9 @@
     ; Mutate the case as appropriate for the operator before
     ; evaluating it.
     (setv expr (+ (hy.models.Expression
-                    [(hy.models.Symbol specialop)]) (cut expr 1)))
+                    [(hy.models.Symbol specialop)]) (cut expr 1 None)))
     (when (= specialop "dfor")
-      (setv expr (+ (cut expr 0 -1) `([~(get expr -1) 1]))))
+      (setv expr (+ (cut expr -1) `([~(get expr -1) 1]))))
     (when (= specialop "for")
       (setv expr `(do
         (setv out [])
diff --git a/tests/native_tests/contrib/sequences.hy b/tests/native_tests/contrib/sequences.hy
--- a/tests/native_tests/contrib/sequences.hy
+++ b/tests/native_tests/contrib/sequences.hy
@@ -9,7 +9,7 @@
 
 (defn test-infinite-sequence []
   "NATIVE: test creating infinite sequence"
-  (assert (= (list (cut (seq [n] n) 0 5))
+  (assert (= (list (cut (seq [n] n) 5))
              [0 1 2 3 4])))
 
 (defn test-indexing-sequence []
@@ -66,7 +66,7 @@
   (assert (= (get fibonacci 40)
              102334155)
           "40th element of fibonacci didn't match")
-  (assert (= (list (cut fibonacci 0 9))
+  (assert (= (list (cut fibonacci 9))
              [0 1 1 2 3 5 8 13 21])
           "taking 8 elements of fibonacci didn't match"))
 
@@ -81,7 +81,7 @@
                 prevs)))
     (defn previous-primes [n]
       "previous prime numbers"
-      (cut primes 0 (dec n)))
+      (cut primes (dec n)))
     (defn next-possible-prime [n]
       "next possible prime after nth prime"
       (inc (get primes (dec n))))
@@ -90,6 +90,6 @@
                     (while (divisible? guess (previous-primes n))
                       (setv guess (inc guess)))
                     guess)]))
-  (assert (= (list (cut primes 0 10))
+  (assert (= (list (cut primes 10))
              [2 3 5 7 11 13 17 19 23 29])
           "prime sequence didn't match"))
diff --git a/tests/native_tests/contrib/test_pprint.hy b/tests/native_tests/contrib/test_pprint.hy
--- a/tests/native_tests/contrib/test_pprint.hy
+++ b/tests/native_tests/contrib/test_pprint.hy
@@ -42,8 +42,8 @@
 
   ;; Break the cycles
   (d.clear)
-  (del (cut a))
-  (del (cut b))
+  (del (cut a None))
+  (del (cut b None))
 
   (for [safe (, a b d (, d d))]
     (assert (not (pprint.recursive? safe)))
diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy
--- a/tests/native_tests/language.hy
+++ b/tests/native_tests/language.hy
@@ -762,7 +762,8 @@
 
 (defn test-cut []
   "NATIVE: test cut"
-  (assert (= (cut [1 2 3 4 5] 1) [2 3 4 5]))
+  (assert (= (cut [1 2 3 4 5] 3) [1 2 3]))
+  (assert (= (cut [1 2 3 4 5] 1 None) [2 3 4 5]))
   (assert (= (cut [1 2 3 4 5] 1 3) [2 3]))
   (assert (= (cut [1 2 3 4 5]) [1 2 3 4 5])))
 
diff --git a/tests/native_tests/model_patterns.hy b/tests/native_tests/model_patterns.hy
--- a/tests/native_tests/model_patterns.hy
+++ b/tests/native_tests/model_patterns.hy
@@ -39,7 +39,7 @@
     (many FORM)]))))
   (defn f [loopers]
     (setv head (if loopers (get loopers 0)))
-    (setv tail (cut loopers 1))
+    (setv tail (cut loopers 1 None))
     (print head)
     (cond
       [(none? head)
diff --git a/tests/native_tests/native_macros.hy b/tests/native_tests/native_macros.hy
--- a/tests/native_tests/native_macros.hy
+++ b/tests/native_tests/native_macros.hy
@@ -540,7 +540,7 @@ in expansions."
 
   (setv output (traceback.format_exception_only
                  excinfo.type excinfo.value))
-  (setv output (cut (.splitlines (.strip (get output 0))) 1))
+  (setv output (cut (.splitlines (.strip (get output 0))) 1 None))
 
   (setv expected ["  File \"<string>\", line 1"
                   "    (defmacro blah [x] `(print ~@z)) (blah y)"
diff --git a/tests/native_tests/quote.hy b/tests/native_tests/quote.hy
--- a/tests/native_tests/quote.hy
+++ b/tests/native_tests/quote.hy
@@ -21,7 +21,7 @@
   "NATIVE: check whether quote works on hoisted things"
   (setv f (quote (if True True True)))
   (assert (= (get f 0) (quote if)))
-  (assert (= (cut f 1) (quote (True True True)))))
+  (assert (= (cut f 1 None) (quote (True True True)))))
 
 
 (defn test-quoted-macroexpand []
@@ -30,7 +30,7 @@
   (setv q2 (quasiquote (-> a b c)))
   (assert (= q1 q2))
   (assert (= (get q1 0) (quote ->)))
-  (assert (= (cut q1 1) (quote (a b c)))))
+  (assert (= (cut q1 1 None) (quote (a b c)))))
 
 
 (defn test-quote-dicts []
diff --git a/tests/resources/bin/main.hy b/tests/resources/bin/main.hy
--- a/tests/resources/bin/main.hy
+++ b/tests/resources/bin/main.hy
@@ -1,5 +1,5 @@
 (defmain [#* args]
-  (print (+ "<" (.join "|" (cut args 1)) ">"))
+  (print (+ "<" (.join "|" (cut args 1 None)) ">"))
   (print "Hello World")
   (if (in "exit1" args)
     1))