[racket] Contract for methods with optional arguments

From: Diego Sevilla Ruiz (dsevilla at ditec.um.es)
Date: Sat Aug 31 14:19:17 EDT 2013

Hi, Greg:

On 31/08/13 17:16, Greg Hendershott wrote:
> 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.
>

Well, yes, I considered it when designing my program. Of course that would 
have been a better option maybe if I had not other constraints. Just to 
give you some background, the project tries to map EMF Ecore (similar to 
UML specifications, but from the Eclipse project) to Racket code. The 
project is on GitHub:

	https://github.com/dsevilla/ecore2racket

	The mapping tries to be faithful to the classes you specify in Ecore, so I 
just wanted a method that retrieves a "property" of the class. If the 
property is multi-valuated, I didn't want to introduce optional methods 
that returned a given element of a vector of elements of the property, so I 
just created a method that returns the whole list, or, optionally, one 
element if specified.

	The example you give for C, you're right, it is not appropriate for C 
because C has a (lax) static type system. I think it is not exacly 
applicable here. You know, Scheme, Racket, they are dynamically typed 
languages: the type of the elements can vary at run time, so there are a 
lot of situations in which the type itself of the element changes. The 
Racket API is full of this. Take into account for example object-info:

http://docs.racket-lang.org/reference/objectutils.html?q=object-info#%28def._%28%28lib._racket%2Fprivate%2Fclass-internal..rkt%29._object-info%29%29

It returns either a class or #f. Clearly, these are two different types, 
and even in this case, it depends on some inner property of the class and 
the environment (the inspector). In my case, the return type depends on 
some argument, and I think this also is a pattern that appears in these 
dynamic languages.

	Just my 2 cents.

	Regards,
	diego.


>
> 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

-- 
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

Posted on the users mailing list.