Add some shortcuts for the examples.

Inspired from the scribblings in Typed Racket.
This commit is contained in:
Sergiu Ivanov 2022-04-24 23:44:02 +02:00
parent 8ded018c05
commit e1a97235c0

View file

@ -4,6 +4,15 @@
typed/racket/unsafe
(only-in racket stream->list stream-first)))
@(define functions-evaluator
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-memory-limit 50])
(make-evaluator 'typed/racket #:requires '((submod "functions.rkt" typed)))))
@(define-syntax-rule (ex . args)
(examples #:eval functions-evaluator . args))
@title[#:tag "functions"]{dds/functions: Formal Functions}
@defmodule[dds/functions]
@ -13,12 +22,6 @@ This modules provides some definitions for working with functions: tabulating,
Some definitions of particular kinds of functions are also provided (threshold
Boolean functions, etc.).
@(define functions-evaluator
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-memory-limit 50])
(make-evaluator 'typed/racket #:requires '((submod "functions.rkt" typed)))))
@section[#:tag "pseudovariadic"]{Pseudovariadic functions}
Functions for @seclink["tabulating"]{tabulating functions} take as an argument
@ -35,7 +38,7 @@ Racket treats @racket[apply] in
special way}. This means that a user-defined function with the same type as
@racket[apply] and directly calling it will not work in the same way.
@examples[#:eval functions-evaluator
@ex[
apply
(define myapply apply)
myapply
@ -54,7 +57,7 @@ this documentation.
Define a pseudovariadic anonymous function.
@examples[#:eval functions-evaluator
@ex[
(: f (-> Boolean * Boolean))
(define f (pseudovariadic-lambda (x y) (and x y)))
(f #t #f)
@ -66,7 +69,7 @@ Define a pseudovariadic anonymous function.
Define a pseudovariadic function called @racket[name].
@examples[#:eval functions-evaluator
@ex[
(: g (-> Boolean * Boolean))
(pseudovariadic-define (g x y) (and x y))
(g #t #f)
@ -82,7 +85,7 @@ Given a function @racket[func] and a list of domains @racket[doms] for each of
its arguments, in order, produces a list of lists giving the values of
arguments and the value of the functions for these inputs.
@examples[#:eval functions-evaluator
@ex[
(tabulate (λ (x y) (and x y)) '((#f #t) (#f #t)))
]}
@ -98,7 +101,7 @@ elements of types @racket[a ...], followed by an element of type @racket[b].
This is why this function returns a list of lists, each containing first a list
of inputs, and then the output of @racket[func].
@examples[#:eval functions-evaluator
@ex[
(tabulate/strict (λ (x y) (and x y)) '((#f #t) (#f #t)))
]}
@ -109,7 +112,7 @@ of inputs, and then the output of @racket[func].
Like @racket[tabulate], but @racket[func]
@seclink["pseudovariadic"]{pseudovariadic}.
@examples[#:eval functions-evaluator
@ex[
(tabulate/pv (pvλ (x y) (and x y)) '((#f #t) (#f #t)))
]}
@ -119,7 +122,7 @@ Like @racket[tabulate], but @racket[func]
Like @racket[tabulate/list], but @racket[func] takes its arguments as a list.
@examples[#:eval functions-evaluator
@ex[
(tabulate/list (λ ([xs : (Listof Boolean)])
(and (car xs) (car xs)))
'((#f #t) (#f #t)))
@ -132,7 +135,7 @@ Like @racket[tabulate/list], but @racket[func] takes its arguments as a list.
Like @racket[tabulate], but @racket[funcs] is a list of functions taking the
same arguments over the same domains.
@examples[#:eval functions-evaluator
@ex[
(tabulate* (list (λ (x y) (and x y))
(λ (x y) (or x y)))
'((#f #t) (#f #t)))
@ -150,7 +153,7 @@ elements of types @racket[a ...], followed by a list of elements of type
@racket[b]. This is why this function returns a list of lists, each containing
first a list of inputs, and then the list of outputs of @racket[funcs].
@examples[#:eval functions-evaluator
@ex[
(tabulate*/strict (list (λ (x y) (and x y))
(λ (x y) (or x y)))
'((#f #t) (#f #t)))
@ -159,7 +162,7 @@ first a list of inputs, and then the list of outputs of @racket[funcs].
The result of @racket[tabulate*] can be obtained by applying
@racket[append-lists]:
@examples[#:eval functions-evaluator
@ex[
(require (only-in "utils.rkt" append-lists))
(append-lists (tabulate*/strict (list (λ (x y) (and x y))
(λ (x y) (or x y)))
@ -173,7 +176,7 @@ The result of @racket[tabulate*] can be obtained by applying
Like @racket[tabulate*], but the functions in @racket[funcs]
are @seclink["pseudovariadic"]{pseudovariadic}.
@examples[#:eval functions-evaluator
@ex[
(tabulate*/pv (list (pvλ (x y) (and x y))
(pvλ (x y) (or x y)))
'((#f #t) (#f #t)))
@ -186,7 +189,7 @@ are @seclink["pseudovariadic"]{pseudovariadic}.
Like @racket[tabulate*], but the functions in @racket[funcs] take their
arguments as a list.
@examples[#:eval functions-evaluator
@ex[
(tabulate*/list (list (λ ([xs : (Listof Boolean)])
(and (car xs) (cadr xs)))
(λ ([xs : (Listof Boolean)])
@ -200,7 +203,7 @@ arguments as a list.
Like @racket[tabulate/pv], but assumes the domains of all variables of the
function are Boolean. The arity of @racket[func] must be explicitly supplied.
@examples[#:eval functions-evaluator
@ex[
(tabulate/pv/boolean 2 (pvλ (x y) (and x y)))
]
@ -210,7 +213,7 @@ a pseudovariadic function cannot be determined programmatically. Note that
@racket[tabulate] requires a cast is required the domains argument
@racket[doms].
@examples[#:eval functions-evaluator
@ex[
(tabulate (λ (x y) (and x y))
(cast (make-list 2 '(#f #t))
(List (Listof Boolean) (Listof Boolean))))
@ -232,7 +235,7 @@ this function.
Like @racket[tabulate/pv/boolean], but takes a list of functions of the
same arity.
@examples[#:eval functions-evaluator
@ex[
(tabulate*/pv/boolean 2 (list (pvλ (x y) (and x y))
(pvλ (x y) (or x y))))
]}
@ -244,7 +247,7 @@ Like @racket[tabulate/pv], but assumes the domains of all variables of the
function are @tt{{0,1}}. The arity of @racket[func] must be
explicitly supplied.
@examples[#:eval functions-evaluator
@ex[
(tabulate/pv/01 2 (pvλ (x y)
(cast (modulo (+ x y) 2)
(U Zero One))))
@ -261,7 +264,7 @@ See @racket[tabulate/pv/boolean] for an explanation of the explicit
Like @racket[tabulate/pv/01], but takes a list of functions of the same arity.
@examples[#:eval functions-evaluator
@ex[
(tabulate*/pv/01 2 `(,(pvλ (x y) (cast (min x y) (U Zero One)))
,(pvλ (x y) (cast (max x y) (U Zero One)))))
]}
@ -273,7 +276,7 @@ Like @racket[tabulate/pv/01], but takes a list of functions of the same arity.
Like @racket[tabulate/list], but assumes the domains of all variables of the
function are Boolean.
@examples[#:eval functions-evaluator
@ex[
(tabulate/list/boolean 2 (λ (xs) (and (car xs) (cadr xs))))
]}
@ -284,7 +287,7 @@ function are Boolean.
Like @racket[tabulate*/list], but assumes the domains of all variables of the
function are Boolean.
@examples[#:eval functions-evaluator
@ex[
(tabulate*/list/boolean 2 (list (λ (xs) (and (car xs) (cadr xs)))
(λ (xs) (or (car xs) (cadr xs)))))
]}
@ -296,7 +299,7 @@ function are Boolean.
Like @racket[tabulate/list], but assumes the domains of all variables of the
function are @tt{{0,1}}.
@examples[#:eval functions-evaluator
@ex[
(tabulate/list/01 2 (λ (xs)
(cast (modulo (+ (car xs) (cadr xs)) 2) (U Zero One))))
]}
@ -308,7 +311,7 @@ function are @tt{{0,1}}.
Like @racket[tabulate*/list], but assumes the domains of all variables of the
function are @tt{{0,1}}.
@examples[#:eval functions-evaluator
@ex[
(tabulate*/list/01
2
`(,(λ (xs) (cast (min (car xs) (cadr xs)) (U Zero One)))
@ -327,7 +330,7 @@ More precisely, given a line of @racket[table] without its last element, the
function returned by @racket[table->function/list] produces the corresponding
last element.
@examples[#:eval functions-evaluator
@ex[
(define tab : (Listof (Listof Boolean))
'((#f #f #f)
(#f #t #f)
@ -344,7 +347,7 @@ last element.
Like @racket[table->function/list], but the resulting function takes a variable
number of arguments rather than a list of values.
@examples[#:eval functions-evaluator
@ex[
(define my-and (table->function tab))
(my-and #f #t)
(my-and #t #t)
@ -359,7 +362,7 @@ raised by the function returned by @racket[table->function]. In other words,
the returned by @racket[table->function/pv] is
@seclink["pseudovariadic"]{pseudovariadic}.
@examples[#:eval functions-evaluator
@ex[
(define my-and/pv (table->function/pv tab))
(my-and/pv #f #t)
(eval:error (my-and/pv #f))
@ -374,7 +377,7 @@ arity @racket[n].
There are @tt{2^(2^n)} Boolean functions of arity @racket[n].
@examples[#:eval functions-evaluator
@ex[
(require typed/racket/stream)
(stream->list (enumerate-boolean-tables 1))
]}
@ -386,7 +389,7 @@ Returns the stream of all Boolean functions of a given arity @racket[n].
There are @tt{2^(2^n)} Boolean functions of arity @racket[n].
@examples[#:eval functions-evaluator
@ex[
(length (stream->list (enumerate-boolean-functions 2)))
]}
@ -396,7 +399,7 @@ There are @tt{2^(2^n)} Boolean functions of arity @racket[n].
Like @racket[enumerate-boolean-functions], but the returned functions are
@seclink["pseudovariadic"]{pseudovariadic}.
@examples[#:eval functions-evaluator
@ex[
(define bool-f1/pv (stream-first (enumerate-boolean-functions/pv 2)))
(bool-f1/pv #f #f)
(eval:error (bool-f1/pv #f))
@ -409,7 +412,7 @@ Like @racket[enumerate-boolean-functions], but the returned functions are
Like @racket[enumerate-boolean-functions], but the returned functions take
their arguments as a single list.
@examples[#:eval functions-evaluator
@ex[
(define bool-f1/list (stream-first (enumerate-boolean-functions/list 2)))
(bool-f1/list '(#f #f))
]}
@ -420,7 +423,7 @@ their arguments as a single list.
Generates a random truth table for a Boolean function of arity @racket[n].
@examples[#:eval functions-evaluator
@ex[
(random-boolean-table 2)
]}
@ -428,7 +431,7 @@ Generates a random truth table for a Boolean function of arity @racket[n].
Generates a random Boolean function of arity @racket[n].
@examples[#:eval functions-evaluator
@ex[
(define random-bool-f (random-boolean-function 2))
(random-bool-f #t #f)
]}
@ -438,7 +441,7 @@ Generates a random Boolean function of arity @racket[n].
Like @racket[random-boolean-function], but the constructed function takes
a list of arguments.
@examples[#:eval functions-evaluator
@ex[
(define random-bool-f/list (random-boolean-function/list 2))
(random-bool-f/list '(#t #f))
]}
@ -464,7 +467,7 @@ Shortcuts for @racket[tbf-weights] and @racket[tbf-threshold].
Converts a Boolean vector to a vector of zeros and ones.
@examples[#:eval functions-evaluator
@ex[
(boolean->01/vector #(#t #f #f))
]}
@ -476,7 +479,7 @@ Applying a TBF consists in multiplying the weights by the corresponding inputs
and comparing the sum of the products to the threshold. If the product is
above the threshold, the function is 1, otherwise it is 0.
@examples[#:eval functions-evaluator
@ex[
(define simple-tbf (tbf #(2 -2) 1))
(tabulate/pv/01 2 (pvλ (x y) (apply-tbf simple-tbf (vector x y))))
]}
@ -486,7 +489,7 @@ above the threshold, the function is 1, otherwise it is 0.
Like @racket[apply-tbf], but takes Boolean values as inputs and outputs
a Boolean value.
@examples[#:eval functions-evaluator
@ex[
(define simple-tbf (tbf #(2 -2) 1))
(tabulate/pv/boolean 2 (pvλ (x y) (apply-tbf/boolean simple-tbf (vector x y))))
]}
@ -496,7 +499,7 @@ a Boolean value.
Converts a list of numbers to a TBF. The last element of the list is taken to
be the threshold, while the other elements are taken to be the weights.
@examples[#:eval functions-evaluator
@ex[
(list->tbf '(1 2 3))
]}
@ -507,7 +510,7 @@ Converts multiple lists of numbers to a list of TBFs.
The main use is for reading TBFs from Org-mode tables read by
@racket[read-org-sexp].
@examples[#:eval functions-evaluator
@ex[
(lists->tbfs '((1 2 3) (2 3 4)))
]}
@ -520,7 +523,7 @@ supposing that it contains the headers of the table.
The input is typically what @racket[read-org-sexp] reads.
@examples[#:eval functions-evaluator
@ex[
(read-org-tbfs "((1 2 1) (1 0 1))")
]}
@ -536,7 +539,7 @@ elements give the values of each the functions corresponding to the input.
All the TBFs in @racket[tbfs] must have the same number of inputs as the first
TBF in the list.
@examples[#:eval functions-evaluator
@ex[
(tbf-tabulate* (list (tbf #(2 2) 1) (tbf #(1 1) 1)))
]}
@ -566,6 +569,9 @@ accompanied by the explicit mention "untyped".
[sandbox-memory-limit 50])
(make-evaluator 'racket #:requires '((submod "functions.rkt" typed untyped)))))
@(define-syntax-rule (ex/untyped . args)
(examples #:eval functions-evaluator/untyped . args))
@defproc[(tabulate [funcs procedure?]
[doms (listof list?)])
(listof list?)]{
@ -574,7 +580,7 @@ Given a function @racket[func] and a list of domains @racket[doms] for each of
its arguments, in order, produces a list of lists giving the values of
arguments and the value of the functions for these inputs.
@examples[#:eval functions-evaluator/untyped
@ex/untyped[
(tabulate (λ (x y) (and x y)) '((#f #t) (#f #t)))
]}
@ -585,7 +591,7 @@ arguments and the value of the functions for these inputs.
Like @racket[tabulate] (untyped), but @racket[funcs] is a list of functions
taking the same arguments over the same domains.
@examples[#:eval functions-evaluator/untyped
@ex/untyped[
(tabulate* (list (λ (x y) (and x y))
(λ (x y) (or x y)))
'((#f #t) (#f #t)))
@ -597,7 +603,7 @@ Like @racket[tabulate] (untyped), but assumes the domains of all variables of
the function are Boolean. @racket[func] must have a fixed arity. It is an
error to supply a function of variable arity.
@examples[#:eval functions-evaluator/untyped
@ex/untyped[
(tabulate/boolean (lambda (x y) (and x y)))
]}
@ -607,7 +613,7 @@ error to supply a function of variable arity.
Like @racket[tabulate/boolean], but takes a list of functions of the
same arity.
@examples[#:eval functions-evaluator/untyped
@ex/untyped[
(tabulate*/boolean `(,(λ (x y) (and x y))
,(λ (x y) (or x y))))
]}
@ -618,7 +624,7 @@ Like @racket[tabulate] (untyped), but assumes the domains of all variables of
the function are @tt{{0,1}}. @racket[func] must have a fixed arity. It is an
error to supply a function of variable arity.
@examples[#:eval functions-evaluator/untyped
@ex/untyped[
(tabulate/01 (λ (x y) (modulo (+ x y) 2)))
]
@ -630,6 +636,6 @@ The same remarks apply as for @racket[tabulate/boolean] (untyped).
Like @racket[tabulate/01], but takes a list of functions of the same arity.
@examples[#:eval functions-evaluator/untyped
@ex/untyped[
(tabulate*/01 `(,(λ (x y) (min x y)) ,(λ (x y) (max x y))))
]}