- 
                Notifications
    You must be signed in to change notification settings 
- Fork 127
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);
wendAn increasing by 1 ranged iteration, with a FOR loop:
for i in list(1 to 5)
	print i;
nextA decreasing by 1 ranged iteration, with a FOR loop:
for i in list(5 to 1)
	print i;
nextUse 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);
wendIterate previous dictionary d with a FOR loop, while the iteration variable represents the key:
for i in d
	print i, ", ", d(i);
nextIt'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);
wendIterate with a FOR loop:
for i in z
	print i;
nextIt'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);
wendIterate 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