I have managed to get the lexical scoping working
This works on the following:
- IronScheme
- Ikarus
- Larceny
- Petite Chez Scheme (remove the import clause)
Implementation:
(import (rnrs))
(define (compare asc? a b)
(cond
[(and (number? a) (number? b))
((if asc? < >) a b)]
[(and (char? a) (char? b))
((if asc? char<? char>?) a b)]
[(and (string? a) (string? b))
((if asc? string<? string>?) a b)]
[(and (symbol? a) (symbol? b))
(let ((a (symbol->string a))
(b (symbol->string b)))
((if asc? string<? string>?) a b))]
[else
(assertion-violation 'compare "not supported" a b)]))
(define (sort asc? l a b)
(list-sort
(lambda (a* b*)
(compare asc? (a a*) (b b*)))
l))
(define (flatten lists)
(apply append lists))
(define-syntax from
(lambda (x)
(define (e? e o)
(eq? (syntax->datum e) (syntax->datum o)))
(syntax-case x (in select)
[(from e in l select s)
(identifier? #'e)
(if (e? #'e #'s)
#'l
#'(map (lambda (e) s) l))]
[(from e in l c ... select s)
(identifier? #'e)
(syntax-case #'(c ...) (where orderby asc desc in)
[(where p rest ...)
(if (e? #'e #'p)
#'(from e in l
rest ...
select s)
#'(from e in (filter (lambda (e) p) l)
rest ...
select s))]
[(from e* in l* rest ...)
#'(flatten
(from e in l
select
(from e* in l*
rest ...
select s)))]
[(orderby p asc rest ...)
#'(from e in
(sort #t l (lambda (e) p) (lambda (e) p))
rest ...
select s)]
[(orderby p desc rest ...)
#'(from e in
(sort #f l (lambda (e) p) (lambda (e) p))
rest ...
select s)]
[(orderby p rest ...)
#'(from e in l
orderby p asc
rest ...
select s)]
)])))
Usage (shows nested ‘from x in y’ equivalence):
(define al ‘((a 4) (d 3) (a 2) (c 9) (a 10)))
(write
(
from e in al
orderby (cadr e)
from x in e
where (eq? x ‘a)
select e
))
(newline) ;=> ((a 2) (a 4) (a 10))
(write
(flatten
(
from e in al
orderby (cadr e)
select
(from x in e
where (eq? x ‘a)
select e)
)))
(newline) ;=> ((a 2) (a 4) (a 10))
Posted in Default, IronScheme