It seems like we're talking about conflation of language
implementation details to simulate a hash-map.  Why not just use a
hash-map for named values?  Or a lazy sequence?  A function returns a
'value', which can be a single thing, a collection of things, or even
an arbitrary graph of things.  If a indirection by a name is required
to reach a value later, then what you really have as your return value
conceptually is a map, and actually returning the map would be more
obvious than projecting the map onto a namespace, with all the baggage
that comes with that.  The downside would be having to refer to the
first value in calling code by name, which I believe is an upside due
to its clarity.

A function that returns 'multiple objects' is equivalent to a function
that returns a meta-object that points to the multiple objects.

Isn't that much more explicit than documenting a hidden var with all
its concurrency semantics, simpler, less verbose AFAICT, and more of a
functional approach?


On Jan 3, 6:05 pm, meb <meba...@gmail.com> wrote:
> I see two fairly straightforward paths to simulating multiple returns
> without breaking existing callers. Both take advantage of thread-local
> state and establish one convention for the caller: before calling the
> function again, every caller interested the extra return values must
> ask for these extra returned values before calling the function again.
> 1.  Use and Abuse VarsThe multiple return idea sounds a lot like the
> global errno facility used commonly in C to communicate out of band
> errors that cannot be conveniently conveyed via the function's
> actually return, except with namespacing to help multiple functions
> cooperate for the scarce resources.  That bit of magic can be pretty
> nasty and metadata usually solves the majority of cases needed to move
> that auxiliary information (errno changed from a simple global
> variable to a complicated macro with the advent of multi-threaded C
> applications).
> However, in cases that metadata simply is unavailable, one way might
> be to augment the run time system with a mapping of functions to a
> thread local store of this auxiliary information just like errno.
>  Clojure already comes with batteries to handle this case called push-
> thread-bindings.  Push-thread-bindings allows a function to
> arbitrarily associate data with predetermined vars, and get-thread-
> bindings provides a function to retreive the information stored in the
> thread.  Then, all that would be necessary to establish multiple
> returns would be to establish a dynamic var associated with each
> function that wanted to be able to return multiple objects.  The
> interested caller would just know to read this preveriously var
> (probably via macro) to get the extra data it wanted.
> The only downside is that, per the documentation, push-thread-bindings
> does not handle its own housekeeping: it requires the calling function
> to ensure that the thread bindings are cleaned up via pop-thread-
> bindings, called in a finally block.  This, of course, is not ideal,
> because the function that establishes the extra information can't be
> sure when or even if its own caller will use it!  A more magical push-
> thread-bindings that could clean up after itself upon thread
> completion is necessary.
> Essentially, it sounds like dynamic vars work basically the way you
> want.  If there is a good way to garbage collect them when the thread
> dies, a couple macros will make implementation relatively
> straightforward.  By the way, more flexibly handling dynamic vars
> seems to be part of a general goal for the 
> future:http://dev.clojure.org/display/design/Improve+Binding.  Directly using
> the ThreadLocal class might also provide you with all the machinery
> necessary to implement this idea and provide garbage collection for
> free on thread completion.
> 2.  Use and Abuse Metadata on the FunctionSimilar to memoize, we could
> store extra return values in function's own metadata via an atom that
> mapped Java thread-id's to extra return values.  To return an extra
> value, the function would simply grab its own metadata set an extra
> return value by thread-id.  Callers wanting to access this extra data
> would be provided a macro to look this value up on demand, probably
> passing the function (something like (return-more! f)).  Subsequent
> calls could just continually update this value.  This essentially
> would emulate thread-local variables though, so the first approach is
> probably preferable.
> Either way, this sounds like it might be implementable via a nice
> little library without having to change the language at all, with very
> little namespace mucking required.
> Hope that helps,Mark
> On Jan 3, 12:24 pm, nchurch <nchubr...@gmail.com> wrote:
>
>
>
>
>
>
>
> > > I think, I'll stop here.  You won't convince me that this approach is
> > > practicable anytime soon. ;-)
>
> > I certainly won't try too hard either.  I'm not questioning here
> > whether it is immediately practicable to implement (maybe not, and in
> > case a very long discussion) but is it potentially useful? (A shorter
> > discussion.)
>
> > In answer to your questions:
>
> > The name of a returned value, of course, \does become part of the
> > interface.  Perhaps library writers would want to have a discipline of
> > using their own internal names and then passing them out in one final
> > values call inside of a let.
>
> > As to the second: the recursive (bar ...) call has no effect on any
> > foo-values used outside of it, whether before or after.  This accords
> > with our expectation for how functions work.
>
> > Think of Values as a magical macro that \at \runtime reaches outside
> > of the function it was used in and writes a little let inside the
> > calling function's scope.  Is this possible?  I don't think so.
> > Presumably it would have to be part of the language, just like Values
> > is part of Common Lisp.

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