-
Notifications
You must be signed in to change notification settings - Fork 120
Using iterators
An iterator is an object that enables a programmer to traverse some data types in MY-BASIC. You may implement generator or just traverse all values with it.
Use the ITERATOR
statement to get an iterator value; then use MOVE_NEXT
to check whether an iteration finishes; you may use GET
, and VAL
to get details of current step.
It also offers ability to traverse all elements with a FOR
statement.
Iterate a list with an explicit pattern:
l = list(1, 1, 2, 3, 5, 8)
i = iterator(l)
while move_next(i)
print get(i);
wend
An increasing by 1 ranged iteration, with a FOR
loop:
for i in list(1 to 5)
print i;
next
A decreasing by 1 ranged iteration, with a FOR
loop:
for i in list(5 to 1)
print i;
next
Use the GET
statement to get the key of a dictionary iterator, and VAL
to get the value:
d = dict("one", 1, "two", 2, "three", 3)
i = iterator(d)
while move_next(i)
print get(i), ", ", val(i);
wend
Iterate previous dictionary d
with a FOR
loop, while the iteration variable represents the key:
for i in d
print i, ", ", d(i);
next
It's possible to make an iterable class instance with overridden functions. It requires overriding for ITERATOR
, MOVE_NEXT
and GET
.
Create class instances:
class clz
var n = 0
def _iterator()
return me ' Return self for example
enddef
def _move_next()
n = n + 1
return n < 5
enddef
def _get()
return n
enddef
endclass
k = new(clz)
z = new(clz)
Iterate with an explicit pattern:
i = iterator(k)
while move_next(i)
print get(i);
wend
Iterate with a FOR
loop:
for i in z
print i;
next
It's possible to make an iterable referenced usertype with overridden functions. It requires ITERATOR
, MOVE_NEXT
and GET
.
Note that an iterator of a referenced usertype is also a referenced usertype, and in this sample, it's the value itself.
The implementation in C:
typedef struct Fibonacci {
int i;
int_t m;
int_t n;
} Fibonacci;
static void _unref(struct mb_interpreter_t* s, void* d) {
Fibonacci* p = (Fibonacci*)d;
mb_assert(s);
free(p);
}
static void* _clone(struct mb_interpreter_t* s, void* d) {
Fibonacci* p = (Fibonacci*)d;
Fibonacci* q = (Fibonacci*)malloc(sizeof(Fibonacci));
mb_assert(s);
*q = *p;
return q;
}
static mb_meta_status_e _fib_coll(struct mb_interpreter_t* s, void** l, mb_value_t* z, const char* n) {
Fibonacci* fib = 0;
mb_assert(s && l);
mb_get_ref_value(s, l, *z, (void**)&fib);
if(!strcmp(n, "ITERATOR")) {
mb_push_value(s, l, *z);
return (mb_meta_status_e)(MB_MS_DONE | MB_MS_RETURNED);
} else if(!strcmp(n, "MOVE_NEXT")) {
mb_push_int(s, l, fib->i++ < 6 ? true : false);
return (mb_meta_status_e)(MB_MS_DONE | MB_MS_RETURNED);
}
return MB_MS_NONE;
}
static mb_meta_status_e _fib_func(struct mb_interpreter_t* s, void** l, mb_value_t* z, const char* n) {
Fibonacci* fib = 0;
mb_assert(s && l);
mb_get_ref_value(s, l, *z, (void**)&fib);
if(!strcmp(n, "GET")) {
if(fib->i < 3) {
mb_push_int(s, l, 1);
} else {
int_t r = fib->n + fib->m;
fib->m = fib->n;
fib->n = r;
mb_push_int(s, l, r);
}
return (mb_meta_status_e)(MB_MS_DONE | MB_MS_RETURNED);
}
return MB_MS_NONE;
}
static int _fibonacci(struct mb_interpreter_t* s, void** l) {
int result = MB_FUNC_OK;
mb_assert(s && l);
mb_check(mb_attempt_open_bracket(s, l));
mb_check(mb_attempt_close_bracket(s, l));
{
mb_value_t ret;
Fibonacci* p = (Fibonacci*)malloc(sizeof(Fibonacci));
p->i = 0;
p->m = 1;
p->n = 1;
mb_make_ref_value(s, p, &ret, _unref, _clone, 0, 0, 0);
mb_override_value(s, l, ret, MB_MF_COLL, _fib_coll);
mb_override_value(s, l, ret, MB_MF_FUNC, _fib_func);
mb_check(mb_push_value(s, l, ret));
}
return result;
}
Don't forget to register it with:
mb_register_func(bas, "FIBONACCI", _fibonacci);
Iterate with an explicit pattern:
f = fibonacci()
i = iterator(f)
while move_next(i)
print get(i);
wend
Iterate with a FOR
loop:
f = fibonacci()
for i in f
print i;
next
- Principles
- Coding
- Data types
- Standalone shell
- Integration
- Customization
- More scripting API
- FAQ