Posted by: leppie | April 13, 2008

LINQ for R6RS Scheme take 5

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))
Advertisements

Responses

  1. That is sweet.


Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: