J # not working as expected - j

I'm just starting to try to pick up the J language, and am confused by the following:
1 2 +/#{ i.4
1 2
+/ 1 2 { i.4
3
when in the documentation for # it says: "x u#v y ↔ u x v y"
I assume I'm just mistaking one part of speech for another, but can't figure it out
also, how do I tell what type of speech a name is?

NB. u b. 0 returns the rank of u
NB. the rank of a verb determines the arguments it applies to at a time
NB. monadic + y applies to atoms; dyadic x + y applies to pairs of atoms
+ b. 0
0 0 0
NB. monadic +/ y and dyadic x +/ y apply to anything (unbounded rank)
+/ b. 0
_ _ _
NB. monadic { y applies to arrays of atoms;
NB. dyadic x { y applies to pairs of atoms and anything
{ b. 0
1 0 _
NB. u # v has the rank of v
+/#{ b. 0
1 0 _
NB. since 1 2 { i.4 returns atoms at a time, +/ works on atoms
+/"0 [ 1 2 { i.4
1 2
NB. u #: v has unbounded rank
+/#:{ b. 0
_ _ _
NB. +/ applies to all of 1 2 { i.4 at once
+/"_ [ 1 2 { i.4
3
NB. mechanical translation to tacit form
13 : '+/ x { y'
[: +/ {

Wikipedia has, in my biased opinion, a decent writeup on rank, and what it means in the context of the different parts of "speech" in J.
But to answer the original question, J's trace facility can be useful for understanding how its grammar works:
require'trace'
trace '1 2 +/#{ i.4'
This will take you step by step through the parsing process, showing the words being consumed by each production rule and the result each generates.

Ah, I think I may have figured it out, I need to use #: instead of #
1 2 +/#:{ i.4
3
which is what I wanted. Guess I'm going to have to read up some more on rank, which is the only difference between # and #:

Related

Building an array of verbs in J

Is it possible to build arrays of verbs?
I've tried this:
f =: >:
f2 =: f f
There's no syntax error but f2 is clearly not an array of verbs.
For instance
f2 yields f f
$ f2 yields $ f2
0 { f2 yields 0 { f2
2 3 $ f behaves in a similar way.
I'd also like to know if verbs can be activated by the name.
Edited
Instead of f2 =: f f, which is a composition, let's have
f =: >:
f2 =: 2 1 $ f
f2 yields 2 1 $ f
$ f2 yields $ f2
0 { f2 yields 0 { f2
It seems that f2 represents the sequence 2 1 $ f, while in the case of an atom, e.g. 2 1 $ 7, the right side is a vector.
A collection of functions is called a gerund in J and is formed using the tick "`":
g =: +`-`f
┌─┬─┬─┐
│+│-│f│
└─┴─┴─┘
You can use #. to apply the appropriate verb using its index:
4 2 3 (g #. 0) 1 5 6
5 7 9
4 2 3 (g #. 1) 1 5 6
3 _3 _3
4 2 3 (g #. 2) 1 5 6
1 0 0
NB. defining a 2x2 gerund:
k =: 2 2 $ +`-`*`%
┌─┬─┐
│+│-│
├─┼─┤
│*│%│
└─┴─┘
1 (((<0 0) { k) #. 0) 2
3
1 (((<0 1) { k) #. 0) 2
_1
1 (((<1 0) { k) #. 0) 2
2
1 (((<1 1) { k) #. 0) 2
0.5
The index can also be a new verb that depends on the arguments or a list of indices.
As the comments point out, f2=: f f creates a composition and f3=: 2 1 $ f creates a composition as well. In the case of f2 you are defining a hook and in the case of f3 you are defining a fork that will take the results of f when it is given an argument and return the 2 1 shape of that result. The reason that it just parrots back your input is that is the way that J displays verbs without arguments. It shows you the construction, because it does not know what the verb will be applied to.
I think what you may want is the process of making a verb into a gerund, which is the noun form of a verb that can be activated in a number of ways. Creating a gerund is done by inserting a backtick between two verbs or for a single verb, a backtick between the verb and an empty string. Examples of conjunctions that work on gerunds are Agenda and Evoke Gerund.
Although this can be done in J, it is pretty clunky because J does not have the meta-operators that are necessary to manipulate verbs as if they are nouns, aside from turning them into gerunds.

different result once square root is added inside tacit

Very new to J. I love it but still far from fluent in it.
I have managed to hit an issue and I don't know why it is happening. If somebody could please explain why this is occuring I could learn more about this straight-to-the-point language.
Basically I'm doing difference (-) then squared (*:) then sum (+/) then want to take the square root (%:).
Now the sum square error part ( (+/#:*:#:-) ) works fine:
1 2 3 4 5 (+/#:*:#:-) 2 2 2 2 2
15
Then I can get the square root this way (just add %: to left):
%: 1 2 3 4 5 (+/#:*:#:-) 2 2 2 2 2
3.87298
But when I add square root to left of the atco (tacit?) part in the middle it doesn't give me the right result:
1 2 3 4 5 (%:#:+/#:*:#:-) 2 2 2 2 2
1.57001
It instead returns 1.57001 instead of 3.87298.
My understanding is all I have done is add a 'then do square root' but obviously I am wrong. But I don't understand why.
When I dissect:
require 'debug/dissect'
dissect '1 2 3 4 5 (%:#:+/#:*:#:-) 2 2 2 2 2'
I see diff (-) and square (*:) are in their own dissect boxes. But then the last box combines sum (+/) and square root (%:) together, showing %:#:+/ . Not a separate box for +/ and then %: .
As I said I am new to J and am struggling to understand why this is occuring here.
I've tried changing to &, &: and # instead but as expected that didn't fix this issue.
It doesn't appear to be due to some composition limit either since this works fine (has many more atco's combined):
(>:#:>:#:>:#:>:#:>:#:>:#:>:#:>:#:>:) 2 2 2
11 11 11
Thank you
The issue that you are encountering is that
(%:#:+/#:*:#:-)
is being evaluated as
1 2 3 4 5 ((%:#:+)/#:*:#:-) 2 2 2 2 2
1.57001
and not
1 2 3 4 5 %:#:(+/#:*:#:-) 2 2 2 2 2
3.87298
because of the way that conjunctions take as much of the left operand as possible. This means that your partial result from *:#:- is being processed by %:#:+/ when you want %: to apply to the result of +/#:*:#:-
Since you are just starting your journey with J, this may be a bit advanced, but at some point you may want to read the tacit programming section of J for C programmers by Henry Rich. It has a very good explanation about how J sentences are parsed. Parenthesis are your friend when you want to change the order of execution. https://www.jsoftware.com/help/jforc/contents.htm#_Toc191734581
Edit: As #Eelvex points out in the comment below the break actually occurs at (+/), but the result is the same because of the way that conjunctions are evaluated left to right.
You are trying to form a dyadic verb for the expression:
%: +/ *: x - y NB. which we can write as
f g h x - y NB. if we define:
f =: %:
g =: +/
h =: *:
f g h x - y
3.87298
One way of making this a dyadic verb is to apply #: everywhere:
x (f#:g#:h#:-) y
3.87298
x (%: #: (+/) #: *: #: -) y
3.87298
A more idiomatic way of doing it uses under (&.) which inverses a verb after applying another:
f &.: g y NB. expands to
(g-inverse) f g y
g &.: h (x - y)
3.87298
x ( g &.: h #: -) y
3.87298
NB. or if you prefer monadic verbs:
(g &.: h #: -/) x,: y

Sum of arrays with repeated indices

How can I add an array of numbers to another array by indices? Especially with repeated indices. Like that
x
1 2 3 4
idx
0 1 0
y
5 6 7
] x add idx;y NB. (1 + 5 + 7) , (2 + 6) , 3 , 4
13 8 3 4
All nouns (x, idx, y) can be millions of items and I need to fast 'add' verb.
UPDATE
Solution (thanks to Dan Bron):
cumIdx =: 1 : 0
:
'i z' =. y
n =. ~. i
x n}~ (n{x) + i u//. z
)
(1 2 3 4) + cumIdx (0 1 0);(5 6 7)
13 8 3 4
For now, a short answer in the "get it done" mode:
data =. 1 2 3 4
idx =. 0 1 0
updat =. 5 6 7
cumIdx =: adverb define
:
n =. ~. m
y n}~ (n{y) + m +//. x
)
updat idx cumIdx data NB. 13 8 3 4
In brief:
Start by grouping the update array (in your post, y¹) where your index array has the same value, and taking the sum of each group
Accomplish this using the adverb key (/.) with sum (+/) as its verbal argument, deriving a dyadic verb whose arguments are idx on the left and the update array (your y, my updat) on the right.
Get the nub (~.) of your index array
Select these (unique) indices from your value array (your x, my data)
This will, by definition, have the same length as the cumulative sums we calculated in (1.)
Add these to the cumulative sum
Now you have your final updates to the data; updat and idx have the same length, so you just merge them into your value array using }, as you did in your code
Since we kept the update array small (never greater than its original length), this should have decent performance on larger inputs, though I haven't run any tests. The only performance drawback is the double computation of the nub of idx (once explicitly with ~. and once implicitly with /.), though since your values are integers, this should be relatively cheap; it's one of J's stronger areas, performance-wise.
¹ I realize renaming your arrays makes this answer more verbose than it needs to be. However, since you named your primary data x rather than y (which is the convention), if I had just kept your naming convention, then when I invoked cumIdx, the names of the nouns inside the definition would have the opposite meanings to the ones outside the definition, which I thought would cause greater confusion. For this reason, it's best to keep "primary data" on the right (y), and "control data" on the left (x).You might also consider constraining your use of the special names x,y,u,v,m and n to where they're already implicitly defined by invoking an explicit definition; definitely never change their nameclasses.
This approach also uses key (/.) but is a bit more simplistic in its approach.
It is likely to use more space especially for big updates than Dan Bron's.
addByIdx=: {{ (m , i.## y) +//. x,y }}
updat idx addByIdx data
13 8 3 4

LHS of # (atop) seems to be applied to the whole list as done with #: (at) NB. +/#(*:#:mdev)

In the explanation:
n=.1 2 3 4
(+/#*:) n NB. 1 4 9 16
(+/#:*:) n NB. 30
In the first one the sum (+/) is applied on each single result of the square (*:), whereas in the second the sum is applied to the whole result list. So far so good. But the next example does not seem to work that way (probably it does. I just don't get it):
mean=.+/%#
mdev=.-mean
(*:#:mdev) n NB. 2.25 0.25 0.25 2.25
ssq=.+/#(*:#:mdev)
ssq n NB. 5
+/#(*:#:mdev) NB. 5 - why not: 2.25 0.25 0.25 2.25
+/#:(*:#:mdev) NB. 5
In ssq the bracket expression is fine. It works as expected: (*:#:mdev) n results in a list of squares. Here it doesn't matter which # or #: is used. I understand the difference. But the # outside of the bracket should to my understanding sum (+/) each item of the result of (*:#:mdev).
Who can enlighten me where my understanding is wrong? Why is the first # in +/#(*:#:mdev) applied to the whole result list and not to each item as in (+/#*:)?
The short answer is that u #: v y applies u to the entire result of v y whereas u # v y applies u to the intermediate results of v based on the rank of v.
Forks such as mean and hooks such as mdev default to infinite rank if you don't specify otherwise with the Rank conjunction (").
This means that
+/ in +/ # (*: #: mdev) and +/ #: (*: #: mdev)
will have the same rank as
*: #: mdev
which in turn will have the same rank as mdev which means that # will be working on the entire result i.e. infinite rank.
Now, look at the example +/ # *: n where *: has a rank of 0 and it works on atoms (you can find ranks of verbs at the top of the dictionary entries for the primitives such as *:)
This means that # stipulates that +/ is applied to each atom of n resulting in your list 1 4 9 16.
For +/ #: *: the rank of *: has no effect on +/ because of #: and +/ is applied to the entire result which is the sum of the list.
For a more in depth reference, chapter 12 of Henry Rich's J for C programmers covers this topic very well. http://www.jsoftware.com/help/jforc/compound_verbs.htm#_Toc191734368

Finding the minimum integer satisfying a predicate

Is there a good way of finding the smallest integer (starting zero) that satisfies a given predicate in J ?
This is what infinite power with a right verb is for (^:v^:_). For example, find the first integer divisible by 7.
check =: 0 ~: 7 | ] NB. check if y is not a multiple of 7
(>:^:check)^:_ ] 1 NB. increment y (1) while check is true
7
A second point is that if you are searching in an array, you can use the special code f i. 1: (first place where x f y). See: http://www.jsoftware.com/help/release/edot504.htm
Eelvex's answer may be what you are looking for, but one way to read your question is what is the minimum integer greater than 0 in a list. These functions return index of first conditional minimum.
(i. <./) _"_^:(<&0)("0) _3 _1 3 4 2
4
minatleast =: (i. <./)#]#:(_"_^:>("0))
0 minatleast _3 _1 3 4 2
4
3 minatleast _3 _1 3 4 2
2

Resources