Skip to content

Instantly share code, notes, and snippets.

@milesrout
Last active August 29, 2015 14:24
Show Gist options
  • Save milesrout/b72afd9594d81ea6e7f8 to your computer and use it in GitHub Desktop.
Save milesrout/b72afd9594d81ea6e7f8 to your computer and use it in GitHub Desktop.
namespace std {
using numeric_range = struct { min,max,stride: int };
// provide an implementation of the Range concept for numeric_range
impl Range<numeric_range> {
using iterator = struct { min,stride: int };
using sentinel = struct { max: int };
let begin(nr: numeric_range) => iterator{nr.min, nr.stride};
let end(nr: numeric_range) => sentinel{nr.max};
let next(iter: iterator) => iterator{iter.min + iter.stride, iter.stride};
let current(iter: iterator) => iter.min;
let __neq__(iter: iterator, sent: sentinel) => (iter.min < sent.max);
};
let range(min,max,stride=1: int) => numeric_range{min, max, stride};
}
// prints "1\n2\n3\n4\n5\n6\n7\n8\n9\n10"
let main(args: []string) {
for x in range(0,10).map(i => i + 1) {
"%d\n".printf(x);
}
}
@RnaodmBiT
Copy link

You've mixed up your case with the Range on line 5
You have nr defined but never use it

what is the point of the impl syntax?

@RnaodmBiT
Copy link

using numeric_range = struct { start, end, step, current: int };

let range(start, end, step=1: int) => numeric_range.new(start, end, step, end == start ? null : start);

let next(range: numeric_range) {
    if (range.current != range.end) {
        return numeric_range.new(range.start, range.end, range.step, range.current + range.step);
    }
    numeric_range.new(range.start, range.end, range.step, null); // indicate that the iteration is over (use whatever you want, this is just a simple example)
}

let map(range: numeric_range, fn: (int) -> int) {
    foreach (let x in numeric_range) {
        yield fn(x);
    }
}

let main(args: []string) {
    foreach (let x in range(0, 10)) {
        printf("%d ", x); // 0 1 2 3 4 5 6 7 8 9
    }
    foreach (let x in range(10, 20).map(i => i + 5)) {
        printf("%d ", x); // 15 16 17 18 19 20 21 22 23 24
    }
}

Define foreach as something like

while (it.current) {
    fn(it.current);
    it = it.next();
}

where it is a templated iterator which conforms to the .next and .current behaviour
and fn is the code block of the foreach

I think so long as a template specialization exists for the object being used as an iterator, it should be fine
If it doesnt exist, throw errors

@milesrout
Copy link
Author

Range is a concept, and concepts use CamelCase names, as do type parameters.

nr was used then I changed it.

impl indicates that a particular type (in this case, numeric_range) fulfils the contract of a given concept (in this case Range).

Ranges are things that you can call begin and end on to get an iterator and a sentinel respectively, which might be the same type. e.g. for a raw array, the begin is a raw pointer to the first element and end is a raw pointer to the last element. for a string, the begin is a pointer to the first element and the length seen so far, while the end is just the length.

map is a generic function that works the same for all Ranges:

let map<R,T>(r: R, f: R.value_type -> T)
    where Range<R> && T != void
{
    let first = r.begin;
    let last = r.end;
    while (first != last) {
        yield f(t);
    }
}

or similar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment