require 'plot' f =: ] - [: #. [: |. #: 'type dot' plot f"0 p: i. 10000
f, is taking a very explicit approach by making judicious use of “capped” (
[:) verb trains. We’re essentially saying that
f is (
=:) the given number (
]) minus (
-) the base two (
#.) of the reverse (
|.) of the antibase two (
#:) of the given number.
Several members of the J community pointed out to me that this verb could be simplified with the help of the “under” (
&.) conjunction. Let’s dig into what “under” is, and how we can use it.
Verb v defines a transformation of the argument(s) (x and) y into the v-domain. Next, verb u operates on the transformed argument(s). Lastly the result is transformed back from the v-domain to the original domain.
In our example, the domain of our input is base ten, but the transformation we want to apply (reversal) needs to happen in the base two domain. “Under” (
&.) can be used to transform our input into base two (
#:), apply our reversal (
|.), and transform the result of that reversal back to our original base ten domain with the obverse, or opposite, of our base two verb, anti base (
f =: ] - |. &. #:
Out of the box, J comes with many obverse pairings. “Open” (
>), for example, is the obverse of “box” (
<), and visa versa. This pairing is especially useful when applying transformations to boxed values:
1+&.>1;2;3 ┌─┬─┬─┐ │2│3│4│ └─┴─┴─┘
Check out a full listing of obverse pairs at the end of this Shades of J article.
Even compound verbs built up of verbs with well-defined obverse pairings can be used with “under” (
&.). J will correctly infer and apply the compound obverse without any intervention or instruction.
For example, if we wanted to unbox a list of values and then work with them in the “square root domain” (whatever that means), we could do something like this:
1+&.([:%:>)1;2;3 ┌────────────────┐ │4 5.82843 7.4641│ └────────────────┘
J takes each value, opens it and finds its square root (
[:%:>), adds one to the result, and then squares and boxes up (
[:*:<) the incremented value.
Even more interestingly, if an obverse pairing isn’t defined or inferable for a given verb, J lets us define our own pairing using the “obverse” (
As an example, imagine that we have a JSON string holding an array of values. We want to parse our string, perform some operation on those values, and then serialize the resulting list back into JSON.
We can use the
enc_json verbs provided by the
convert/json package, and tell J that the obverse of
json =: dec_json :. enc_json
dec_json on a JSON array like
'[1, 2, 3]' will return a list of boxed numbers, so we’ll want to open each of these boxes, perform our operation, and box the results back up. This sounds like another job for “under” (
transform =: 1&+&.>
All together, we can perform our
transform “under” (
transform &. json '[1, 2, 3]' [2,3,4]
And our result is the JSON string
“Under” is definitely a very powerful conjunction, and I can see myself using it extensively in the future. Thanks to everyone in the J community who was kind enough to point it out and teach me something new!