⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 optargs.scm

📁 MSYS在windows下模拟了一个类unix的终端
💻 SCM
📖 第 1 页 / 共 2 页
字号:
;; paramater list, but before any dotted rest argument. For example,;;   (lambda* (a b #:optional c d . e) '());; creates a procedure with fixed arguments a and b, optional arguments c;; and d, and rest argument e. If the optional arguments are omitted;; in a call, the variables for them are bound to `#f'.;;;; lambda* can also take keyword arguments. For example, a procedure;; defined like this:;;   (lambda* (#:key xyzzy larch) '());; can be called with any of the argument lists (#:xyzzy 11);; (#:larch 13) (#:larch 42 #:xyzzy 19) (). Whichever arguments;; are given as keywords are bound to values.;;;; Optional and keyword arguments can also be given default values;; which they take on when they are not present in a call, by giving a;; two-item list in place of an optional argument, for example in:;;   (lambda* (foo #:optional (bar 42) #:key (baz 73)) (list foo bar baz));; foo is a fixed argument, bar is an optional argument with default;; value 42, and baz is a keyword argument with default value 73.;; Default value expressions are not evaluated unless they are needed;; and until the procedure is called.;;;; lambda* now supports two more special parameter list keywords.;;;; lambda*-defined procedures now throw an error by default if a;; keyword other than one of those specified is found in the actual;; passed arguments. However, specifying #:allow-other-keys;; immediately after the keyword argument declarations restores the;; previous behavior of ignoring unknown keywords. lambda* also now;; guarantees that if the same keyword is passed more than once, the;; last one passed is the one that takes effect. For example,;;   ((lambda* (#:key (heads 0) (tails 0)) (display (list heads tails)));;    #:heads 37 #:tails 42 #:heads 99);; would result in (99 47) being displayed.;;;; #:rest is also now provided as a synonym for the dotted syntax rest;; argument. The argument lists (a . b) and (a #:rest b) are equivalent in;; all respects to lambda*. This is provided for more similarity to DSSSL,;; MIT-Scheme and Kawa among others, as well as for refugees from other;; Lisp dialects.(defmacro lambda* (ARGLIST . BODY)  (parse-arglist   ARGLIST   (lambda (non-optional-args optionals keys aok? rest-arg)     ; Check for syntax errors.     (if (not (every? symbol? non-optional-args))	 (error "Syntax error in fixed argument declaration."))     (if (not (every? ext-decl? optionals))	 (error "Syntax error in optional argument declaration."))     (if (not (every? ext-decl? keys))	 (error "Syntax error in keyword argument declaration."))     (if (not (or (symbol? rest-arg) (eq? #f rest-arg)))	 (error "Syntax error in rest argument declaration."))     ;; generate the code.     (let ((rest-gensym (or rest-arg (gensym "lambda*:G")))	   (lambda-gensym (gensym "lambda*:L")))       (if (not (and (null? optionals) (null? keys)))	   `(let ((,lambda-gensym		   (lambda (,@non-optional-args . ,rest-gensym)		     ;; Make sure that if the proc had a docstring, we put it		     ;; here where it will be visible.		     ,@(if (and (not (null? BODY))				(string? (car BODY)))			   (list (car BODY))			   '())		     (let-optional*		      ,rest-gensym		      ,optionals		      (let-keywords* ,rest-gensym				     ,aok?				     ,keys				     ,@(if (and (not rest-arg) (null? keys))					   `((if (not (null? ,rest-gensym))						 (error "Too many arguments.")))					   '())				     (let ()				       ,@BODY))))))	      (set-procedure-property! ,lambda-gensym 'arglist				       '(,non-optional-args					 ,optionals					 ,keys					 ,aok?					 ,rest-arg))	      ,lambda-gensym)	   `(lambda (,@non-optional-args . ,(if rest-arg rest-arg '()))	      ,@BODY))))))(define (every? pred lst)  (or (null? lst)      (and (pred (car lst))	   (every? pred (cdr lst)))))(define (ext-decl? obj)  (or (symbol? obj)      (and (list? obj) (= 2 (length obj)) (symbol? (car obj)))))(define (parse-arglist arglist cont)  (define (split-list-at val lst cont)    (cond     ((memq val lst)      => (lambda (pos)	   (if (memq val (cdr pos))	       (error (with-output-to-string			(lambda ()			  (map display `(,val					 " specified more than once in argument list.")))))	       (cont (reverse (cdr (memq val (reverse lst)))) (cdr pos) #t))))     (else (cont lst '() #f))))  (define (parse-opt-and-fixed arglist keys aok? rest cont)    (split-list-at     #:optional arglist     (lambda (before after split?)       (if (and split? (null? after))	   (error "#:optional specified but no optional arguments declared.")	   (cont before after keys aok? rest)))))  (define (parse-keys arglist rest cont)    (split-list-at     #:allow-other-keys arglist     (lambda (aok-before aok-after aok-split?)       (if (and aok-split? (not (null? aok-after)))	   (error "#:allow-other-keys not at end of keyword argument declarations.")	   (split-list-at	    #:key aok-before	    (lambda (key-before key-after key-split?)	      (cond	       ((and aok-split? (not key-split?))		(error "#:allow-other-keys specified but no keyword arguments declared."))	       (key-split?		(cond		 ((null? key-after) (error "#:key specified but no keyword arguments declared."))		 ((memq #:optional key-after) (error "#:optional arguments declared after #:key arguments."))		 (else (parse-opt-and-fixed key-before key-after aok-split? rest cont))))	       (else (parse-opt-and-fixed arglist '() #f rest cont)))))))))  (define (parse-rest arglist cont)    (cond     ((null? arglist) (cont '() '() '() #f #f))     ((not (pair? arglist)) (cont '() '() '() #f arglist))     ((not (list? arglist))	  (let* ((copy (list-copy arglist))		 (lp (last-pair copy))		 (ra (cdr lp)))	    (set-cdr! lp '())	    (if (memq #:rest copy)		(error "Cannot specify both #:rest and dotted rest argument.")		(parse-keys copy ra cont))))     (else (split-list-at	    #:rest arglist	    (lambda (before after split?)	      (if split?		  (case (length after)		    ((0) (error "#:rest not followed by argument."))		    ((1) (parse-keys before (car after) cont))		    (else (error "#:rest argument must be declared last.")))		  (parse-keys before #f cont)))))))  (parse-rest arglist cont));; define* args . body;; define*-public args . body;;   define and define-public extended for optional and keyword arguments;;;; define* and define*-public support optional arguments with;; a similar syntax to lambda*. They also support arbitrary-depth;; currying, just like Guile's define. Some examples:;;   (define* (x y #:optional a (z 3) #:key w . u) (display (list y z u)));; defines a procedure x with a fixed argument y, an optional agument;; a, another optional argument z with default value 3, a keyword argument w,;; and a rest argument u.;;   (define-public* ((foo #:optional bar) #:optional baz) '());; This illustrates currying. A procedure foo is defined, which,;; when called with an optional argument bar, returns a procedure that;; takes an optional argument baz.;;;; Of course, define*[-public] also supports #:rest and #:allow-other-keys;; in the same way as lambda*.(defmacro define* (ARGLIST . BODY)  (define*-guts 'define ARGLIST BODY))(defmacro define*-public (ARGLIST . BODY)  (define*-guts 'define-public ARGLIST BODY));; The guts of define* and define*-public.(define (define*-guts DT ARGLIST BODY)  (define (nest-lambda*s arglists)    (if (null? arglists)        BODY        `((lambda* ,(car arglists) ,@(nest-lambda*s (cdr arglists))))))  (define (define*-guts-helper ARGLIST arglists)    (let ((first (car ARGLIST))	  (al (cons (cdr ARGLIST) arglists)))      (if (symbol? first)	  `(,DT ,first ,@(nest-lambda*s al))	  (define*-guts-helper first al))))  (if (symbol? ARGLIST)      `(,DT ,ARGLIST ,@BODY)      (define*-guts-helper ARGLIST '())));; defmacro* name args . body;; defmacro*-public args . body;;   defmacro and defmacro-public extended for optional and keyword arguments;;;; These are just like defmacro and defmacro-public except that they;; take lambda*-style extended paramter lists, where #:optional,;; #:key, #:allow-other-keys and #:rest are allowed with the usual;; semantics. Here is an example of a macro with an optional argument:;;   (defmacro* transmorgify (a #:optional b)(defmacro defmacro* (NAME ARGLIST . BODY)  (defmacro*-guts 'define NAME ARGLIST BODY))(defmacro defmacro*-public (NAME ARGLIST . BODY)  (defmacro*-guts 'define-public NAME ARGLIST BODY));; The guts of defmacro* and defmacro*-public(define (defmacro*-guts DT NAME ARGLIST BODY)  `(,DT ,NAME	(,(lambda (transformer) (defmacro:transformer transformer))	 (lambda* ,ARGLIST ,@BODY))));;; optargs.scm ends here

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -