[plt-scheme] Best style on argument checking...

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Tue Mar 27 17:55:18 EDT 2007

Also see

  http://people.cs.uchicago.edu/~robby/plt-contracts-guide/#genfunc

-- Matthias




On Mar 27, 2007, at 5:51 PM, Robby Findler wrote:

> Contracts work fine for that example:
>
>  (opt-> (string?) (number? symbol?) string?)
>
> Robby
>
> On 3/26/07, Paulo J. Matos <pocm at soton.ac.uk> wrote:
>> Hello all,
>>
>> I'd like suggestions on style about arguments checking.
>> This happens to me (and I'm sure to you too) regularly. Guess [to
>> exemplify] you want to define a function with 3 arguments, 2 of them
>> optional. The first obligatory argument should be a string, the  
>> second
>> a number and the third a symbol. You just want to append them all and
>> return a string.
>>
>> No arguments checking is easy:
>> (define (append-all str . args)
>>   (string-append str
>>                  (if (>= (length args) 1) (number->string (car  
>> args)) "")
>>                  (if (= (length args) 2) (symbol->string (cadr  
>> args)) "")))
>>
>> Problem is str might not be a string and the rest of the arguments  
>> may
>> not have correct type. And args can have 3 arguments [probably we
>> would like to warn the user about it].
>>
>> So, the other chance is:
>> (define (append-all1 str . args)
>>   (if (<= (length args) 2)
>>       (let ([str-ok? (string? str)]
>>             [arg2-ok? (or (null? args)
>>                           (number? (car args)))]
>>             [arg3-ok? (or (< (length args) 2)
>>                           (symbol? (cadr args)))])
>>         (if (and str-ok? arg2-ok? arg3-ok?)
>>             (string-append str
>>                  (if (>= (length args) 1) (number->string (car  
>> args)) "")
>>                  (if (= (length args) 2) (symbol->string (cadr  
>> args)) ""))
>>             (error "args not of correct type but I cannot say  
>> which")))
>>       (error "usage is append-all1 string [number] [symbol], you
>> passed in too many arguments")))
>>
>> or even this:
>> (define (append-all2 str . args)
>>   (cond [(> (length args) 2)
>>          (error "too many arguments")]
>>         [(not (string? str))
>>          (error "first argument needs to be a string")]
>>         [(not (or (null? args)
>>                   (number? (car args))))
>>          (error "second argument needs to be a number")]
>>         [(not (or (< (length args) 2)
>>                   (symbol? (cadr args))))
>>          (error "third argument needs to be a symbol")]
>>         [else
>>          (string-append str
>>                         (if (>= (length args) 1) (number->string  
>> (car args)) "")
>>                         (if (= (length args) 2) (symbol->string (cadr
>> args)) ""))]))
>>
>> I tend to switch between variants of the first way (this cond'ified
>> check is just something that came up while thinking about the issue).
>> However, I might guess other options are:
>> - contracts, however, I'm not sure if they help you checking the  
>> types
>> of the optional arguments and the number of optional arguments, I
>> don't think they do.
>> - typed-scheme (?!?), not really sure about this one but that would
>> probably require you to type variables also within the function which
>> you might not want to do.
>>
>> So, given that you have pure scheme, what would be the best style to
>> do this (hopefully portably since this is a general scheme problem)?
>>
>> Cheers,
>> --
>> Paulo Jorge Matos - pocm at soton.ac.uk
>> http://www.personal.soton.ac.uk/pocm
>> PhD Student @ ECS
>> University of Southampton, UK
>> _________________________________________________
>>   For list-related administrative tasks:
>>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>>
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.