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