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

Reply via email to