I've just managed to get back to this. On Tuesday, 8 April 2014 17:06:31 UTC+10, Carlo wrote: > > On Mon, Apr 07, 2014 at 11:23:31PM -0700, Peter West wrote: > > On Tuesday, 8 April 2014 12:20:16 UTC+10, Carlo wrote: > > > Your issue here is that the symbol "lineseq" in the eval form doesn't > > > have a name to refer to. You do have a local binding for lineseq, but > > > it's not visible to the eval: > > > > > > (let [x 10] (eval 'x)) ;=> Unable to resolve symbol: x
Ok. > ... > > > > There are two ways for you to resolve this. What you're writing sounds > a > > > little bit like it should be a macro, so you could write it as such: > > > > > > (defmacro lines-only [varname prom resource] > > > `(with-open [r# (vcf-res-reader ~resource)] > > > (let [lineseq# (line-seq r#)] > > > (def ~(symbol varname) lineseq#) > > > @~prom))) > > > > > > (I think that's right, but I've not actually tested it.) > > > > > > > I think this will run into the same problem, for reasons mentioned > above. > > Have you tried actually running it? I'm confident that this will not > have the issues that you had with your eval approach. The difference is > that it is a macro, so it is returning code to be run, rather than > attempting to compile and run code at run-time (as eval does). > > This approach did not work. I still had problems getting the symbol for the "def" recognised. > > > Alternatively, you could write it as a function and use "intern": > > > > > > (defn lines-only [varname prom resource] > > > (with-open [r (vcf-res-reader resource)] > > > (let [lineseq (line-seq r)] > > > (intern *ns* (symbol varname) lineseq) > > > @prom))) > > > > > > I'm less confident about this approach, but it should work. > > This form of "lines-only" is a function, but it uses the function > "intern" instead of the special form "def". This lets us maintain our > lexical context while also re-binding a name in the top-level namespace. > "intern" solved the problem. I still need to have two functions, I think, because of timing problems. The "with-open" has to be held open until the client is finished with the line-seq, so it needs to be wrapped in a future. The @prom in the tail of the function serves to hold it open, but it also holds up the thread that is executing the function, until the promise is delivered. In another thread, I have to know when the line-seq has been assigned to the var; that much needs to be synchronous, so I need a promise coming back to the caller to indicate that the var can now be dereferenced. (defn lines-only > > [varname term-prom ok-prom resource] > > (with-open [r (vcf-res-reader resource)] > > (intern *ns* (symbol varname) (line-seq r)) > > (deliver ok-prom (str varname " assigned")) > > @term-prom)) > > >> (defn lazy-line-seq > > [varname term-prom resource] > > (let [ok-prom (promise)] > > (future > > (lines-only varname term-prom ok-prom resource)) > > @ok-prom)) > > > The term-prom is still instantiated prior to the call to lazy-line-seq. One interesting thing about intern is that it will create *or find* a var, setting its root binding. That means that var circumvents the immutability of a var, doesn't it? I thought vars were supposed to be immutable. -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
