Title

ALAMBDA and ADEFINE

Author

Joo ChurlSoo

Status

This SRFI is currently in withdrawn status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi-187@nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.

Abstract

This SRFI introduces alambda, which creates a procedure that checks its actual arguments, takes various types of required and optional variables.
This SRFI is based on SRFI 92 as an extension of the optional argument of SRFI 182.

Rationale

The syntax reduces not only the clutter of various error conditionals by checking actual arguments but also somewhat lengthy code by combining optional argument handling methods such as let-optionals and let-keywords into a single syntax.
The formal argument list of lambda is extended to discriminate among the various types of variables with quote, quasiquote, and unquote.

Optional variables include not only sequent variables but also non-sequent variables.
The following are examples to show the various types of variables.

  1. optional sequent variables

    ((alambda (req () num cha str)	       	  ;same as (#f)
       (list req num cha str))
     10)				=> (10 #f #f #f)
    
    ((alambda (req ('undefined) num cha str)
       (list req num cha str))
     10)				=> (10 undefined undefined undefined)
    
    ((alambda (req () (num req) (cha #\a) (str "opt"))
       (list req num cha str))
     10 30 #\o)   	       	     	=> (10 30 #\o "opt")
        
  2. optional keyword variables

    ((alambda (req () ('num req) ('cha #\a) ('str "opt"))
       (list req num cha str))
     10 'str "key" 'num 30)	     	=> (10 30 #\a "key")
    
    ((alambda (req () (('num #:num) req) (('cha #:cha) #\a) (('str #:str) "opt"))
       (list req num cha str))
     10 #:str "key" #:num 30)      	=> (10 30 #\a "key")
        
  3. optional unnamed variables

    ((alambda (req () (,num req (number? num)) (,cha #\a (char? cha)) (,str "opt"))
       (list req num cha str))
     10 "fox" 30 #\f)      	     	=> (10 30 #\f "fox")
        
  4. optional mixed variables

    ((alambda (req () ((`num #:num) req) (,cha #\a (char? cha)) (str "opt") . rem)
       (list req num cha str rem))
     10 "fox" #:num 30 #\f)	     	=> (10 30 #\f "fox" ())
    
    ((alambda (req () (('num #:num) req) (,cha #\a (char? cha)) (str "opt") . rem)
       (list req num cha str rem))
     10 "fox" #:num 30 #\f)	     	=> (10 10 #\f "fox" (#:num 30))
        

Like optional variables, required variables can be divided into three groups, namely, sequent variables, keyword variables, and unnamed variables. These are best explained by simple examples.

  1. required sequent variables

    (adefine (str-ref-seq (str (string? str)) (num (integer? num)))
      (string-ref str num))
    
    (str-ref-seq "str" 1)		=> #\t
    (str-ref-seq 1 "str")		=> bad argument 1 s (string? s)
        
  2. required keyword variables

    (adefine (str-ref-key 'str 'num)
     (string-ref str num))
    
    (str-ref-key 'num 1 'str "str")	 	=> #\t
    
    (adefine (str-ref-key (('str #:str)) (('num #:num)))
     (string-ref str num))
    
    (str-ref-key #:num 1 #:str "str")	=> #\t
        
  3. required unnamed variables

    (adefine (str-ref-fox (,str (string? str)) (,num (integer? num)))
       (string-ref str num))
    
    (str-ref-fox "str" 1)	=> #\t
    (str-ref-fox 1 "str")	=> #\t
    (str-ref-fox 1 123)	=> no argument for required unnamed variable str
    (str-ref-fox 1 "str" 2)	=> too many arguments (1 2)
        

Specification

(alambda <rnrs formals> <body>)		;The alambda is the same as the lambda.

(alambda <extended formals> <body>)

<extended formals> --> <variable>
	       | (<required spec>* <delimiter> <optional spec>* <rest spec>)

<delimiter> -- ()
	     | (default)

<required spec> -->  <required sequent spec>
		   | <required keyword spec>
		   | <required unnamed spec>
<optional spec> -->  <optional sequent spec>
		   | <optional keyword spec>
		   | <optional unnamed spec>
<rest spec> --> . <variable> | <empty>

<required sequent spec>	 --> <variable> | ( <variable> <test spec>)
<required keyword spec> -->  <key-spec> | ( <key-spec> <test spec>)
<required unnamed spec> --> ,<variable> | (,<variable> <test spec>)
<optional sequent spec>	 --> <variable> | ( <variable> <default spec>)
<optional keyword spec> -->  <key-spec> | ( <key-spec> <default spec>)
<optional unnamed spec> --> ,<variable> | (,<variable> <default spec>)

<key-spec> --> '<variable>   		; two at a time
	    |  `<variable>		; one at a time
	    | ('<variable> <keyword>)
	    | (`<variable> <keyword>)
	    | ('<variable> <keyword> <equivalence predicate>)
	    | (`<variable> <keyword> <equivalence predicate>)
<equivalence predicate> --> eq?		;default equivalent predicate
	     		  | eqv?
			  | equal?

<default spec> --> <default>
	         | <default> <test spec>
<test spec> --> <test>
	      | <test> <true substitute>
	      |	<test> <true substitute> <false substitute>

<variable> --> <identifier>
<keyword> <default> <test> <true substitute> <false substitute> --> <expression>

The alambda of <extended formals> is to the lambda what the let* is to the let.
The <default>, <test>, <true substitute>, and <false substitute> of alambda are evaluated in an environment in which all the bindings of previous <variable>s are visible. But duplication of variables is permitted only after an extended variable of <extended formals> appears.

There are two types of delimiter, which separate variables into required and optional variables. One is an empty list and the other is a list with one element. The former has #f as the default value and the latter has its element.

There are three kinds of required variables - sequent, keyword, and unnamed. They determine the number of required actual arguments, that is, the minimum arity of the resulting procedure.

The required sequent variable is bound to the first one of the remaining actual arguments. If there are no more actual arguments, an error is signaled.

The keyword used at a call site for the corresponding variable is a symbol of the same name as the variable or <keyword>. The remaining arguments are interpreted one at a time (quote symbol) or two at a time (quasiquote symbol) until an actual argument is the keyword, then the variable is bound to the next actual argument. If there is no keyword or the keyword is the last actual argument, an error is signaled.

The required unnamed variable is temporarily bound to each of remaining actual arguments sequentially, until <test> returns a true value, then the variable is finally bound to the passed argument. If there is no <test>, the first one of the remaining actual arguments is regarded as passing. If any actual argument does not pass <test>, an error is signaled. If there is a <false substitute> and <test> returns a false value, the variable is finally bound to the <false substitute> instead of the above process. If there is a <true substitute> and <test> returns a true value, the variable is rebound to the <true substitute>.

The binding method of the optional sequent variable is the same as that of the required sequent variable except that the variable is bound to the <default> instead of signaling an error if there are no remaining actual arguments. When <default> is not specified, #f is the default.

The binding method of the optional keyword variable is the same as that of the required keyword variable except that the variable is bound to the <default> instead of signaling an error if there is no keyword or the keyword is the last actual argument. When <default> is not specified, #f is the default.

The binding method of the optional unnamed variable is the same as that of the required unnamed variable except that the variable is bound to the <default> instead of signaling an error if any actual argument does not pass <test>. When <default> is not specified, #f is the default.

When there are remaining actual arguments, an error is signaled if dotted rest variable is not given. If dotted rest variable is given, it is bound to the remaining actual arguments.

The following are applied to all <variable>s except <unnamed variable>s: If there is a <test>, it is evaluated only when the variable is bound to an actual argument. If it returns a false value and there is no <false substitute>, an error is signaled. If it returns a false value and there is a <false substitute>, the variable is rebound to the <false substitute> instead of signaling an error. If it returns a true value and there is a <true substitute>, the variable is rebound to the <true substitute>.

(adefine name <expression>)
(adefine (name . <extended formals>) <body>)

These are the same as the DEFINE except <extended formals>.

Sample Implementation

Sample implementations are provided based on both define-syntax and define-macro. They're available both in the Github repo and in this .tgz file.

References

[R5RS]Richard Kelsey, William Clinger, and Jonathan Rees: Revised(5) Report on the Algorithmic Language Scheme.http://www.schemers.org/Documents/Standards/R5RS/
[R6RS]Michael Sperber, R. Kent Dybvig, Matthew Flatt, and Anton von Straaten: Revised(6) Report on the Algorithmic Language Scheme.http://www.r6rs.org
[SRFI 51]Joo ChurlSoo: Handling rest list.https://srfi.schemers.org/srfi-51/
[SRFI 54]Joo ChurlSoo: Formatting.https://srfi.schemers.org/srfi-54/
[SRFI 86]Joo ChurlSoo: MU and NU simulating VALUES & CALL-WITH-VALUES, and their related LET-syntax.https://srfi.schemers.org/srfi-86/
[SRFI 89]Marc Feeley: Optional and named parameters. http://srfi.schemers.org/srfi-89/
[SRFI 92]Joo ChurlSoo: Alambda and Alambda*.http://srfi.schemers.org/srfi-89/
[SRFI 182]Joo ChurlSoo: Adbmal, Alet, and Alet*.http://srfi.schemers.org/srfi-182/

Copyright

Copyright © Joo ChurlSoo (2012).

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Editor: Arthur A. Gleckler