. — Inner product
X f.g Y pairs items with g, then reduces with f. It contracts the last axis of X with the first of Y.
1 2 3+.×4 5 6 ⍝ 32
[1 0⋄0 1]+.×2 2⍴⍳4 ⍝ 2 2⍴⍳4Singleton contraction axes extend. Empty contractions use the reduction identity. g⊗ is outer product.
After an array, .name reads a keyed array value: T.name is "name"⊃T. It also works as an assignment target. Plain assignment creates missing records along the path.
T←["n":1 "addr":["city":"LA"]]
T.addr.city ⍝ "LA"
T.n+←1 ⋄ T.n ⍝ 2After an array, . followed by brackets indexes it through Index: x.[I] is [I]⌷x. Each bracket item indexes one axis. The positions on one axis form one item, as in m.[[2 0]]. Dot indexing binds as tightly as .name and needs no parentheses inside a larger expression. Paths chain from left to right. The array is evaluated before the index.
m←3 4⍴⍳12
m.[1 2] ⍝ 6
m.[[2 0]] ⍝ [8 9 10 11⋄0 1 2 3]
m.[⍳2 ¯1] ⍝ 3 7
9,m.[0 1],3 ⍝ 9 1 3After a keyed vector T, T.(expr) evaluates expr with each key of T as a name for its item. Names that aren’t keys resolve in the current scope, and a key hides a name it shares. A key that holds a function binds as a function. Assignments inside the parentheses stay there, and leave T and the current scope unchanged. Execute does the same for code in text: T⍎"price×qty" is T.(price×qty). A scope doesn’t map over an array of records. Write {⍵.(expr)}¨recs for that.
T←["price":2 3;"qty":10 20]
T.(price×qty) ⍝ 20 60
rate←0.5 ⋄ T.(price×rate) ⍝ 1 1.5
r←T.(price←0) ⋄ T.price ⍝ 2 3A dot followed by a digit is a decimal point: .2 is a number. To index position 2, write v.[2] or the subscript v₂. Assignment to a dot path goes through ⌷ and adds missing keys.
v←10 20 30
v.[[2 0]]←7 8 ⋄ v ⍝ 8 20 7