> On Jul 8, 2019, at 8:17 AM, David Storrs <david.sto...@gmail.com> wrote:
> 
> Note that in many cases it can be better to use a contract as opposed to an 
> explicit check.  For example, you could replace this:
> 
> (define (feed-animals cow sheep goose cat)
>     (if (not (eq? goose 'goose))
>       (raise-argument-error 'feed-animals "'goose" 2 cow sheep goose cat)
>       "fed the animals"))
> 
> With this, which is precisely equivalent:
> 
> (define/contract (feed-animals cow sheep goose cat)
>    (-> any/c any/c 'goose any/c any)
>     "fed the animals")
> 
> 
> Or maybe you want to verify that neither cow, sheep, nor cat are also goose:
> 
> (define/contract (feed-animals cow sheep goose cat)
>    (-> (not/c 'goose) (not/c 'goose) 'goose (not/c 'goose) any)
>     "fed the animals")
> 
> Or, maybe you can accept either a symbol or a string for goose:
> 
> (define/contract (feed-animals cow sheep goose cat)
>    (-> any/c any/c (or/c 'goose "goose") any/c any)
>     "fed the animals")
> 
> Or maybe do that case-insensitively (I'm getting rid of the excess arguments 
> for brevity):
> 
> (define/contract (feed-animals goose)
>    (-> (compose1 (curry string-ci=? "goose") ~a) any)
>     "fed the animals")
> 
> Same as above, but let's insist that the return value be a non-empty string:
> 
> (define/contract (feed-animals goose)
>    (-> (compose1 (curry string-ci=? "goose") ~a) non-empty-string?)
>     "fed the animals")
> 
> If you really want to get nuts then you can do all kinds of inter-argument 
> checking in a contract.  Here's an actual contract that I use in my database 
> layer, for the 'upsert-rows' function:
> 
> (define symbol-string? (or/c symbol? string?))
> (define false-or-unsupplied? (or/c false? unsupplied-arg?))
> 
> (define/contract (upsert-rows #:table             table-name
>                               #:rows              rows
>                               #:conflict-clause   conflict-clause
>                               #:db                [conn             #f]
>                               #:fields-to-update  [fields-to-update #f]
>                               )
>   (->i (#:table           [table symbol-string?]
>         #:rows            [rows (or/c  (hash/c symbol-string? any/c)
>                                        (listof (hash/c symbol-string? 
> any/c)))]
>         #:conflict-clause [conflict-clause (or/c #f 'FAIL symbol-string?)] ; 
> 'FAIL is redundant with `symbol-string?`. It's there for clarity.
>         )
>        (
>         #:db                 [db connection?]
>         #:fields-to-update   [fields-to-update (or/c #f (non-empty-listof 
> symbol-string?))]
>         )
>        ; If conflict clause is 'FAIL then fields-to-update must be #f or 
> unsupplied           
>        ; If conflict clause is #f then fields-to-update must be #f or 
> unsupplied              
>        ; If conflict clause is NOT #f then fields-to-update must be a list    
>                 
>        #:pre (conflict-clause fields-to-update)
>        (or  (and (equal? 'FAIL conflict-clause)
>                  (false-or-unsupplied? fields-to-update))
>             (and (false? conflict-clause) (false-or-unsupplied? 
> fields-to-update))
>             (and conflict-clause (list? fields-to-update)))
>        any)
> ...code…)

Thanks, David! I’ll have to look into using contracts in my code. Are there any 
downsides to contracts over the raising an error? 

Kevin

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/F9660627-85E0-4970-A357-E6C60486FCB9%40gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to