2020-11-29 00:28:46 +01:00
|
|
|
#lang scribble/manual
|
2020-11-29 23:07:40 +01:00
|
|
|
@(require scribble/example racket/sandbox
|
2020-12-04 02:25:19 +01:00
|
|
|
(for-label racket graph "../utils.rkt"
|
|
|
|
(only-in typed/racket/base
|
|
|
|
Any AnyValues)))
|
2020-11-29 00:28:46 +01:00
|
|
|
|
|
|
|
@title[#:tag "utils"]{dds/utils: Various Utilities}
|
|
|
|
|
2020-11-29 21:41:00 +01:00
|
|
|
@defmodule[dds/utils]
|
|
|
|
|
|
|
|
This module defines miscellaneous utilities, supporting the other modules of
|
|
|
|
the package: evaluating sexps, manipulating lists,
|
|
|
|
@hyperlink["https://orgmode.org/"]{Org-mode} interoperability, etc.
|
|
|
|
|
2020-11-29 23:07:40 +01:00
|
|
|
|
|
|
|
@(define utils-evaluator
|
|
|
|
(parameterize ([sandbox-output 'string]
|
|
|
|
[sandbox-error-output 'string]
|
|
|
|
[sandbox-memory-limit 50])
|
2020-12-04 02:25:19 +01:00
|
|
|
(make-evaluator 'typed/racket/base #:requires '("utils.rkt"))))
|
|
|
|
|
|
|
|
@section{Base Types}
|
|
|
|
@defidform[Variable]{
|
|
|
|
|
|
|
|
Any Racket symbol. Designates a variable in a discrete dynamical network.
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@defform[(VariableMapping A)]{
|
|
|
|
|
|
|
|
An immutable mapping (a hash table) assigning elements of type @racket[A] to
|
|
|
|
the variables.
|
|
|
|
|
|
|
|
}
|
2020-11-29 23:07:40 +01:00
|
|
|
|
2020-11-29 21:41:00 +01:00
|
|
|
@section{Hashtable injection}
|
|
|
|
|
|
|
|
This section defines some utilities to streamline the usage of hash tables
|
|
|
|
mapping symbols to values. The goal is essentially to avoid having to write
|
2020-11-29 23:07:40 +01:00
|
|
|
explicit @racket[hash-ref] calls.
|
|
|
|
|
2020-12-04 02:25:19 +01:00
|
|
|
@defproc[(eval-with [ht (VariableMapping Any)] [expr Any]) AnyValues]{
|
2020-11-29 23:07:40 +01:00
|
|
|
|
|
|
|
Temporarily injects the mappings from the given hash table as bindings in
|
|
|
|
a namespace including @racket[racket/base] and then evaluates the expression.
|
|
|
|
|
|
|
|
@examples[#:eval utils-evaluator
|
|
|
|
(let ([ht (hash 'a 1 'b 1)])
|
|
|
|
(eval-with ht '(+ b a 1)))
|
|
|
|
]
|
|
|
|
|
|
|
|
The local bindings from the current lexical scope are not
|
|
|
|
conserved. Therefore, the following outputs an error about a
|
|
|
|
missing identifier:
|
|
|
|
|
|
|
|
@examples[#:eval utils-evaluator
|
|
|
|
(eval:error
|
|
|
|
(let ([ht (hash 'a 1 'b 1)]
|
|
|
|
[z 1])
|
|
|
|
(eval-with ht '(+ b z a 1)))
|
|
|
|
)]}
|
2020-11-29 21:41:00 +01:00
|
|
|
|
2020-12-04 02:25:19 +01:00
|
|
|
@defproc[(eval1-with [ht (VariableMapping Any)] [expr Any]) Any]{
|
|
|
|
|
|
|
|
Like @racket[eval-with], but returns only the first value computed by
|
|
|
|
@racket[expr].
|
|
|
|
|
|
|
|
@examples[#:eval utils-evaluator
|
|
|
|
(let ([ht (hash 'a 1 'b 1)])
|
|
|
|
(eval1-with ht '(+ b a 1)))
|
|
|
|
]}
|
2020-12-04 03:16:38 +01:00
|
|
|
|
|
|
|
@defform[(auto-hash-ref/explicit stx)
|
|
|
|
#:contracts ([stx (VariableMapping A)])]{
|
|
|
|
|
|
|
|
Given a @racket[VariableMapping] and a sequence of symbols, binds these symbols
|
|
|
|
to the values they are associated with in the hash table, then puts the body in
|
|
|
|
the context of these bindings.
|
|
|
|
|
|
|
|
@examples[#:eval utils-evaluator
|
|
|
|
(let ([ht #hash((a . 1) (b . 2))])
|
|
|
|
(auto-hash-ref/explicit (ht a b) (+ a (* 2 b))))
|
|
|
|
]
|
|
|
|
|
|
|
|
Note that only one expression can be supplied in the body.
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@defform[(auto-hash-ref/: stx)
|
|
|
|
#:contracts ([stx (VariableMapping A)])]{
|
|
|
|
|
|
|
|
Given an expression and a @racket[VariableMapping], looks up the symbols with
|
|
|
|
a leading semicolon and binds them to the value they are associated with in the
|
|
|
|
hash table.
|
|
|
|
|
|
|
|
@examples[#:eval utils-evaluator
|
|
|
|
(let ([ht #hash((a . 1) (b . 2))])
|
|
|
|
(auto-hash-ref/: ht (+ :a (* 2 :b))))
|
|
|
|
]
|
|
|
|
|
|
|
|
Thus the symbol @racket[:a] is matched to the key @racket['a] in the
|
|
|
|
hash table.
|
|
|
|
|
|
|
|
Note that only one expression can be supplied in the body.
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-11-29 21:41:00 +01:00
|
|
|
@section{Analysis of quoted expressions}
|
|
|
|
|
|
|
|
@section{Org-mode interoperability}
|
|
|
|
|
|
|
|
Org-mode supports laying out the output of code blocks as tables, which is very
|
|
|
|
practical for various variable mappings (e.g., states). However, when the hash
|
|
|
|
table maps variables to lists, Org-mode will create a column per list element,
|
|
|
|
which may or may not be the desired effect. This section defines some
|
|
|
|
utilities for nicer interoperation with Org-mode tables. It also defines some
|
|
|
|
shortcuts to reduce the number of words to type when using dds with Org-mode.
|
|
|
|
See
|
|
|
|
@hyperlink["https://git.marvid.fr/scolobb/dds/src/branch/master/example/example.org"]{example.org}
|
|
|
|
for examples of usage.
|
|
|
|
|
|
|
|
@section{Additional graph utilities}
|
|
|
|
|
|
|
|
@section{Pretty printing}
|
|
|
|
|
|
|
|
@section{Additional list and hash map utilities}
|
|
|
|
|
|
|
|
@section{Functions and procedures}
|
|
|
|
|
|
|
|
@section{Randomness}
|
|
|
|
|
|
|
|
@section{Additional stream utilities}
|
|
|
|
|
|
|
|
@section{Boolean operations}
|