Erling Hellenäs wrote:
> q([ } ])x,:y
This doesn't do what you expect because } isn't what you think it is.
Unlike (for example) { which is a verb, } is an adverb: a completely
different kind of animal, with completely different rules. That's why
you're having trouble using it tacitly. Using adverbs tacitly is one of
the most advanced topics in J (essentially because that's done less
frequently, so there's less material, fewer examples, and less support in
both the language and the documentation). While you're learning how to do
it, you'll have to accept that } is different from { and will act
differently even when you use it "the same way" (and I don't mean this in
the sense of "+ is different from * will act differently"; there's an
element of that, of course, but the issue is bigger).
Anyway, if you have x,:y and q and you want to use } tacitly, then you can
say q {.`}.} @, x,:y or something like it.
But notice how I phrased that: "if you have (x,:y) and q ...". That was a
bit of a sidestep: the trick only works if x,:y is treated as a single
entity, precomposed by "somebody else". I think the fundamental issue
you're wrestling with is referring to three independent arguments in J.
Because J is a linear, infix, array-oriented language, verbs can refer to
at most 2 independent arguments (one on the left, the other on the right).
If you've got three independent arguments, then you either need to:
- Calculate (derive) the third argument from one of the other two.
This is usually the easiest and was the approach I was advocating
in my previous message (and it's how e.g. (2|[)mergeMask works),
- pack (at least) two logical arguments into a single physical argument
and unpack them later which is how the x,:y sidestep works (as well
as all the other ,: and ,&< and , etc verbs in the examples I posted)
- or use an adverb, which gives you the ability to address one
additional physical argument.
Now the first approach isn't always possible (the three arguments may be
truly independent: e.g. 3 separate inputs from the user), and the second
carries some overhead both in terms of performance and code complexity.
So sometimes the best option is an adverb.
In fact, the need to address three independent arguments is precisely why
} is defined as an adverb instead of a more typical and convenient verb.
It's cleaner and for most use cases requires less overhead (both in terms
performance of code complexity). But this comes at the cost of pushing
that complexity onto other use cases: in particular, using it tacitly when
all three arguments must be supplied at runtime (as opposed to having at
least one static argument, or of using it in an explicit context where we
can treat the indices as "static" even if they're provided at runtime).
Or, in short: everything is a tradeoff.
> Why is Amend so much faster then From?
Amend has more information than From. In particular, Amend "knows" the
shape of the output, and so can optimize for that, basically by avoiding
the manifestation of a bunch of intermediate structures. By contrast,
probably the biggest cost in q ([ {"0 1 ] ) x,"0 y is building the
intermediate array x ,"0 y (though we'd have to measure to know for
sure). I'm pretty sure we could create a From-based approach which is
competitive in performance to the Amend-based approach, but I'm equally
certain that the best Amend-based approach will beat the best From-based
approach.
-Dan
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm