[racket] contracts on liberal function inputs: avoiding duplicate effort
I think the proper interface to offer is to separate the interfaces:
-- one function that works on normalized interfaces and for that you use rgb-color/c
-- other function(s) that work on liberal inputs and clients know they may pay the cost for double-normalization
On Nov 18, 2013, at 12:03 PM, Matthew Butterick <mb at mbtype.com> wrote:
> In a function that permits liberal inputs, I often find that the input processing I do in a contract is duplicated at the beginning of the body of the function. Is this avoidable?
>
> Certain functions want to be liberal with input because there are multiple common ways to represent the data. For instance, I have a function that operates on CSS RGB colors. This function should be prepared to accept these forms of input & understand that they're all the same:
>
> "#c00"
> "#cc0000"
> '("204" "0" "0")
> #xcc0000
> '(0.8 0 0)
>
> Let's say that my internal representation of an RGB color is described by the contract rgb-color/c:
>
> (define rgb-color/c (list/c (real-in 0 1) (real-in 0 1) (real-in 0 1)))
>
> But I can't use rgb-color/c as the input contract for the function because it's too narrow. So I make a second contract that tests for things that can be converted to an rgb-color:
>
> (define (rgb-colorish? x) (or/c rgb-color/c [tests for the other input formats ...] )
>
> To determine if the input is rgb-colorish?, this contract usually just ends up trying to convert the input to rgb-color. If it works, then the contract returns true.
>
> But after the contract returns, I have to convert the input to an rgb-color anyhow. So I'm doing exactly the same work that the contract just finished. If the conversion is expensive, I'm doing it twice.
>
>
>
>
> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users