This is a really neat macro, but would people want to rewrite their programs in continuation-passing style just to be able to return multiple values sometimes? (And a macro is not a first-class entity.) Of course, much of the time, the easiest thing to do \is to return a vector or some other destructureable object. But this changes the interface: the function no longer directly returns a singular value. Metadata avoids this problem, but doesn't work on numbers, among other things. So there really are cases where having multiple return values would help (when you want a function to give you one value unless you want more)----preferably without judo! (altough judo is great too.)
Replying to Tassilo: I'm not quite sure I understand this problem: > then changing its > name requires changing all places where clojure.core.quotient/remainder is > used surely the call to Values takes place inside the function definition, which happens \once. If you want a different variable name on \use, you use a let; if you want to return a different variable name on \definition, you use a let inside the function (or perhaps Values could have some sugar for renaming variables). It's true that quotient/remainder must be thread-local (in fact it should really be function-local), but this makes it no different than a let-variable or a function parameter; it doesn't necessarily mean it is mutable. Is X mutable in (let [X 1 X (inc X)]) ? If you slapped that X in a data structure, you would not find it changing under your nose. quotient/remainder really has to behave in the same way----imagine the quotient call creates an invisible let every time. Perhaps I should explain why I think this is "simple". It's simple because a) it allows you to ignore the extra values unless you want them and b) it gives you ready-to-use names. To my taste, b) is very important. One of the reasons I dislike OOP is all the boilerplate like this.x = x. But how many times do you have to write (let [x (some-expensive function ... )....] just so you can use the returned value more than once? What we would do here is write some-expensive-function/ the next time we want to use the value (assuming this is the notation for getting the \default value)----so in this case we don't even \care about multiple return values. If we think of this as a name-generating facility that happens to handle multiple values, we could imagine extensions to it for distinguishing more values---- (quotient 5 2) (quotient 8 3) quotient(5 2)/remainder --> 1 (rand(1) 12) (rand(2) 12) rand(1)(12)/ This is all rather fanciful, and admittedly a huge extension to the language; but what's the harm in thinking about these things? The next time you are telling your kids a bedtime story, you might start as follows: "A man ate some soup. The man was bald, and the soup had an unhappy grasshopper in it. The grasshopper...." Scratch that: you should tell it as follows: Let there be a man my-man, and some soup my-soup, and a grasshopper my- grasshopper. my-man ate some of my-soup. my-man was bald. my-soup had my-grasshopper in it. And my-grasshopper was unhappy.... This makes for earlier bedtimes but worse storytelling. On Jan 3, 12:36 am, Cedric Greevey <cgree...@gmail.com> wrote: > On Mon, Jan 2, 2012 at 2:16 PM, Tassilo Horn <tass...@member.fsf.org> wrote: > > nchurch <nchubr...@gmail.com> writes: > > > Hi, > > >> Someone was asking on the list here about multiple return values, > >> which Clojure does not have. > > >> If the facility were ever added, perhaps multiple values could be > >> accessed via namespaces. Functions would possess another level of > >> namespace and have the ability to inject values into the environment > >> under that namespace. For instance: > > >> (defn quotient [x y] > >> ..... > >> (values quotient remainder)) > > >> (clojure.core/quotient 5 2) > >> --> 2 > >> clojure.core/quotient/remainder > >> --> 1 > > >> This seems simpler than the Common Lisp way. > > > I don't think so. And there are several major problems with that > > approach. First of all, your clojure.core.quotient/remainder var needs > > to be a mutable, thread-local var, because else you couldn't be sure > > that 1 is the remainder of the quotient call directly above, or the > > remainder of a call that happened a blink later in another thread (or > > ForkJoinTask). > > > Another problem is that if the var name is determined by the name of the > > local var in the function which is given to `values', then changing its > > name requires changing all places where clojure.core.quotient/remainder > > is used. > > On top of all that, how often is this needed anyway where > destructuring or metadata can't solve the problem? When performance > isn't a concern and you control the calling functions (or they're > generic things like map and reduce that just pass the return value > through to code you control, such as whatever processes the map > sequence output) you can replace something with a vector of that > something and additional values, and destructure. And even when you > don't control the calling functions, and replacing the return value > with a wrapper of any kind would blow up, if that return value is a > seq, vector, or other Clojure data type that supports metadata, you > can attach metadata (and, to avoid collisions, use namespaced keywords > in it) to smuggle the extra values out. In a similar vein, if a > non-primitive, non-final Java type is the expected value, you can > subclass it with added fields and getters to smuggle out the extra > values (the old "decorator pattern") using deftype or reify or proxy. > (Some of these don't let you explicitly add fields, but all of them > let you define "getters" that close over locals in the function > returning them. You'll need a definterface specifying the getters, > too.) > > When the only objection to destructuring is performance, as is likely > with your quotient-and-remainder case or similar > mathematical-transform cases, there's a final judo move available: > continuation-passing. You make the code that was going to *use* the > results into a *parameter*, which takes all of the results as > arguments. Pre-1.3 you'd probably write something like > > (defmacro quot-and-rem [a b q r & forms] > `(let [a# (long ~a) > b# (long ~b) > t# (... a# ... b# ...) > ~q (...) > ~r (...)] > ~@forms)) > > which would execute forms with q and r bound to the quot and rem, > respectively, of a and b. > > Now you can also pass a function expecting two long primitives to a > function that takes two long primitives and a function and calls that > function with two long primitives, the quotient and the remainder. > (The macro approach still gets you the potential benefits and > drawbacks of inlining both functions: avoiding the overhead of calls > and parameter passing, twice, but also making the current function > larger, perhaps large enough to cause cache misses. Obviously it also > lets you stay source-compatible with older Clojure versions, for > whatever that's worth.) -- 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 Note that posts from new members are moderated - please be patient with your first post. 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