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