It's already possible, but metadata is the wrong tool. Wrap all return
values that "might" have multiple values in a vector, and return/bind
as many elements as you want. Add macros to make it less ugly, stir
awhile, and you have multiple values.

Using metadata for this purpose would have real problems: the metadata
for multiple-values would bubble up unintentionally from some
functions, and not from others, giving the mistaken impression that
the higher-level functions are returning multiple values. Consider:

(defn values [v & vs]
  (vary-meta v assoc ::values vs))

(defmacro mv-bind [names val & body]
  `(let [~names (cons ~val (-> ~val meta ::values))]
     ~@body))

(mv-bind [x y] (values {:age 20} "steve")
  (if-not y
    x
    (assoc x :name y)))

This all looks good (aside from the fact that it won't work for types
that can't have metadata, such as integers), right? But from what I
understand of Common Lisp (and that's not a lot), this is a broken
version of its multiple values. Specifically, a function that's not
concerned at all with multiple values, such as conj, will accidentally
return multiple values if its args were carrying around multiple-value
metadata:

(mv-bind [x y] (conj (values [1 2] "whatever") 3 4)
  [x y]) ; returns [[1 2 3 4] "whatever"]!

In contrast, here's a snippet of me trying something similar at an
SBCL repl:

* (multiple-value-bind (x y) (values 1 2) (list x y))
(1 2)

* (multiple-value-bind (x y) (identity (values 1 2)) (list x y))
(1 NIL)

On Mar 25, 9:19 am, Joop Kiefte <iko...@gmail.com> wrote:
> Would it be possible to create something like CL's multiple values this way?
>
> 2011/3/25 James Reeves <jree...@weavejester.com>:
>
>
>
>
>
>
>
> > On 25 March 2011 10:41, msappler <msapp...@web.de> wrote:
> >> Never used metadata until now.
>
> >> I had an insight yesterday that I want to share with you:
>
> >>http://resatori.com/metadata-insight
>
> > In my view, it depends whether your :id key is a surrogate key or a natural 
> > key.
>
> > Object metadata should not affect object equality, so if your :id key
> > is just an internal database identifier, you could include it as
> > metadata.
>
> > But if your :id key is exposed to the outside world, then it should
> > not be metadata, because changing the :id would change the external
> > representation of the object, and therefore affect equality.
>
> > I should also point out that if you want information hiding, then
> > object composition might be a better solution. For example:
>
> >  (defprotocol Identifiable
> >    (id [self] "Return an object's unique id"))
>
> >  (deftype DBRef [db-id data]
> >    Identifiable
> >    (id [_] db-id)
> >    clojure.lang.IDeref
> >    (deref [_] data))
>
> >  (defn db-ref [id data]
> >    (DBRef. id data))
>
> > Then we can get information about the reference, and deref it to get
> > its contents:
>
> >  (def user
> >    (db-ref 193 {:login "fred"}))
>
> >  => (id user)
> >  193
> >  => @user
> >  {:login fred}
>
> > - James
>
> > --
> > 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

-- 
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