I am getting an unexpected value error
when I use a name to pass a verb as the argument to an adverb.
The adverb (integer binary search with predicate u
and bounds x
):
bsearch=: adverb define
r=. y NB. range
while. ~:/ 1 0 + r do.
n=. ([: -: ] - 2&|) +/r NB. next
r=. n (u n)}r
end.
{.r
)
Some working code:
>&3 bsearch 1 11
3
works=: monad define
r=. 1,y
>&3 bsearch r
)
works 11
3
And now for the surprising behavior:
breaks=: monad define
p=. >&3
r=. 1,y
p bsearch r
)
breaks 11
|value error: p
| r=.n( u n)}r
Setting stops and debugging shows the expected name classes at p bsearch r
(verb adverb noun).
reset=: 13!:0
reset 1
13!:3'breaks 2'
breaks 11
|stop: breaks
| p bsearch r
|breaks[2]
4!:0 ;:'p bsearch r'
3 1 0
5!:4<'p'
┌─ >
── & ─┴─ 3
13!:21''
|stop: bsearch
| r=.y
|bsearch[0]
5!:4<'u'
── p
Inside breaks
everything is as expected. Inside bsearch
the verb u
is defined in terms of a private var p
that isn't there. This is completely unexpected and difficult to work with for more complex use cases.
I tried a little indirection by using ([: p ])
instead of p
but the results were similar.
Using =:
to set p
in breaks
does solve the immediate problem but is an untenable solution.
One workaround might be to have a tacit definition of bsearch
so that using it doesn't introduce a new scope. I think that may be what I need here, but I want a more general solution and I want an understanding of why what I have doesn't work. What I want to be able to do is define a verb in a local scope and pass it or a verb derived from it to an explicitly defined adverb or conjunction.
Thanks
Use u. (and v. for a conjunction) in place of u (and v). u. is similar to u, but it uses the environment of the caller. If you define bsearch as follows:
bsearch=: adverb define
r=. y NB. range
while. ~:/ 1 0 + r do.
n=. ([: -: ] - 2&|) +/r NB. next
r=. n (u. n)} r
end.
{.r
)
Then it should do what you want. See wiki.