(range...)

This commit is contained in:
2020-12-07 19:12:22 -07:00
parent 6866c7133d
commit 74d070d7b3
4 changed files with 45 additions and 2 deletions

View File

@@ -83,6 +83,14 @@ class Macros {
CallExp(Symbol("Reflect.callMethod").withPosOf(wholeExp), [callOn, func, args]).withPosOf(wholeExp);
};
macros["range"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
wholeExp.checkNumArgs(1, 3, '(range [?min] [max] [?step])');
var min = if (exps.length > 1) exps[0] else Symbol("0").withPosOf(wholeExp);
var max = if (exps.length > 1) exps[1] else exps[0];
var step = if (exps.length > 2) exps[2] else Symbol("1").withPosOf(wholeExp);
CallExp(Symbol("Prelude.range").withPosOf(wholeExp), [min, max, step]).withPosOf(wholeExp);
};
function bodyIf(formName:String, negated:Bool, wholeExp:ReaderExp, args:Array<ReaderExp>, k) {
wholeExp.checkNumArgs(2, null, '($formName [condition] [body...])');
var condition = if (negated) {

View File

@@ -186,6 +186,23 @@ class Prelude {
];
}
// Ranges with a min, exclusive max, and step size, just like Python.
public static function range(min, max, step):Iterator<Int> {
if (step <= 0)
throw "(range...) can only count up";
var count = min;
return {
next: () -> {
var oldCount = count;
count += step;
oldCount;
},
hasNext: () -> {
count < max;
}
};
}
public static dynamic function truthy(v:Any) {
return switch (Type.typeof(v)) {
case TNull: false;

View File

@@ -246,6 +246,10 @@ class BasicTestCase extends Test {
function testMaps() {
_testMaps();
}
function testRange() {
_testRange();
}
}
class BasicObject {

View File

@@ -349,8 +349,22 @@
(doFor =>key value myMap
(Assert.isTrue (<= 0 (.indexOf ["hey" "found"] key)))
(Assert.isTrue (<= 0 (.indexOf ["you" "me"] value))))
// Map destructuring:
(let [[=>"hey" v1 =>"found" v2] myMap]
(Assert.equals "you" v1)
(Assert.equals "me" v2)))
(Assert.equals "me" v2)))
(defun _testRange []
// With just one arg, it's the max:
(deflocal &mut :kiss.List<Int> myList (for i (range 5) i))
(Assert.equals 4 (nth myList -1))
// with two args, they are min and max:
(set myList (for i (range 3 5) i))
(Assert.equals 3 (first myList))
(Assert.equals 4 (last myList))
// With three args, they are min, max, and step:
(set myList (for i (range 7 17 2) i))
(Assert.equals 7 (first myList))
(Assert.equals 9 (second myList))
(Assert.equals 15 (last myList)))