-
-
Save shegeley/c574578ae5e2b7886aad7b3281dead47 to your computer and use it in GitHub Desktop.
A succinct anonymous procedure syntax for Guile scheme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; convenience-lambda.scm | |
;; | |
;; This syntax was inspired by arc and Clojure's anonymous procedure | |
;; syntax. | |
;; | |
;; #.\ (+ %1 %2) -> (lambda (%1 %2) (+ %1 %2)) | |
;; #.\ (+ % %%) -> (lambda (% %%) (+ % %%)) | |
;; | |
;; The .\ is supposed to approximate the lowercase lambda character in | |
;; ascii. | |
;; | |
;; Shane Celis | |
(eval-when (compile load eval) | |
(use-modules (ice-9 regex)) | |
(define (convenience-lambda char port) | |
(let ((uses-numbers? 'unknown)) | |
(define (range a b) | |
(if (> a b) | |
'() | |
(cons a (range (1+ a) b)))) | |
(define (read-from-string string) | |
(call-with-input-string string (lambda (port) (read port)))) | |
(define (scan-tree lst) | |
"scan-tree :: tree -> number" | |
(cond | |
((symbol? lst) | |
(let ((str (symbol->string lst))) | |
(if (char=? #\% (string-ref str 0)) | |
(if (string-match "^%[0-9]+" str) | |
(if uses-numbers? | |
(begin | |
(set! uses-numbers? #t) | |
(string->number (string-trim str #\%))) | |
(error "Pick a convention. Use %, %% or %1, %2 not both.")) | |
(if (string-match "^%+" str) | |
(if (or (eq? uses-numbers? 'unknown) | |
(eq? uses-numbers? #f)) | |
(begin | |
(set! uses-numbers? #f) | |
(string-length str)) | |
(error "Pick a convention. Use %, %% or %1, %2 not both.") | |
) | |
(error "Expected %1 or % to name positional variables; found '~a' instead." str))) | |
0))) | |
((pair? lst) | |
(max (scan-tree (car lst)) (scan-tree (cdr lst)))) | |
(else 0))) | |
(if (char=? #\\ (read-char port)) | |
(let* ((content (read port)) | |
(arg-count (scan-tree content))) | |
(display (number->string arg-count)) | |
`(lambda ,(map (lambda (x) | |
(string->symbol | |
(if uses-numbers? | |
(string-concatenate (list "%" (number->string x))) | |
(make-string x #\%)))) | |
(range 1 arg-count)) | |
,content)) | |
(error "Expected form like #.\\ (+ %1 %2)")))) | |
(read-hash-extend #\. convenience-lambda)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment