/usr/share/guile/site/scheme/kwargs.scm is in guile-library 0.2.2-0.2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | ;; (scheme kwargs) -- an alternate implementation of keyword arguments
;; Copyright (C) 2003,2004,2007 Andy Wingo <wingo at pobox dot com>
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; @c
;; Support for defining functions that take python-like keyword
;; arguments.
;;
;; In one of his early talks, Paul Graham wrote about a large system
;; called "Rtml":
;;
;; @quotation
;;
;; Most of the operators in Rtml were designed to take keyword
;; parameters, and what a help that turned out to be. If I wanted to add
;; another dimension to the behavior of one of the operators, I could
;; just add a new keyword parameter, and everyone's existing templates
;; would continue to work. A few of the Rtml operators didn't take
;; keyword parameters, because I didn't think I'd ever need to change
;; them, and almost every one I ended up kicking myself about later. If
;; I could go back and start over from scratch, one of the things I'd
;; change would be that I'd make every Rtml operator take keyword
;; parameters.
;;
;; @end quotation
;;
;; @xref{scheme kwargs lambda/kwargs,,lambda/kwargs}, for documentation
;; and examples.
;;
;; @xref{Optional Arguments,,,guile,Guile Reference Manual}, for more
;; information on Guile's standard support for optional and keyword
;; arguments.
;;
;; Quote taken from
;; @uref{http://lib.store.yahoo.net/lib/paulgraham/bbnexcerpts.txt}.
;;
;;; Code:
(define-module (scheme kwargs)
:use-module (ice-9 optargs)
:use-module (scheme documentation)
:export (lambda/kwargs define/kwargs))
(define (until pred? list)
"Returns the first elements of @var{list} for which @var{pred?} is false."
(if (or (eq? list '()) (pred? (car list)))
'()
(cons (car list) (until pred? (cdr list)))))
(define-macro-with-docs (lambda/kwargs BINDINGS . BODY)
"Defines a function that takes keyword arguments.
@var{bindings} is a list of bindings, each of which may either be a
symbol or a two-element symbol-and-default-value list. Symbols without
specified default values will default to @code{#f}.
For example:
@example
(define frobulate (lambda/kwargs (foo (bar 13) (baz 42))
(list foo bar baz)))
(frobulate) @result{} (#f 13 42)
(frobulate #:baz 3) @result{} (#f 13 3)
(frobulate #:foo 3) @result{} (3 13 42)
(frobulate 3 4) @result{} (3 4 42)
(frobulate 1 2 3) @result{} (1 2 3)
(frobulate #:baz 2 #:bar 1) @result{} (#f 1 2)
(frobulate 10 20 #:foo 3) @result{} (3 20 42)
@end example
This function differs from the standard @code{lambda*} provided by Guile
in that invoking the function will accept positional arguments.
As an example, the @code{lambda/kwargs} behaves more intuitively in the
following case:
@example
((lambda* (#:optional (bar 42) #:key (baz 73))
(list bar baz))
1 2) @result{} (1 73)
((lambda/kwargs ((bar 42) (baz 73))
(list bar baz))
1 2) @result{} (1 2)
@end example
The fact that @code{lambda*} accepts the extra @samp{2} argument is
probably just a bug. In any case, @code{lambda/kwargs} does the right
thing.
"
(or (list? BINDINGS)
(error "lambda/kwargs bindings must be a list"))
(let ((lambda-gensym (gensym))
(args-gensym (gensym))
(positional (gensym))
(keyword (gensym))
(nbindings (length BINDINGS))
(CANONICAL-BINDINGS (map (lambda (x)
(if (list? x) x (list x #f)))
BINDINGS))
(VARIABLES (map (lambda (x) (if (list? x) (car x) x))
BINDINGS)))
`(let ((,lambda-gensym
(lambda ,args-gensym
,@(if (string? (car BODY)) (list (car BODY)) '())
(let* ((,positional ((@@ (scheme kwargs) until)
keyword? ,args-gensym))
(,keyword (list-tail ,args-gensym (length ,positional))))
(if (> (length ,positional) ,nbindings)
(error "Too many positional arguments."))
((@ (ice-9 optargs) let-optional) ,positional
,CANONICAL-BINDINGS
;; ,@(map car CANONICAL-BINDINGS)
((@ (ice-9 optargs) let-keywords) ,keyword
#f
,(map list VARIABLES VARIABLES)
,@(if (string? (car BODY)) (cdr BODY) BODY)))))))
(set-procedure-property! ,lambda-gensym
'arglist
'(() () ,CANONICAL-BINDINGS #f #f))
,lambda-gensym)))
(define-macro-with-docs (define/kwargs what . body)
"Defines a function that takes kwargs. @xref{scheme kwargs
lambda/kwargs}, for more information.
"
`(define ,(car what) ((@ (scheme kwargs) lambda/kwargs) ,(cdr what) ,@body)))
|