Posted by: leppie | April 11, 2008

LINQ for R6RS Scheme

UPDATE: please see newer posts for newer (and much better) versions. šŸ™‚
Implementation:

(import (rnrs))

(define (compare asc? a b)
  (if asc?
    (cond
      [(and (number? a) (number? b)) (< a b)]
      [(and (char? a) (char? b)) (char<? a b)]
      [(and (string? a) (string? b)) (string<? a b)]
      [else (error 'compare "not supported" a b)])
    (cond
      [(and (number? a) (number? b)) (> a b)]
      [(and (char? a) (char? b)) (char>? a b)]
      [(and (string? a) (string? b)) (string>? a b)]
      [else (error 'compare "not supported" a b)])))


(define-syntax from
  (lambda (x)
    (syntax-case x (in select where orderby asc desc)
      [(from e in l select sel)
        #'(map (lambda (e) sel) l)]
      [(from e in l where p select sel)
        #'(from e in (filter (lambda (e) p) l)
           select sel)]
      [(from e in l orderby p asc select sel)
        #'(from e in
            (list-sort
              (lambda (a b)
                (compare #t
                  ((lambda (e) p) a)
                  ((lambda (e) p) b)))
              l)
           select sel)]
      [(from e in l orderby p desc select sel)
        #'(from e in
            (list-sort
              (lambda (a b)
                (compare #f
                  ((lambda (e) p) a)
                  ((lambda (e) p) b)))
              l)
           select sel)]
      [(from e in l orderby o select s)
        #'(from e in l orderby o asc select s)]
      [(from e in l where w orderby o select s)
        #'(from e in (from e in l where w select e) orderby o select s)]
      [(from e in l where w orderby o asc select s)
        #'(from e in (from e in l where w select e) orderby o asc select s)]
      [(from e in l where w orderby o desc select s)
        #'(from e in (from e in l where w select e) orderby o desc select s)]
      )))

Usage (output in comments):

(define l '(2 3 4 1))

(write
  (
  from e in l
  where (or (odd? e) (= e 4))
  select e
  ))
(newline) ;=> (3 4 1)

(write
  (
  from x in
   (from e in l
    where (or (odd? e) (= e 4))
    select (+ e 1))
  where (even? x)
  select x
  ))
(newline) ;=> (4 2)

(write
   (from e in l
    orderby (- e)
    select e)
  )
(newline) ;=> (4 3 2 1)

(write
   (from e in l
    where (odd? e)
    orderby e
    select e)
  )
(newline) ;=> (1 3)
Advertisements

Responses

  1. That’s pretty damned cool. I’ve not used Scheme, so this is fairly new to me but it does seem to bear a certain resemblance to LISP.


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: