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 [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---