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.

Reply via email to