Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

CL list comprehension:

  (loop for file across "ABCDEFGH"
        nconc (loop for rank from 1 to 9
                    collect (format nil "~C~D" file rank)))


Or with more Python-esque syntax:

    (let ((files (coerce "ABCDEFGH" 'list))
          (ranks (loop for r from 1 to 9 collect r)))
      [(format nil "~a~a" file rank) (file <- files) (rank <- ranks)])
Based on the list comprehension macro from 1991 in https://3e8.org/pub/scheme/doc/lisp-pointers/v4i2/p16-lapalm... that still works.

    (defmacro comp ((e &rest qs) l2)
      (if (null qs) `(cons ,e ,l2) ; rule A
          (let ((q1 (car qs))
                (q (cdr qs)))
            (if (not (eq (cadr q1) '<-)) ; a generator?
                `(if ,q1 (comp (,e ,@q) ,l2) ,l2) ; rule B
                (let ((v (car q1)) ; rule C
                      (l1 (third q1))
                      (h (gentemp "H-"))
                      (us (gentemp "US-"))
                      (us1 (gentemp "US1-")))
                  `(labels ((,h (,us) ; corresponds to a letrec
                              (if (null ,us) ,l2
                                  (let ((,v (car ,us))
                                        (,us1 (cdr ,us)))
                                    (comp (,e ,@q) (,h ,us1))))))
                     (,h ,l1)))))))

    (defun open-bracket (stream ch)
      (do ((l nil)
           (c (read stream t nil t)(read stream t nil t)))
          ((eq c '|]|) `(comp ,(reverse l) ()))
      (push c l)))

    (defun closing-bracket (stream ch) '|]|)

    (set-macro-character #\[ #'open-bracket)
    (set-macro-character #\] #'closing-bracket)
Supports filtering too, e.g.

    (let ((xs '(1 2 3 4))
          (ys '(1 2 3 4)))
      [(+ x y) (x <- xs) (y <- ys) (evenp x) (oddp y)])
    ; -> (3 5 5 7)


I didn't try macroexpanding it yet, but when I make the 9 a runtime-parameter, I eventually get a stack-overflow with SBCL not TCO-ing the "H" binding in labels.

The comments make me think this is ported from scheme, which has precise TCO rules.

[edit] macroexpanded:

    (LABELS ((H-37 (US-38)
               (IF (NULL US-38)
                   NIL
                   (LET ((FILE (CAR US-38)) (US1-39 (CDR US-38)))
                     (LABELS ((H-43 (US-44)
                                (IF (NULL US-44)
                                    (H-37 US1-39)
                                    (LET ((RANK (CAR US-44)) (US1-45 (CDR US-44)))
                                      (CONS (FORMAT NIL "~a~a" FILE RANK) (H-43 US1-45))))))
                       (H-43 RANKS))))))
      (H-37 FILES))




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: