From d038dfe8cff280210346c4177fef2f66c63411e4 Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Wed, 12 Mar 2014 23:43:44 -0700 Subject: [PATCH] updates --- coerce/contract.rkt | 16 ++-- scribblings/coerce.scrbl | 187 +++++++++++++++++++++++++++++++++++++++ scribblings/sugar.scrbl | 140 +---------------------------- 3 files changed, 196 insertions(+), 147 deletions(-) create mode 100644 scribblings/coerce.scrbl diff --git a/coerce/contract.rkt b/coerce/contract.rkt index 6560046..bcf5b2b 100644 --- a/coerce/contract.rkt +++ b/coerce/contract.rkt @@ -23,17 +23,17 @@ (with-syntax ([coerce/stem? (format-id stx "coerce/~a?" #'stem)] [->stem (format-id stx "->~a" #'stem)] [can-be-stem? (format-id stx "can-be-~a?" #'stem)]) - #'(define+provide coerce/stem? - (make-contract + #'(make-contract #:name 'coerce/stem? - #:projection (make-blame-handler ->stem 'can-be-stem?)))))])) + #:projection (make-blame-handler ->stem 'can-be-stem?))))])) -(make-coercion-contract int) -(make-coercion-contract string) -(make-coercion-contract symbol) -(make-coercion-contract path) -(make-coercion-contract boolean) +(define+provide coerce/int? (make-coercion-contract int)) +(define+provide coerce/symbol? (make-coercion-contract symbol)) +(define+provide coerce/path? (make-coercion-contract path)) +(define+provide coerce/boolean? (make-coercion-contract boolean)) +(define+provide coerce/string? (make-coercion-contract string)) + #| (define/contract (foo x) diff --git a/scribblings/coerce.scrbl b/scribblings/coerce.scrbl new file mode 100644 index 0000000..49caf69 --- /dev/null +++ b/scribblings/coerce.scrbl @@ -0,0 +1,187 @@ +#lang scribble/manual + +@(require scribble/eval (for-label racket "../main.rkt" sugar)) + +@(define my-eval (make-base-eval)) +@(my-eval `(require sugar)) + +@title{Coercion} +@defmodule[sugar/coerce] + +@section{Values} +@defmodule[sugar/coerce/value] + +@defproc[ +(->int +[v any/c]) +integer?] +Convert @racket[_v] to an integer in the least surprising way possible, or raise an error if it can't be done + +Numbers are rounded down to the nearest integer. + +Stringlike values are converted to numbers and rounded down. + +Characters are directly converted to integers. + +Lists, vectors, and other multi-value datatypes return their length (using @racket[len]). + +@examples[#:eval my-eval +(map ->int (list 3 3.5 -2.5 (+ 3 (/ 1 2)))) +(map ->int (list "3.5" '3.5 (string->path "3.5"))) +(->int (list 5 6 7)) +(->int (hash 'a 1 'b 2 'c 3)) +(->int #t) +] + +@defproc[ +(->string +[v any/c]) +string?] +Return the most natural string representation of @racket[_v], or raise an error if none exists. + +@examples[#:eval my-eval +(->string "string") +(->string 'symbol) +(->string 98.6) +(->string (string->path "stdio.h")) +(->string #\u0041) +(->string #t) +] + +@defproc[ +(->symbol +[v any/c]) +symbol?] +Same as @racket[->string], but returns a symbol rather than a string. + +@examples[#:eval my-eval +(->symbol "string") +(->symbol 'symbol) +(->symbol 98.6) +(->symbol (string->path "stdio.h")) +(->symbol #\u0041) +(->symbol #t) +] + +@deftogether[( +@defproc[ +(->path +[v any/c]) +path?] + +@defproc[ +(->complete-path +[v any/c]) +complete-path?] +)] +Same as @racket[->string], but returns a path (or complete path) rather than a string. + +@examples[#:eval my-eval +(->path "string") +(->path 'symbol) +(->complete-path 98.6) +(->complete-path (string->path "stdio.h")) +(->complete-path #\u0041) +(->complete-path #t) +] + + +@defproc[ +(->list +[v any/c]) +list?] +Convert a listlike @racket[_v] into a list, or put an atomic @racket[_v] into a single-member list. + +@examples[#:eval my-eval +(->list "string") +(->list 'symbol) +(->list +) +(->list '(a b c)) +(->list (list->vector '(a b c))) +] + +@defproc[ +(->vector +[v any/c]) +vector?] +Same as @racket[->list], but returns a vector rather than a list. + +@examples[#:eval my-eval +(->vector "string") +(->vector 'symbol) +(->vector +) +(->vector '(a b c)) +(->vector (list->vector '(a b c))) +] + +@defproc[ +(->boolean +[v any/c]) +boolean?] +Return @racket[#t] for any @racket[_v] except @racket[#f], which remains @racket[#f]. Same as @code{(and v #t)}. + +@examples[#:eval my-eval +(map ->boolean (list "string" 'symbol + '(l i s t) #f)) +] + + +@deftogether[( +@defproc[(intish? [v any/c]) boolean?] +@defproc[(stringish? [v any/c]) boolean?] +@defproc[(symbolish? [v any/c]) boolean?] +@defproc[(pathish? [v any/c]) boolean?] +@defproc[(complete-pathish? [v any/c]) boolean?] +)] +Report whether @racket[_v] can be coerced to the specified type. + +@examples[#:eval my-eval +(map intish? (list 3 3.5 #\A "A" + #t)) +(map stringish? (list 3 3.5 #\A "A" + #t)) +(map symbolish? (list 3 3.5 #\A "A" + #t)) +(map pathish? (list 3 3.5 #\A "A" + #t)) +(map complete-pathish? (list 3 3.5 #\A "A" + #t)) + +] + + + +@section{Contracts} +@defmodule[sugar/coerce/contract] + +@deftogether[( +@defproc[(coerce/int? [v any/c]) int?] +@defproc[(coerce/string? [v any/c]) string] +@defproc[(coerce/symbol? [v any/c]) symbol] +@defproc[(coerce/path? [v any/c]) path?] +@defproc[(coerce/boolean? [v any/c]) boolean?] +)] +If @racket[_v] can be coerced to the specified type, these contracts will return it so coerced. If not, they raise the usual contract error. This is an unusual way to use contracts, but it can be handy. + +@examples[#:eval my-eval +(define/contract (add-ints x y) + (coerce/int? coerce/int? . -> . any/c) + (+ x y)) +(add-ints 1.6 3.8) +(define/contract (int-sum x y) + (any/c any/c . -> . coerce/int?) + (+ x y)) + (int-sum 1.6 3.8) +] + +@defproc[ +(make-coercion-contract +[type string?]) +contract?] +Make a coercion contract named @code{coerce/type?} that will coerce a value to the speficied type. Assumes the existence of a @code{->type} function to do the coercion. + + +@examples[#:eval my-eval +(define (->list x) + (if (list? x) x (list x))) +(define coerce/list? (make-coercion-contract list)) +(define/contract (listify x) + (any/c . -> . coerce/list?) + x) +(listify '(a b c)) +(listify 24) +] \ No newline at end of file diff --git a/scribblings/sugar.scrbl b/scribblings/sugar.scrbl index 45333a6..ea5e459 100644 --- a/scribblings/sugar.scrbl +++ b/scribblings/sugar.scrbl @@ -21,145 +21,7 @@ After that, you can update the package from the command line: @verbatim{raco pkg update sugar} -@section{Coercion} -@defmodule[sugar/coerce] - -@subsection{Values} -@defmodule[sugar/coerce/value] - -@defproc[ -(->int -[v any/c]) -integer?] -Convert @racket[_v] to an integer in the least surprising way possible, or raise an error if none exists. - -Numbers are rounded down to the nearest integer. - -Stringlike values are converted to numbers and rounded down. - -Characters are directly converted to integers. - -Lists, vectors, and other multi-value datatypes go through @racket[len]. - -@examples[#:eval my-eval -(map ->int (list 3 3.5 -2.5 (+ 3 (/ 1 2)))) -(map ->int (list "3.5" '3.5 (string->path "3.5"))) -(->int (list 5 6 7)) -(->int (hash 'a 1 'b 2 'c 3)) -] - -@defproc[ -(->string -[v any/c]) -string?] -Return the most natural string representation of @racket[_v], or raise an error if none exists. - -@examples[#:eval my-eval -(->string "string") -(->string 'symbol) -(->string 98.6) -(->string (string->path "stdio.h")) -(->string #\u0041) -] - -@defproc[ -(->symbol -[v any/c]) -symbol?] -Same as @racket[->string], but returns a symbol rather than a string. - -@examples[#:eval my-eval -(->symbol "string") -(->symbol 'symbol) -(->symbol 98.6) -(->symbol (string->path "stdio.h")) -(->symbol #\u0041) -] - -@deftogether[( -@defproc[ -(->path -[v any/c]) -path?] - -@defproc[ -(->complete-path -[v any/c]) -complete-path?] -)] -Same as @racket[->string], but returns a path (or complete path) rather than a string. - -@examples[#:eval my-eval -(->path "string") -(->path 'symbol) -(->complete-path 98.6) -(->complete-path (string->path "stdio.h")) -(->complete-path #\u0041) -] - - -@defproc[ -(->list -[v any/c]) -list?] -Convert a listlike @racket[_v] into a list, or put an atomic @racket[_v] into a single-member list. - -@examples[#:eval my-eval -(->list "string") -(->list 'symbol) -(->list +) -(->list '(a b c)) -(->list (list->vector '(a b c))) -] - -@defproc[ -(->vector -[v any/c]) -vector?] -Same as @racket[->list], but returns a vector rather than a list. - -@examples[#:eval my-eval -(->vector "string") -(->vector 'symbol) -(->vector +) -(->vector '(a b c)) -(->vector (list->vector '(a b c))) -] - -@defproc[ -(->boolean -[v any/c]) -boolean?] -Return @racket[#t] for any @racket[_v] except @racket[#f], which remains @racket[#f]. Same as @code{(and v #t)}. - -@examples[#:eval my-eval -(map ->boolean (list "string" 'symbol + '(a) #f)) -] - - -@deftogether[( -@defproc[(intish? [v any/c]) boolean?] -@defproc[(stringish? [v any/c]) boolean?] -@defproc[(symbolish? [v any/c]) boolean?] -@defproc[(pathish? [v any/c]) boolean?] -@defproc[(complete-pathish? [v any/c]) boolean?] -)] -Report whether @racket[_v] can be coerced to the specified type. - -@examples[#:eval my-eval -(map intish? (list 3 3.5 #\A "A" + #t)) -(map stringish? (list 3 3.5 #\A "A" + #t)) -(map symbolish? (list 3 3.5 #\A "A" + #t)) -(map pathish? (list 3 3.5 #\A "A" + #t)) -(map complete-pathish? (list 3 3.5 #\A "A" + #t)) - -] - - - -@subsection{Contracts} -@defmodule[sugar/coerce/contract] - +@include-section["coerce.scrbl"] @section{License & source code}