Hi, 2009/4/20 Timo Mihaljov <noid....@gmail.com>
> > Laurent PETIT wrote: > > While interesting, this approach seems to me limited to simple cases : > > * limited in possibilities: you are not able to directly use values of > > other fields. So in more complex cases, you won't be able to combine > > calculated values without code repetition or prepraration via lets .. > > * limited in extensibility: in a live system, you won't be able to > > change the function that displays a name because it's "hard-coded" once > > and for all at the same time the data is entered in the system. > > Depending on your use cases, it may or may not be a problem, though. > > * limited for persistence: when you want to persist a lazy-struct-map, > > the computed value is fixed and stored, where it should not be used I > think. > > * limited for equality tests (in relation with "limited in > > extensibility"): you will not be able to succesfully compare for > > equality 2 persons with the exact same essential data, if the way to > > represent names has been even slightly enhanced, since the :name value > > will always be used for the comparison as well. So it's not just a > > problem for performance (very minor in that case, though it may not be > > that minor in other cases), but also a problem of correctness, in the > > long run (for systems you want to keep "live", and without having to do > > weird things when you have to marshall / unmarshall your data). > > Thanks for your insightful reply, Laurent. You are right, lazyseq is > indeed too limited to be used in the way I proposed. It's still very > cool, though, and I'm sure I'll find some other use for it :) No doubt, Meikel made a very interesting addition to Maps with that ! > > > > I would like to offer another possibility. Not ideal, maybe, but that > > may answer your needs. > > Basically, the idea is that with a language like clojure that has higher > > order functions and macros, writing "boiler plate" code should be a code > > smell. The good news being that in Java, this "boiler plate" code smell > > has no solution in some cases (think about design patterns), while with > > a lisp, you can do something for that. > > > > By using a macro, you could generate "boiler plate" getters for your > > structure. And just "override" with new definitions those getter/setters > > that need computations. > > The thing that bothers me is that AFAIK there's no standard macro to do > this in Clojure. AFAIK too. > Combined with the facts that spelling out each accessor > by hand would be a code smell, and all APIs -- internal or external -- > need some form of information hiding to remain stable, I'm left feeling > that information hiding should be done in some other way in Clojure. Well, I don't know how others do. I think we should indeed consider that the macro creating the "getters" accept a :private modifier to not create getters for certain fields. As for information hiding, I don't think that's the philosophy of clojure to prevent users from mistakes in this area ? > > That's why I asked for the idiomatic way to solve the problem in my > example. One can write FORTRAN in any language, and I could write any > language in Clojure, but I'd rather learn Clojure :) > > Another issue I have with the accessor function approach is that it can > be circumvented very easily by accident because the data structure is > exposed to the users of the API. All it takes is typing (:first-name > some-person) instead of (first-name some-person), and you get a map > lookup instead of a call to a getter. Yes, but I think that in the spirit of clojure, data should indeed be considered as black boxes, even if it is so easy to do introspection on them. When Rich said in another thread that maps should certainly deserve to be used as the primary data structures for a vast number of cases, I think he suggested that they be used as the underlying memory data storage. And then, there are different kinds of usages: * manipulation of a piece of data in "end user code". Here, the code should not try to rely on a particular storage implementation (unless if clearly specified in the doc), and rely on functions for manipulating the data. * manipulation of a piece of data in the library code: here the library creator can leverage all the facilities of clojure data structures manipulation. * manipulation of a piece of data by a third party orthogonal library : e.g. a library for storing information in a database. The library can work with the map and store information in a very generic way, without having to know any business detail on the data. Here again, having used a regular map is a big win. Please note that it's my own interpretation, and I also would like to hear here from users using clojure in a more day to day basis than me. > Both forms work as long as the > records are maps containing the key :first-name, but the former breaks > when the data structure changes. This is especially problematic when > wrapping an existing map with accessors -- how can you be sure that you > converted each and every key lookup to a getter call? If you end up having you user code against each and every information, then * either you very largely just expose data structures and it may not be bad then to directly expose their inners * either you expose too much that should instead be exposed as manipulating functions What do others think about these 2 above statements ? The standard OO approach to information hiding would be private fields > and accessor methods. Any suggestions for the One True Clojure Pattern > that addresses the same problem? I think accessor methods. > Now that I've read Programming Clojure I know the capabilities of the > language. My problem is that I have no idea how to apply them to solve > real-world problems, such as the contrived example in my first message. > I hope Mr. Halloway starts writing the sequel soon :) :) --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---