2024Mar08 change (fn-var) to use (demunge (.getName (.getClass f))) for cleaner code, more robust beahvior

2024Feb28: rename
	(wrap-fn) to (instrument)
	(unwrap-fn) to (unstrument)
	(test-fn-with) to (validate-fn-with)

2024Feb29: write (arg-vs-ret-spec-validate) function to compare the args to the returns

2024Mar01: write branching logic for (validate-fn-with) and (wrapping-fn) that validates a function's scalar return with a bare predicate (i.e., not a collection)

2024Feb27: write (clamp) function that restricts eval of lazy sequences in either the data or the spec (but not both)

test sequences, lazy-sequences, infinite lazy sequences
2024Feb23: Regarding bare sequences, things get goofy. You can't merely create a de novo sequence, you can only coerce one by calling (sequence) or (seq) on a collection literal. The resulting sequence is not its own type, but a derivation of that original collection. 
	(type (sequence [11 22 33])) ; clojure.lang.PersistentVector$ChunkedSeq
	(type (sequence {:a 11 :b 22})) ; clojure.lang.PersistentArrayMap$Seq
	(type (sequence '(11 22 33))) ; clojure.lang.PersistentList
	(type (sequence #{11 22 33})) ; clojure.lang.APersistentMap$KeySeq
	Running (first) on a sequence derived from a map returns a MapElement.
	Running (first) on a sequence derived from a set returns some un-defined 'first' element. (i.e., once it's been sequence-ized, you can't address a set element by it's value, only its un-predicatable (nth)-able sequence index). Once a collection has been sequence-ized, we can't tell what it was originally, because every seq and every sequence returns true for both (sequential?) and (seqable?).

2024Feb25: upgraded (get*), (get-in*), (assoc*), (assoc-in*), (update*), (update-in*), (dissoc*), (dissoc-in*) to consume (possibly) non-terminating sequences including
    clojure.lang.{Cycle,Iterate,LazySeq,LongRange,Range,Repeat}

2024Feb26: You must tread lightly at the REPL, or something you do may trigger evaluation. However, if you send a function a non-terminating sequence and immediately bind it (e.g., (def)) or send it off to another function, and don't do anything lame, like try to (println) it, it may work...
	One strategy for working with infinite sequences is to have a policy to always wrap them with a (take 99 __), which doesn't usually blow up the stack unless the sequence contents are themselves really large.

2024Feb28: Adapted the various (validate-*) and (valid?*) functions to consume non-terminating sequences. (Strategy is to 'clamp' them at the length of their counterpart.)

2024Mar01: In (validate-fn-with) and (instrument), wrap (apply f args) in a (try (catch...)) block so that improper invocation is a little helpful.

2024Mar08: add clojore.lang.Symbol to type+predicate+canonical+generator registry

2024Mar12: use numeric coercion functions plus type.check generators to fill out type+predicate+canonical+generator registry
	add hex and binary types
	re-order registry so that they're in some kind of semantic/lexographical  order
	ensure full/exhaustive test coverage of all types

2024Mar09: switch (only-valids) to catch not-false and not-nil, and
	(only-valids) to catch false or nil
	so that predicate application for regex et al that return a non-true nontheless truthy value, will validate

2024Mar10: added set-as-a-predicate feature to scalar specs

2024Mar12: upgrade higher-order function validation to handle arbitrary depth and bare (i.e., non-coll) return values

2024Apr15: generalize (only-valid), (only-invalid), etc to filter both scalar validation results and collection validation results
*earmuffs* on namespace-wide constants (esp., clamp depths)

adjust (validate-scalar-spec) to seemlessly accept non-coll val and predicate, return something normalized like [{:path nil :value val :predicate pred :valid? bool :bare-val-pred true}]
	Since an empty path [] is minimal valid path for a true container, {:path nil} is a good sentinel for a bare value/predicate.
	This would obviate much logic spread around in other functions, particularly in the function-spec namespace, where every function does it's own special handling of bare values.

2024Apr24: add (utility/in?) as a replacement for what clojure.core/contains? appears to be
    (defn in? [coll item] (boolean (some #(= item %) coll)))

2024Mar14: add generator for set-as-a-predicate

2024Apr27: check collection specs for false-or-nil; update to simple clojure.core/not

2024May10: move ordinal accessor helper functions from core to utility namespace; migrate tests

2024May12: rename get-assoc-update-dissoc namespace to something like fn-in

2024May13: change :refer :all to :refer :only [] for more specificity

2024May16: Refactor function-specification utilities to consolidate common code paths: validate-fn-with, validate-fn-meta-spec, wrapping-fn.

2024May22: Adjust data-from-spec to search for a random sample generator within a predicate function's metadata

2024May23: create utility to find predicates in a scalar specification that do not provide a random sample generator

2024May23: create utility to verify that a random sample generator produces a value that satisfies its predicate

2024May25: create a collection-without-predicate utility to report collections in data that lack a predicate within a collection specification

check UUIDv4 for all functions and relevant data

2024May18: list trade-offs, limitations, and intentionally rejected features (i.e., "to-don't")

2024June05: license and copyright statements

check terminology consistency: specification/spec, datums, etc
check for proper elispses, em-dashes
check for passive voice

2024XYZ: add inline code comment elucidations where helpful

2024May30: change seq-regex operators from symbols to keywords
	'* '+ '. '?
	:* :+ :. :?

for data-from-spec, add optional :random-truncate to shorten sequences, remove key-vals, and/or set members

Fix grammer and puctuation of public todo

2024July25: check/add handling to clojure.lang.{interleave,interpose,mapcat,lazy-cat,iteration,zipmap} seq types

2024July25: add `lazy-seq?` utility predicate function

2024July25: declare this as Won'tFix: explore using (list*) to replace bespoke list-concat function
	why: `list-concat` concatenates arbitrary number of input lists into a single output of type list, while `clojure.core/list*` creates a new sequence from input items; `conj` and `cons` don't appear to do anything more elegant, so I'll leave the original function as it currently is

2024July10: adjust fn names for clarity
	(done) validate-scalar-spec -> validate-scalars
	(done) validate-collection-spec -> validate-collections
	(done) valid-scalar-spec? -> valid-scalars?
	(done) valid-collection-spec? -> valid-collections?
	(done) update docs to reflect name changes
	(done) valid-macro-spec? -> valid-macro?
	(done) update docs for valid-macro?

2024July19: implemented `thorougly-valid?` utility; `valid?` and `validate` group of functions remain as before
	re-name fn names for correctness
	valid? ->
		thoroughly-valid? (all entities have a predicate, all predicates return true)
		or
		none-invalid? (any predicates that are present [possibly zero] return true)
	re-consider only-valids

2024July18: expand defpred macro to inspect predicate function and possibly auto-create a competant non-simple generator
	i.e., (fn [x] (and (int? x) (even? x) (< x 100)))
	would yield an even integer, less than one-hundred

2024July21: double-check correctness of `data-without-specs` when handling elements contained in a set; also `data-with-specs` and `specs-without-data`

2024July21: rename
	`data-without-specs` to `scalars-without-predicates`
	`data-with-specs` to `scalars-with-predicates`
	`specs-without-data` to `predicates-without-scalars`
	`collections-without-specs` to `collections-without-predicates`

upgrade `defpred` to handle `every-pred` and `some-fn` predicate constructions

2024July23: increase `max-tries` for random-sample generators so that they'll succeed more often; make it a dynamic var

move clamp and `clamp-in` to fn-in lib

re-implement predicate->generators using multi-way associate data structure
	consider marick/suchwow.relational

done: publish gpg key to OpenPGP keyserver

2024Nov09 :improve changelog: list function changes, multiple possible changes, add specification and validation utilities (create a case study out of this; add to README)

2024Nov11: update fn-in dep to use new version that handles subvectors; add tests

Split out ReadMe and Changelog generation into separate lib projects

Add case study on specifying and validating the changelog

within utility namespace, create a multi-way associative data strucuture that combines all base predicates, their symbols, the canonical value, and the sample generator; use library such.relational/one-to-one-index-on or such.relational/one-to-many-index-on

version tag formatting
	mercurial, dev and publish (inherited from dev repos): 'release 99' or 'version 2-SNAPSHOT0'
	git publish tag: v99

*** Release checklist
	run all tests
		$ lein test :all
	re-generate api docs
		$ lein codox
	update changelog edn
		run changelog generator
	check html spelling
		$ aspell -H -c <filename>.html ;; (adjust spelling in .clj files while tapping i/I ignore)
	check html grammar
	bump version number
		in projects.clj
		in chagelog.edn
		in source.clj
	push to github
		from speculoos-publish
		$ hg pull ../speculoos
		$ cd speculoos
		$ hg update
		$ git commit -a
		possible $ git tag v99
		$ git push -u origin main
			use blosavio, then GitHub classic token instead of pw
	run GitHub workflow that 'deploys static content to GitHub Pages'
	publish to clojars
        $ lein deploy clojars
		check cljdoc generation
	test loading and usage of new deployment
		lein repl
		fresh session of emacs CIDER

*** documentation standards
Show, don't tell. But also: Introduce what we're about to show, and explain what we just saw.
	Be specific; Walk people through the results: Say "The predicate `map?` at key `:x`..." instead of "The results show..."

Strive for a linear, flowing narrative.

Have 'canonical' examples, so people can more quickly understand examples because they've see that thing before.
	Examples:
		vector [42 "abc" 22/7]
		map {:x 42 :y 22/7}

Simple examples!
	Eliminate/minimize nested data structures.
	Use simple predicates.

"People" or "programmers", not "users".

"We" preferred to "you". Be collaborative.

One spot for every topic. One readme document, every topic is discussed in a single, deep-linkable spot.
	API is documented separately.

Be consistent with terminology. Deep links to where terms are discussed, or glossary.

No personal stuff (motivation, stories, etc): It doesn't help other people get their job done.

Hyperlinks: Within a section, upon first mention, create an internal link to...
	scalar validation
	collection validation
	three mottos

	Also, if the section is long and it's been many words since the previous internal link, consider making another link. Especially relevant to Mottos.
