On Apr 20, 4:17 pm, Mark Engelberg <mark.engelb...@gmail.com> wrote:
> On Mon, Apr 20, 2009 at 1:27 PM, Bradbev <brad.beveri...@gmail.com> wrote:
> > If you promise that
> > functions will accept and return maps with certain keys, then you must
> > keep that promise moving forward.
>
> I think you're missing part of the point of the original post.  You
> don't really want to promise that your functions accept and return
> maps with certain keys; you want to promise that your functions accept
> and return objects that *act* like maps with certain keys.  Promising
> a map is too specific.  You merely want to promise something that
> behaves like a map.  Of course, the simplest thing that acts like a
> map is a map, so in early stages of development, you're certainly
> going to use maps.  But does such a thing scale when you decide you
> need something more complex?
>
> In the original example, the data has grown from a map that actually
> contains a :name to something that retrieves a :name indirectly by
> concatenating :first-name and :last-name.  This is a perfectly
> reasonable example of the way that data representations grow and
> change over time.
>
> Of course, if you had programmed your entire app with getters and
> setters from the outset, making such a modification is relatively
> straightforward (see footnote *).  But most people aren't going to
> program that way from the outset.  They are going to use maps because
> that's the easiest thing, and that means they will get and set things
> using get, assoc, and the syntactic function-like shortcuts for
> retrieving things from maps.
>
> (Footnote * - Well maybe it's not so easy to convert something that
> uses getters and setters from the outset but still uses a map to hold
> the data.  maps are very "leaky abstractions", and even if you provide
> getters and setters, it's entirely possible that users might
> intentionally or unintentionally use something map-specific, rather
> than adhering to the level of indirection that is needed to make a
> conversion easy.)
>
> But then when you eventually want to alter your data representation,
> then what do you do?  It's certainly possible to make your name
> objects some sort of proxy for the associative interface, function
> interface, and anything else relevant to maps, and special case the
> getting of :name, but that's quite cumbersome.  Is there a simple way
> to do this extension?  Not really, and I think this is a legitimate
> concern.

This line of reasoning is one of the reasons for getters and setters.
Smalltalk doesn't give you direct access to an object's data layout
except in the methods of the object. Instead of a data layout, it
gives you a protocol.

Clojure's sequence protocol also provides a protocol in lieu of access
to data fields. That's generally a good way to future-proof your data
structures: divide data design into a public part and a private part.
The layout of the data is private; the public part is the protocol,
which, in Clojure, is made of functions. The more of your data you can
define in terms of functions, the less subject it is to breaking when
you discover that it's a good idea to lay something out differently.

Clojure offers an additional convenience for such abstractions in the
form of polymorphic functions (MultiFns). If you define your data type
in terms of polymorphic functions, you can introduce a new data layout
without even removing the old one. You could even modify the old API
functions to convert data to the new layout when it's encountered.

Is it going to be simpler and more natural to work directly with built-
in data types? Sure. But it's a cliche of development in Lisp that you
cons up some arbitrary data structure, then, in the course of working
with it, discover what the natural API and performance characteristics
are for it, then you write the API in terms of functions and change
the data layout to something that works efficiently with those
functions. To a large extent, that process is what Lisp-hacking *is*.


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to