Skip to content

Instantly share code, notes, and snippets.

@msp729
Created January 12, 2025 13:19
Show Gist options
  • Select an option

  • Save msp729/0ae3c8f46f01969c01ea929f455a0071 to your computer and use it in GitHub Desktop.

Select an option

Save msp729/0ae3c8f46f01969c01ea929f455a0071 to your computer and use it in GitHub Desktop.
Python list comprehensions in lisp
(defun flatmap (fn lst)
"as seen in haskell's (>>=) :: [a] -> (a -> [b]) -> [b], or rust's flat_map"
(apply #'append (mapcar fn lst)))
(defun get-fors (lst)
"extract the for clauses, as (variable list list-of-conditions)"
(unless lst (return-from get-fors nil))
(let ((v (get-for lst)))
`((,(car v) ,(cadr v) ,(caddr v)) . ,(get-fors (cdddr v)))
))
(defun get-for (lst)
"get a for clause"
(unless lst (return-from get-for nil))
(cond
((equal 'for (car lst)) (cons (cadr lst) (get-in (cddr lst))))
(t (get-for (cdr lst)))))
(defun get-in (lst)
"get the list a variable is from"
(unless lst (return-from get-in nil))
(cond
((equal 'in (car lst)) (cons (cadr lst) (get-ifs (cddr lst))))
(t (get-in (cdr lst)))
))
(defun get-ifs (lst)
"conditions to be met"
(unless lst (return-from get-ifs nil))
(cond
((equal 'if (car lst)) (let ((v (get-ifs (cddr lst))))
`((,(cadr lst) . ,(car v)) . ,(cdr v))))
((equal 'for (car lst)) (cons nil lst))
((null lst) '(() . ()))
(t (get-ifs (cdr lst)))))
(defun flat-mapper (clause expr)
"given a clause and the interior expression, returns the function to flatmap"
`(lambda (,(car clause))
(if
(and ,@(caddr clause))
,expr
nil
)))
(defun gencode (expr clauses)
"generate code for macro"
(if (null clauses) expr
`(flatmap ,(flat-mapper (car clauses) (gencode expr (cdr clauses))) ,(cadar clauses))
))
(defmacro pylc (expr &rest clauses)
"pythonic list comprehensions"
(gencode `(list ,expr) (get-fors clauses))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment