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

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

Related

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

Is there any use for dyadic hooks in J?

It occurs to me that a dyadic hook has the same effect as the same verbs without the parentheses, e.g.,
2 (+ #) 1 2 3
2 + # 1 2 3
These both produce the same result: 5. What can I do with (+ #) that I can't do with + #?
I think that the big difference is that you can use hooks tacitly to build more complex verbs. The hook becomes a module that you can drop into a longer fork. Removing parentheses takes away the functionality of the hook.
2 (+ #) 1 2 3
5
This allows me to pad out a list with 2 more zeros
2 ((+ #){. ]) 1 2 3
1 2 3 0 0
This gives a different result
2 (+ # {. ]) 1 2 3
3 4 5
Dyadic hook solves the composition "problem" where M stands for a monadic verb, and D a dyadic verb.
M#D
(D M)
Dyadic hook is more necessary than the monadic version which is just a short cut for
(] D M)
though dyadic hook can also be modeled as
([ D M#:])
which is also an ambivalent expression. An example:
(, *~)
monadically, appends y and its square
dyadically, appends x and the product of x and y.
(oops, bob is right). Correct ambivalent verb with above explanations.
([ , *~)

column and row join a second box data

I want to column join
┌─┬─┬─┐
│1│1│2│
│2│4│4│
│3│9│6│
└─┴─┴─┘
and I'd like to put a=.1 2 3 as the fourth row, and then put b=.1 1 1 1 as the first column to the new boxed data. How can I do this easily? Do I have to ravel the whole thing and compute the dimention on my own in order to box it again?
Also, if I want the data i.8 to be 2 rows, do I have to calculate the other dimension 4(=8/2) in order to form a matrix 2 4$i.8? And then box it ;/2 4$i.8? Can I just specify one dimension, either the number of row or columns and ask automatic boxing or forming the matrix?
The answer to your question will involve learning about &. , the 'Under' conjunction, which is tremendously useful in J.
m
┌─┬─┬─┐
│1│1│2│
│2│2│4│
│3│9│6│
└─┴─┴─┘
a=. 1 2 3
b=. 1 1 1 1
So we want to add each item of a to each boxed column of m . It would be perfect if we could unbox the column using unbox(>), append the item of a to the column using append (,) and then rebox the column using box (<). This undo, act, redo cycle is exactly what Under (&.) does. It undoes both its right and left arguments ( m and a ) using the verb to its right, then applies the verb to its left, then uses the reverse of the verb to its right on the result. In practice,
m , &. > a
┌─┬─┬─┐
│1│1│2│
│2│2│4│
│3│9│6│
│1│2│3│
└─┴─┴─┘
The fact that a is unboxed when it was never boxed to begin with means that it is not changed, while m is unboxed before (,) is applied to each a . In fact this is used so often in J that &. > is assigned the name 'each'.
m , each a
┌─┬─┬─┐
│1│1│2│
│2│2│4│
│3│9│6│
│1│2│3│
└─┴─┴─┘
Prepending a boxed version of b requires first giving it an extra dimension with laminate (,:) then transposing (|:) b and finally boxing (<) the result. The step of adding the extra dimension is required because transposing swaps the indices and b start as a one-dimensional list.
(<#|:#,:b)
┌─┐
│1│
│1│
│1│
│1│
└─┘
The rest is easy as we just use append (,) to join the boxed b with (m, each a)
(<#|:#,: b) , m , each a
┌─┬─┬─┬─┐
│1│1│1│2│
│1│2│2│4│
│1│3│9│6│
│1│1│2│3│
└─┴─┴─┴─┘
Brackets around (<#|:#,: b) are necessary to force the correct order of execution.
For the second question, you can use i. n m to create a n X m array, which may help.
i. 4 2
0 1
2 3
4 5
6 7
i. 2 4
0 1 2 3
4 5 6 7
but perhaps I am misunderstanding your intentions here.
Hope this helps, bob
append a (with rank): ,"x a
You can simply append (,) a to your unboxed (>) input but you have to be careful with the append rank. You want to append each "item" of a, so you have right rank of "0". You want to apend to a 2-cell so you have a left rank of "2". Therefore, the , you need has rank "2 0. After the append, you rebox your data to a 2-cell with <"2.
<"2(>in)(,"2 0) a
┌─┬─┬─┐
│1│1│2│
│2│4│4│
│3│9│6│
│1│2│3│
└─┴─┴─┘
prepend b: b,
If your b has the right shape you prepend it with b,. The shape you seem to use is (boxed) 4 1:
b =: < 4 1$ 1
┌─┐
│1│
│1│
│1│
│1│
└─┘
b,in
┌─┬─┬─┬─┐
│1│1│1│2│
│1│2│4│4│
│1│3│9│6│
│1│1│2│3│
└─┴─┴─┴─┘

J # not working as expected

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 #:

Resources