(range...)
This commit is contained in:
@@ -83,6 +83,14 @@ class Macros {
|
|||||||
CallExp(Symbol("Reflect.callMethod").withPosOf(wholeExp), [callOn, func, args]).withPosOf(wholeExp);
|
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) {
|
function bodyIf(formName:String, negated:Bool, wholeExp:ReaderExp, args:Array<ReaderExp>, k) {
|
||||||
wholeExp.checkNumArgs(2, null, '($formName [condition] [body...])');
|
wholeExp.checkNumArgs(2, null, '($formName [condition] [body...])');
|
||||||
var condition = if (negated) {
|
var condition = if (negated) {
|
||||||
|
|||||||
@@ -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) {
|
public static dynamic function truthy(v:Any) {
|
||||||
return switch (Type.typeof(v)) {
|
return switch (Type.typeof(v)) {
|
||||||
case TNull: false;
|
case TNull: false;
|
||||||
|
|||||||
@@ -246,6 +246,10 @@ class BasicTestCase extends Test {
|
|||||||
function testMaps() {
|
function testMaps() {
|
||||||
_testMaps();
|
_testMaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testRange() {
|
||||||
|
_testRange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicObject {
|
class BasicObject {
|
||||||
|
|||||||
@@ -349,8 +349,22 @@
|
|||||||
(doFor =>key value myMap
|
(doFor =>key value myMap
|
||||||
(Assert.isTrue (<= 0 (.indexOf ["hey" "found"] key)))
|
(Assert.isTrue (<= 0 (.indexOf ["hey" "found"] key)))
|
||||||
(Assert.isTrue (<= 0 (.indexOf ["you" "me"] value))))
|
(Assert.isTrue (<= 0 (.indexOf ["you" "me"] value))))
|
||||||
|
|
||||||
// Map destructuring:
|
// Map destructuring:
|
||||||
(let [[=>"hey" v1 =>"found" v2] myMap]
|
(let [[=>"hey" v1 =>"found" v2] myMap]
|
||||||
(Assert.equals "you" v1)
|
(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)))
|
||||||
Reference in New Issue
Block a user