Is it possible to write a J program that uses monadic or dyadic verb forms based on runtime values?
Cool, which 3 * 4
leads to 12
, and * 4
leads to 1
, but does the same primitive take advantage of both operations? For example, let's say I would have to define the following:
SIGNUM =: * : [:
TIMES =: [: : *
If I only used SIGNUM
and TIMES
instead *
, could I ever miss smart use *
? That is, x TIMES y
it seems exactly the same as x * y
for everyone x
I can imagine (although my imagination is rather limited in this regard). Does it exist x
where x * y
gives the same result as SIGNUM y
?
In case it is * : [:
not immediately clear, the following: •
SIGNUM =: * : [:
TIMES =: [: : *
SIGNUM 4
1
3 TIMES 4
12
* 4
1
3 * 4
12
3 SIGNUM 4
|domain error: SIGNUM
| 3 SIGNUM 4
TIMES 4
|domain error: TIMES
| TIMES 4
source to share
Record the findings from the comments:
There is no direct language-level reason not to use names for primitives
Using names instead of primitives can hurt performance, since special code doesn't necessarily run. I think this can be fixed by setting the verbs after creating them with f.
.
The reason that the same name for monadic and dyadic verbs is historical: APL used it before. Most verbs have associated actions in monadic / dyadic versions and inflections (multiple endpoints and colons).
For example, it ^
can be expressed in traditional notation as pow(x,y)
or exp(y)
, where x and y are left and right arguments, and e is Euler's constant. Here the monadic version is the same as the dyadic version, with a reasonable default argument on the left. All kinds of inflections of the same root - all verbs related to power: - ^.
performs logarithms (base e for a monad) - ^:
makes a connection of power, applying the verb a variable number of times.
Other relationships between monadic and dyadic verbs can also exist, for example one $
can say to get or set the shape of an array depending on whether it is used as a monad or a dyad.
However, I think that when a person gets a little experience with J, it becomes easier to determine what valency a verb has based on the sentence in which it is used. Examples:
Monad @ Ambiv NB. Mv is always used monadically, Av depends on arguments
Ambiv & Monad
(Dyad Monad) NB. A hook, where verb 1 is always dyadic
(Ambiv Dyad Ambiv) NB. A fork, the middle is one always dyadic
source to share
It was probably a mistake to use the same symbols for binary and monadic builtins, except where the monadic case is the default for the dyad.
TIMES =: 1 & $ :: *
would be a good failure that gives no error.
As for ambivalent cases,
(3 * TIME) 4
12
2 (3 * TIME) 4
24
Another useful ambivalent verb is:
TIMESORSQUARE =: * ~
* ~ 3
9
2 * ~ 3
6
source to share