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 <[email protected]> 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 [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en
