Maybe my brain's just gotten too used to objects, but the idea of reaching into a structure and ripping out its guts seems kinda odd to me. When do you find it more useful (or intuitive or whatever) to destructure an object than to put the code inside the object itself? -- AdamSpitz (who might be confused about what "destructuring macro" means) See http://www.bookshelf.jp/texi/onlisp/onlisp_8.html#SEC54. I think it pretty much speaks for itself; you want to use it practically whenever possible. -- DougMerritt (who might be confused about what you mean by "put the code inside the object itself") So (taking my example right from that page) in Lisp, it seems like you might do something like this: (destructuring-bind ((first last) (month day year) . notes) birthday ...) In Self, I'd have a birthday object, and the birthday object would have three slots: "name", "date", and "notes". (And the name object would have "first" and "last" slots, and the date object would have "month", "day", and "year" slots.) I wouldn't need a "destructuring macro" to give names to the fields of the object; they'd already have names. * No, no, that's cheating, you're assuming that you already '''have''' what we're trying to '''create'''. The fact that in Lisp, it's idiomatic to hold these things in a list ((first last (month day year) . notes), whereas in Self, you'd hold them in a birthday object, is not the point at all. In both cases, that is the '''end''' point of the process, not the start. * The real point is that you're '''starting''' with a flat list that hasn't been broken down into its implicit components yet. Someone hands you a sequence (Marilyn Monroe June 1 1926 "film star; Norma Jean Baker") to start with, and you don't get a choice about that input. You then want to convert that into a more structured thingie (nested list or object) where each implicit field is explicitly made available. * Your birthday object would contain 3 sub-objects, name, date, and notes. Name itself is composed of 2 sub-objects, first and last, and similarly with date. The thing that maps the flat input sequence into that structured object is the "destructuring bind". * The alternative in any language is to just keep accessing the original flat sequence, which is ugly and error prone and doesn't provide error checking in a single spot (what if elements are missing?) It's true, though, that it would be easier to construct a birthday "object" in Lisp than in Self, because in Self I'd have to say the name of each slot as well as the value that goes in it, whereas in the Lisp version I'd only have to say the values (but I'd have to know what position each value should go in). * That's a minor issue; with reflection, you could in Self do something very similar, passing in the target object and the flat sequence, and it could traverse the components of the object, initializing each from the appropriate element of the flat sequence. This would seem to have more gotcha's than if you were just operating on a nested/structured list as destination and flat list as source, but never mind that for the moment. What do you do, in Lisp, when you decide that you want to be able to represent people who have a middle name? It seems like you'd need to go around to all the places where you destructure a name and replace (first last) with (first middle last). * What would you do with any solution, in any language, when the data that you are parsing needs to have changes made to its format? If you're parsing strings, and originally you expect blank separated names, but exactly two of them, and then later you decide to expect exactly three, do you need to change the parser? Of course, because this is a matter of '''what you want''', not what a language provides. Same thing here, except the parsing is over lists rather than strings, and the pattern matching is very simplistic. It also seems like the birthday-related functions wouldn't usually need to be aware that the name object consists of a "first" and "last" slot, or that a date object consists of a month and a day and a year. So maybe most of the time you wouldn't bother destructuring those parts - you'd just say: (destructuring-bind (name date . notes) birthday ...) And then it seems like you'd need to duplicate that call to destructuring-bind in all of your birthday-related functions. (So, of course, you make a macro for that. :) * But again, this is a question of what you wanted in the first place. You could write either one in Lisp, but the first example breaks the data down further than the other. Which do you want? Both work. In your example above, "name" would get bound to (Marilyn Monroe), that's all. Have I taken a wrong turn somewhere? This just seems to me to be a really weird mindset - using a general-purpose data structure and then ripping the pieces out of it and giving them names, rather than using a data structure that knows the names of the pieces. And I'm not sure what it buys you. Can you give me an example of a use of one of these macros that wouldn't be just as easily done in an OO language? Right now all I can think of are examples like this: (defun distance-from-origin (aPoint) (destructuring-bind (x y) aPoint (square-root (+ (square x) (square y))))) In the SelfLanguage, I'd write that as a method on the point object: distanceFromOrigin (x square + y square) squareRoot I've got more questions, but this seems like a good time to stop and find out which parts of the Lisp mindset I've misunderstood. :) -- AdamSpitz Most of this was answered above, but there's the remaining question of why are Lispers fond of lists in contexts where in another language one would use an object. Well, Lisp does have objects, so people would sometimes use them instead. But of course, any time you create a custom data structure, you have to create custom tools for manipulating that data structure, whereas when you use a generic data structure in any language, you can use all of the standard tools without needing to create new ones. So in Lisp, it might well make sense to stick to lists and use standard list manipulations, including destructuring-bind, rather than creating a new birthday object and writing a custom destructuring-bind-to-birthday-object. Whereas in other languages, possibly including Self, standard practice and idioms are such that one just assumes that one needs to do custom programming. (Nothing in Self that I am aware of prevents using a generic list, except that no one got around to creating destructuring-bind as a standard tool in Self.) This was one of those things that got reinvented by so many people in Lisp over the years that it finally caught on as a standard. It seems to me one of the concepts that other languages should borrow. -- DougMerritt I often use destructuring-bind for conversion jobs when the data I have is not in the format I'd like it. Consider for example a (untested, mickey-mouse) HTTP server processing the request from a client: (destructuring-bind (method url http-version) (split-sequence #\Space (read-line stream) :count 3) (make-instance 'http-request :method method :url url :headers (if (> (mismatch request-version "HTTP/0") 6) nil (read-headers stream)))) Within the domain of the application I'd tend to concur with Adam's original viewpoint; also I'd be using an object a la CLOS, not a naked list anyway, so destructuring-bind would be useless as well as inappropriate. -- DanielBarlow, but feel free to refactor and remove sig ''Saying you wouldn't use it if it were useless is beside the point. The question is, what would you do instead, to convert flat input data of some sort into the form that your nested birthday object needed? (E.g. would you create something akin to destructuring-bind that '''would''' work in your domain, or would you limp along without any utility functions to help, or what?)'' I thought that was what Dan just said he ''would'' use destructuring-bind for. He wouldn't use it for internal application data, which is where objects would be handy. -- jt His final paragraph says he'd use objects, and that destructuring-bind would then be useless. I should have added that the chapter of "On Lisp" in question (see URL top of page) goes on to discuss generalizing the notion of destructuring-bind for non-lists, and then to more general patterns (using macros). So although destructuring-bind is what the canned library offers, the point really is the concept behind it, which is a very handy one. And yes, I'm basically suggesting that such a generalization can and should be used to populate the birthday object in question, so that indeed it doesn't deeply matter whether one is using lists or objects. -- dm ---- That makes sense to me. Thanks, guys. My question now, though, is: How often does this problem come up in your world? I'm pretty sure I spend about 0% of my time converting flat input data into more useful forms, even though I definitely agree that Self is worse at it than Lisp is. Maybe the costs are just hidden? Or maybe my particular problem domain (VM and compiler stuff, these days) just naturally has very little flat user input? I dunno. Where are all of these flat input lists coming from, in your world? -- AdamSpitz ---- I think that we're looking at two sides of the same coin. Consider a function in an OO language which takes a Ball object and computes its energy... double energy(object ball) { return 0.5 * ball.mass * ball.velocity^2; } ...compare and contrast to pattern matching against an algebraic data type Ball (a la Haskell)... energy (Ball mass velocity) = 0.5 * mass * velocity^2 Neither is better than the other, just different ways of accomplishing the task of naming pieces of data. -- GregBuchholz ---- See also: PatternMatching