[racket] Contract for methods with optional arguments

From: Greg Hendershott (greghendershott at gmail.com)
Date: Sat Aug 31 11:16:08 EDT 2013

If I knew the answer I'd tell you, and hopefully someone else will.

Meanwhile, another way you could look at this: If it becomes too
difficult to write a contract (or documentation) for a function, it
might be good to revise the function.

For example, a function that takes an optional argument that, if
supplied, causes the function to return something as different as
number? instead of (vectorof number?). That feels like a function that
instead wants to be two, more-specialized functions. Probably;
admittedly depends on the context of what you're doing.

p.s. An old, classic example s the C stdlib `realloc( ptr, size )`
function. It reallocates ptr to be size bytes. But wait -- there's
more!  If ptr is NULL, then realloc will act like `malloc` and
allocate memory for you. And -- if you order before midnight tonight!
-- passing 0 for size will make it act like `free` and return void.
It's an entire API in one function! Three tools for the price of one!
Call now! :)

This example paraphrased by memory from what I think was "Writing
Solid Code" by Steve Maguire in the mid 90s. His point: `realloc` is
too flexible. Because it accepts anything, you can't write ASSERTs (or
a contract) to catch a misuse by a caller.  Of course the
implementation may be some private function like realloc, an
all-in-one tools that accepts anything. But the public realloc should
be a thin wrapper function, just like malloc and free are.

On Sat, Aug 31, 2013 at 7:39 AM, Diego Sevilla Ruiz
<dsevilla at ditec.um.es> wrote:
> Hi all:
>         I have encountered a situation in which I don't know how to specify
> the contract for a method that:
> 1. Has a final optional argument
> 2. The value of the optional argument makes the method change the return
> type of the method.
> It is similar to this:
> (define/public (get-whatever (pos #f))
>   (if (not pos)
>       inner-vector-of-int
>       (vector-ref inner-vector-of-int pos)))
> (that is, if you don't specify a position, return the whole vector, but if
> you specify a position, return that position).
>         For what I've seen in the documentation, there exists the ->i
> function that allos the specification of named parameters, such as (not
> working but you get the idea):
> (->i () ;; mandatory
>      ([pos (or/c number? boolean?)])  ;; optional
>      [result (pos) (or/c (and/c (=/c #f pos) (vectorof number?))
>                          (and/c (number? pos) number?))])
> (I don't think the result expression is correct, but it expresses what I
> want).
>         The real problem comes with methods, because I have ->m and ->dm,
> but not ->im (->dm does not allow specifying dependent previous values in
> the result, for example, as far as I know).
>         So the question is, how to write a method contract for this method?
>         Thanks in advance,
>         diego.
> --
> Diego Sevilla Ruiz -- http://ditec.um.es/~dsevilla/ -- dsevilla at um.es _.___
> Dep. Ingeniería y Tecnología de Computadores, Facultad de Informática D|TEC
> Univ.de Murcia,Campus Espinardo,30080 Murcia (SPAIN),Tel.+34868887571
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users

Posted on the users mailing list.