Naming code, the value-identity relation
Table of Contents
There are only two hard things in Computer Science: cache invalidation and naming things.
source: … famous programming joke attributed to Phil Karlton (a Netscape engineer)
[/Names]
… Our name is now layer of indirection, separating what the function does from how it does it….
Indirection, also sometimes called abstraction, is the foundation of the software we write. Layers of indirection can be peeled away incrementally, allowing to us to work within a codebase without understanding its entirety. Without indirection, we’d be unable to write software longer than a few hundred lines.
Names are not the only means of creating indirection, but they are the most common. The act of writing software is the act of naming, repeated over and over again. It’s likely that software engineers create more names than any other profession. Given this, it’s curious how little time is spent discussing names in a typical computer science education. Even in books that focus on practical software engineering, names are seldom mentioned, if at all….
[/Names/Naming data]
… Finding good names is difficult, and so wherever possible we should avoid trying. …
source: https://elementsofclojure.com/ by by Zachary Tellman
clojure.core/def
special form
Usage: (def symbol doc-string? init?)
Creates and interns a global var with the name of symbol in the current namespace (ns) or locates such a var if it already exists. If init is supplied, it is evaluated, and the root binding of the var is set to the resulting value. If init is not supplied, the root binding of the var is unaffected.
Please see https://clojure.org/reference/special_forms#def
source: https://tangrammer.codeberg.page/on-the-clojure-move/output/posts/naming-code.html
1. Naming code as the relation of identity and value
It seems that clojure.core/def is exactly about this relation, and clojure uses a symbol
value as identity.
Once the relation is internalised
(evaluated), the identity/symbol
will be replaced by the value of that naming relation.
So, that's clear, and also, that identity choice (namespaced symbol) is semantically "place oriented": 'folder-path-and-file/symbol-name
.
But, identities don't need to be "an always one and only one value replacement relation". An example of that is clojure.spec/def
(require '[clojure.spec.alpha :as s]) (s/def ::foo string?) ;;=> ::foo (eval ::foo) ;; => ::foo
clojure.spec/def is not only different from clojure/def for that. clojure.spec chooses namespaced-keyword as identity values, but clojure/def chooses symbols for the same.
There are tons of good consequences from using namespaced keywords that I've already talk about it on "Decomplecting clojure.spec: From validation to self-discoverable semantic services", thus I'll not get into that now. In this post I'd like to get into the 1-1 identity-value relation.
2. why "always one and only one" identity-value relation
why not a collection of identities to mean/fetch a place/value? Why not using a combination of generic identities instead of trying a condensed and ambiguous one only identity ("Finding good names is difficult, and so wherever possible we should avoid trying")
2.1. clojure.spec/keys with semantic/compound-identity
so, let's move to spec/keys naming (Maybe Not) problem, and let's try to avoid naming/define a collection of clojure.spec/keys with 1 namespace-keyword (s/def ::xxx (s/keys [....])
and, instead let's use a compound-identity (semantic-namespace.spec.keys/def #{::xxx ::yyy} [....])
with just the collection of spec-keys, to define clojure.spec/keys based on any combination of namespace-keywords.
Example using semantic-namespace/spec.keys
(require '[semantic-namespace.spec.keys :as spec.keys] '[clojure.spec.alpha :as s]) (s/def ::id string?) (s/def ::alias string?) (spec.keys/def #{:app.api.endpoint.get/response :app.domain/user} [::id ::alias]) ;; (spec.keys/valid? #{:app.api.endpoint.get/response :app.domain/user} {::id "foo" ::alias "@foo"}) ;;=> true (spec.keys/valid? #{:app.api.endpoint.get/response :app.domain/user} {::id "foo" ::alias 55}) ;;=> false (spec.keys/valid? #{:app.api.endpoint.get/response :app.domain/user} {::id "foo" ::emal "foo@foo"}) ;;=> false
Hope you enjoy the topic, I'd love to hear your thoughts https://news.ycombinator.com/item?id=45637111