Sseveral comments regarding the pinholes post, have forced me, against the deepest elements of my nature, to engage in thought. Since that might never happen again, I thought it meet to record the event.

I'm going to say "I" a lot, because this is mostly my opinions.

Bidirectional programming

As pointed out by Christian Schuhegger in a comment on the original post, lenses were originally introduced to computer science in the context of bidirectional programming, rather than as a tool for dealing with deeply nested immutable structures. He points to a good list of papers on the subject on the subject. I was, it seems, excessively influenced by the use case from the Scalaz tutorial (if not by the exact details).

The original metaphor was, I suppose, that light rays traced out the same path through a lens, irrespective of direction. My take on the metaphor - that a lens is so called because it focuses on small or distant things - is, it seems to me, compelling, but it is not the original intent. Within the context of the original definition (well not the original, original definition, which would be anything in the shape of a lentil), it seems like the things I create with mk-ph-set and mk-ph-get are acceptably the ADT equivalent of lenses, but the mk-ph-mod artifacts are really state transformers. Irrespective of name, however, a tool for dealing with deeply and weirdly nested immutable data structures is demonstrably important to have, and I'm not penitent or creative enough to come up with a completely different metaphor.

Fresnel and protocols and aesthetics

Someone (whose name I'll publish if he asks me to) on twitter mentioned fresnel, which is also a lens library. I did know about this before blogging, but I didn't really want to argue about the differences, because it's such a nice and polished piece of work.

Now that the subject has come up, I'll cop to being aesthetically opposed to creating a protocol for anything that could potentially show up as (or in) the second argument to assoc (or assoc-in), especially since, if the first argument is a hash-map, Lens becomes an incomplete proxy for Object.

Clojure and Clojurescript protocols pay homage to the object-oriented nature of their virtual machines, but do so in moderation, providing abstractions over fundamentally different implementations of fundamental objects that are used in essentially the same way. Hence IPersistentMap being implemented by both (hash-map) and (sorted-map), or core.async having different impl namespaces for Clojure and Clojurescript. In Java code reviews, the detection of cond-like logic immediately results in prescription for a new interface. Not so, in Clojure, which recognizes the limitations of virtual function dispatch and so provides rich semantics for computed dispatch. In Java, the interface is the interface: instructions for using a new library generally involve telling you to implement one.1 Clojure, I think, avoided the word "interface" in conscious rejection of this paradigm.

Pinhole relies on implementations of clojure.lang.Associative, to do the right thing when assoc and get are ultimately called, but beyond that differentiates only between keys that are vectors and keys that are not vectors, and in the rare case where you want a vector as a hash key, you have provide an [in,out] function pair to do the dirty work. That feels right to me, but opinions may of course differ.

  1. Though, perhaps, the wind that brought lambdas to Java 8 may carry off a few of those idioms eventually. 


comments powered by Disqus