EoN

As an experiment in concise function naming, consider using the classic Lisp (x->y) ‘coercion/conversion’ syntax as much as possible in your Clojure code. What are some consequences of programming in this manner?

First note that a slightly gratuitous semantic cast of the ‘coercion/conversion’ endpoints is probably required. By referring to these endpoints as ‘entities’ you accrue a bunch of functions where entity->entity and program logic is then dominated by entity transformations.

Entity oriented Naming.
 

motivation:

In statically typed languages such as OCaml/Haskell/Rust/etc you have both a function name and a function signature.

We need the function names because some things are different from other things, and because type signatures describe ingress and egress things but not necessarily what happens inside the function.

For example the function:
bank-balance
might have a type signature of:
  id->double

but then so might a much nicer function:
bottomless-bank-balance
  id->double

More seriously, it would be nice to have concise function names that are both structurally and semantically descriptive.
 

so then, Entities:

  • as Clojure is dynamically typed these are treated as type-like rather than actual types (although some entities are actually types, e.g., String) and any associated discipline is handled manually

  • the names of functions consist of only one or two entity clauses, representing input and output

  • parameters may not be apparent from the name, but you can easily read the endpoints. Actual function parameters are only an IDE convenience feature away

  • function names may resemble function signatures but the name clauses do not necessarily represent function parameters, and entity-endpoint name clauses do not imply currying

  • entities are value-like but not necessarily pure or referentially transparent

  • they blend well with pre/post block asserts

  • they encourage names like location-value over something like get-location-value

  • and entities & functions mostly sort into the expected lisp-ish categories:

    • nouns: x
    • verbs: x->y
    • predicates: x?
    • state-mutation ops: x!
    • verb-likes/actions: basically everything else (as usual it’s probably best to keep the “everything else” category to a minimum)

 
Some examples from an application written in this manner

  • nouns:
    packed-codon
    upacked-codons (list)
    image-file
    MResult
    string
    out

  • verbs:
    text-file->image-file
    image-file->string
    packed-message-string->MResult

  • state mutator / destructive:
    draw-image-pixel!

  • predicates:
    supported-image-file?
    fasta-file?

  • verb-likes/actions
    cli-decode cli-encode

 
and some example code

(defn otp-image-file->string 
  "Given OTP-encoded image file + appropriate key files,
   return plaintext.

   note: By app convention, filenames are used as 
         file references."

  [fname, key-files]
    (packed-codon-string->string 
      (apply str 
         (map codon->packed-codon
              (string->unpacked-codons 
                (packed-codon-string->string 
                  (image-file->codon-string-themed fname)) 
                string->otp-numcodes   
                key-files )) ))   )



(defn image-file->string 
  "Extract the base-encoded text from an AGCTAG-style image"

  [fname]
    (->> fname
         image-file->codon-string-themed
         packed-codon-string->string ) )

 

results:

pros:

  • reduction of write-time cognitive load, e.g., time spent conjuring the ‘right’ function name
  • enhancement of glance-time efficiency, e.g., time not spent wondering what a function does
  • a reductive stylistic pressure towards smaller, specific transformation functions
  • a kind of inherent facilition of concern separation
  • entities are type-like, and sometimes even actual types

cons:

  • can be wordy. Care must be taken to keep individual entity names “appropriately small”
  • reductive sure, but ‘type-like’ is not the same as ‘type’
  • maybe not generally efficient

mehs:

  • if you try to structurally force everything into a bunch of entity transformations, you’ll sink into a bikeshed-y morass
  • quit saying ‘reductive’; anyway this is just stale, are you unaware of all Lisp Traditions?

 

conclusions:

Ok sure, yet another facile remix of some Lisp-isms. But consider:

These conventions emphasize the ‘verb’ aspect of functions. Construction tends to proceed verb-first, then with the identification of noun-like abstractions.

In practice, cases where entities do not arity-map to function parameters are not really as confusing as might be initially assumed and can help reveal overly complex function signatures. And if there is an implicit pressure towards reducing the number of function parameters, this is probably not a bad thing.

The data transformation style of programming emphasized by this naming scheme seems to fit well with Clojure, and the type-like names do seem to facilitate function reuse.

Using this structural pattern you quickly accrue a lexicon of the entities. This can be a nice addition to your documentation, even if you use a doc generator.

And finally, it’s not unusual for vaguely-named or “processor/handler” functions to tend toward bloat accretion. An entity->entity naming style can help keep such naughtiness in check.  

epilogue:

I have found that this fairly simple style of nomenclature can both improve program readability and facilitate logic organization. Perhaps you will find it helpful as well.

Written on April 16, 2016