想象一下我在 J 中定义了以下名称:
m =: >: 我。 2 4 5
这看起来如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
我想创建一个 1 级的单子动词,应用于此列表列表中的每个列表。它将为列表中的每个备用项目加倍 (
+:
) 或加 1 (>:
)。如果我们将此动词应用于第一行,我们会得到 2 3 6 5 10
。
获取与每个项目交替的布尔值列表相当容易,例如,
0 1 $~{:$ m
给我们0 1 0 1 0
。我想,啊哈! 我会使用像 +:
`>: @.
这样的东西,后面跟着一些表情,但我永远无法让它发挥作用。
有什么建议吗?
更新
以下内容似乎可行,但也许 J 专业人士可以将其重构为更优雅的东西。
poop =: monad 定义 (($y) $0 1 $~{:$y) ((]+:)`(]>:) @.[)"0 y )
我会使用排名 1 的斜动词 (
/."1
) - 因此它依次适用于每个列表的连续元素。
您可以将动名词传递给
/.
,它会按顺序应用它们,循环扩展。
+:`>: /."1 m
2
3
6
5
10
12
8
16
10
20
22
13
26
15
30
32
18
36
20
40
42
23
46
25
50
52
28
56
30
60
62
33
66
35
70
72
38
76
40
80
我花了很长时间看了它,我相信我知道为什么
,@
能够恢复论证的形状。
括号短语的参数的形状是右侧传递给它的参数的形状,即使等级被
"
共轭改变(好吧,这就是踪迹所说的,我认为它是一个副词)。如果 ,
是一元的,那么它将是一个 ravel,并且基于 ravel 的副词,结果将是一个向量或至少比输入的等级更低。这就是如果你把连词去掉会发生什么——你得到一个向量。
所以我相信正在发生的是,合词使
,
表现得像二元 ,
,称为追加。附加将其附加内容更改为其附加内容。它没有附加任何内容,但该东西仍然具有形状,因此它最终将中间向量更改回输入的形状。
现在我可能错了。但是
$,"0@(+:
>:/.)"1 >: i. 2 4 5 -> 2 4 5 1 1` 我认为这证明了我的情况。
(,@(+:`>:/.)"1 a) 有效,但请注意 ((* 2 1 $~ $)@(+ 0 1 $~ $)"1 a) 也有效(并且在我的简短测试中,在大型阵列上大约快 20 倍)。
1:`2:"0"1
1:`2:"0"1 >:i.2 4 5
1 2 1 2 1
1 2 1 2 1
1 2 1 2 1
1 2 1 2 1
1 2 1 2 1
1 2 1 2 1
1 2 1 2 1
1 2 1 2 1
"1
表示将交替动词应用于每一行; "0
表示在 0 单元(原子)之间交替,因为它的操作数是动名词。为了清晰演示,我在这里使用了常量动词 1:
和 2:
,但可以用您选择的动词代替。
,@(+:`>:/."1)
关于
,@(+:`>:/."1)
(来自别人的回答)保留原始形状,这是因为u@v被定义为(u@:v)"v
。在这种情况下 v=. +:>:/."1
,所以它的排名是:我在这里使用了常量动词 1:
和 2:
来清楚地演示,但可以用你选择的动词代替。
v=.+:`>:/."1
v b.0
1 1 1
所以
,@v
⟷,@:v"1 1 1
⟷,@:v"1
⟷(,@:v)"1
。这意味着 v
将分别应用于每一行,并且 ,
将整理 v
的每个结果。在我们的例子中,行上 v
的每次迭代都会生成一个 [5 1] 矩阵,因为 f/.
为每行的每个元素(这里简单地说,每个“对角线”)生成一个列表。 ,
然后将该矩阵整理成一行;因此,形状保持不变。
从
[: $ ,"0@(+:`>:/.)"1
获得的 [2 4 5 1 1] 形状中的第一个尾随 1 是由于 (…)"1
结果(每个形状 [5 1])被 2 4
框住,即框架相对于 1 单元(参见 https://code.jsoftware.com/wiki/Vocabulary/FramingFill#Argument_Frame_And_Result_Frame)。后者尾随 1 是由于 ,"0
将每个标量分解为单个向量。