On Mar 23, 2009, at 18:20, Mark Engelberg wrote: > standard maps. I guess, loosely speaking, I was envisioning a model > in which seq on a hash map would only traverse the "public keys", so > that library functions will work on your objects, without exposing > innards. But perhaps there is no consistent, sane way to do this, > since it's hard to predict what things might actually need that > private information (like equality, for example).
One way to do this is to implement some well-defined public interface for your type. Your implementation of the interface would then ensure that only selected fields of your data structure are exposed in this way. Take a look at these interfaces, for example: http://code.google.com/p/clojure-contrib/source/browse/trunk/src/ clojure/contrib/generic/collection.clj They are "high-level" versions of some common Clojure functions for manipulating collections. By "high-level" I mean that they are implemented as multimethods for which you can provide specific implementations based on a type tag in metadata. This makes them more versatile, but also slower, so I don't expect something like this to replace the basic Clojure functions. If you want to expose a map-like interface to your data structures in which only certain keys are exposed, you could implement the interfaces assoc, dissoc, and get from clojure.contrib.generic.collection and make them part of the public API of your objects. That still won't stop mischievous or buggy client code from using Clojure's built-in low-level versions of these operations and destroy the integrity of your data, of course. I have been using these interfaces in my code for a while now and overall I like that approach. The biggest problem is that these high- level interface functions have the same names as the corresponding Clojure functions, which can lead to confusion. On the other hand, there are so many of these functions that choosing different names would be a pain as well. For the moment, I have adopted the convention of accessing the high-level versions through a namespace alias, e.g. (ns ... (:require [clojure.contrib.generic.collection :as gc])) (gc/seq my-data) I find this clear enough when reading the code, but it does happen that I forgot to type the gc/ when writing. I am open for better ideas for handling this! Konrad. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---