2

从 J 中的表达式中提取名词作为参数的系统方法是什么?需要明确的是,包含两个文字的表达式应该成为使用左右参数而不是文字的二元表达式。

我正在尝试学习默认风格,所以如果可以避免的话,我不喜欢使用命名变量。

一个具体的例子是我制作的一个简单的掷骰子模拟器:

   >:?10#6    NB. Roll ten six sided dice.
2 2 6 5 3 6 4 5 4 3
   >:?10#6
2 1 2 4 3 1 3 1 5 4

我想系统地将参数 10 和 6 提取到表达式的外部,以便它可以滚动任意数量的任意大小的骰子:

   d =. <new expression here>
   10 d 6  NB. Roll ten six sided dice.
1 6 4 6 6 1 5 2 3 4
   3 d 100  NB. Roll three one hundred sided dice.
7 27 74

随意使用我的示例进行说明,但我希望能够遵循任意表达式的过程。

编辑:我刚刚发现使用 x 和 y 引用的版本可以使用 eg 自动转换为默认形式13 : '>:?x#y'。如果有人可以告诉我如何找到我的定义,13 :我也许可以回答我自己的问题。

4

2 回答 2

5

如果您的目标是学习默契风格,最好从头开始学习,而不是尝试记住显式算法(J4CLearning J是很好的资源),因为将表达式从显式转换为默会的一般情况是棘手

即使忽略自 J4 以来一直没有对默示连词的规定这一事实,在动词的显式定义中,您可以 (1) 使用控制词,(2) 使用和修改全局变量,(3) 放置包含x和/或的表达式y作为副词或连词的操作数,以及 (4) 引用自身。在一般情况下,求解 (1)、(3) 或 (4) 非常困难,而 (2) 则完全不可能。*

如果你的 J 语句是一小类表达式中的一个,有一个简单的方法可以应用 fork 规则使其默认,这或多或少是在13 :. 回顾

  • (F G H) y(F y) G (H y),x (F G H) y(x F y) G (x H y)( Monad/Dyad Fork )
  • ([: G H) yG (H y), 并且x ([: G H) yG (x H y)( Monad/Dyad Capped Fork )
  • x [ yis x, x ] yis y, and both of [ yand ] yare y(左/右)

注意 fork 如何使用它们的中心动词作为“最外层”动词:Fork给出 的二元应用g,而Capped Fork给出一元应用。这正好对应于动词在 J 中的两种应用模式,一元和二元。F G H因此,对于动词和N名词来说,使默认的“二元”表达的快速而简单的算法可能如下所示:

  1. 替换x(x [ y)和。y_ (x ] y)左/右
  2. 将任何其他名词替换n(x N"_ y)
  3. 如果您看到该模式(x F y) G (x H y),请将其替换为x (F G H) y. (叉子
  4. 如果您看到该模式G (x H y),请将其替换为x ([: G H) y. (*加盖叉()
  5. 重复 1 到 4 直到获得表格x F y,此时您获胜。
  6. 如果无法进行更多简化并且您还没有获胜,那么您就输了。

可以为“一元表达式”导出类似的算法,表达式仅依赖于y. 这是一个示例推导。

<. (y - x | y) % x                          NB. start
<. ((x ] y) - (x [ y) | (x ] y)) % (x [ y)  NB. 1
<. ((x ] y) - (x ([ | ]) y)) % (x [ y)      NB. 3
<. (x (] - ([ | ])) y) % (x [ y)            NB. 3
<. x ((] - ([ | ])) % [) y                  NB. 3
x ([: <. ((] - ([ | ])) % [)) y             NB. 4 and we win

这忽略了一些明显的简化,但达到了目的。你可以混合各种其他规则来简化,比如长火车规则——如果Train是奇数长度的火车,那么(F G (Train))它们是等价(F G Train)的——或者观察到x ([ F ]) yx F y是等价的。在学习了规则之后,修改算法得到结果应该不难[: <. [ %~ ] - |,这就是13 : '<. (y - x | y) % x'给出的结果。

每当包含x和/或的表达式y是副词或连词的操作数时,就会达到失败条件。有时可以通过一些深度重构以及对 and 的动词和动名词形式的了解来恢复默认形式^:}但我怀疑这是否可以通过编程方式完成。

这就是使 (1)、(3) 和 (4) 变得困难而不是不可能的原因。有了工作原理的知识,一个隐性程序员可以很容易地为Ackermann 函数$:找到一种隐性形式,而聪明的程序员甚至可以重构它以提高效率。如果你能找到一种算法来做到这一点,那么你就可以避开程序员了。

   ack1 =: (1 + ])`(([ - 1:) $: 1:)`(([ - 1:) $: [ $: ] - 1:)@.(, i. 0:)
   ack2 =: $: ^: (<:@[`]`1:) ^: (0 < [) >:
   3 (ack1, ack2) 3
61 61
   TimeSpace =: 6!:2, 7!:2@]  NB. iterations TimeSpace code
   10 TimeSpace '3 ack1 8'
2.01708 853504
   10 TimeSpace '3 ack2 8'
0.937484 10368

* 这是一种谎言。您可以通过一些高级巫术魔术重构涉及这样一个动词的整个程序,参见。Pepe Quintana2012 年 J 会议上的演讲。它不漂亮。

于 2015-03-09T23:11:40.747 回答
3

13 :记录在(Explicit)下的词汇表NuVoc中。:

基本思想是你想x成为的价值变成你想成为[的价值。但是一旦最右边的记号从名词(值)变成动词,比如or ,整个语句就变成了火车,你可能需要使用动词或连词,或者恢复你之前的组合行为。y][][:@@:

您还可以将值替换为实际名称xy,然后将整个内容包含在 ( (dyad : ' ... ')) 中。那是:

>:?10#6    NB. Roll ten six sided dice.

可以变成:

10 (dyad : '>: ? x # y') 6  NB. dyad is predefined. It's just 4.

如果你只需要y参数,你可以使用monad,它被预定义为3。名字verb也是3verb :当我同时提供一元和二元版本时,我倾向于使用monad单子含义,并且只需要一元含义。

如果您的动词是这样的单行动词,您有时3可以通过将or4替换为 自动将其转换为默认形式13

我有一些关于在 j中分解动词的注释,可以帮助您逐步进行转换。

附录:用于将语句转换为默认 dyad 的伪代码

这仅涵盖单个语句(一行代码),如果您尝试提取的常量值被传递给连词或副词,则可能不起作用。

此外,该语句不得引用其他变量。

  • 附加[ x=. xVal [ y =. yVal到声明中。
  • 用适当的值代替xValyVal
  • x用 new和重写原来的表达式y
  • 改写statement [ x=. xVal [ y=. yVal为:

newVerb =: (4 : 0)
  statement ] y   NB. we'll fill in x later.
)
(xVal) newVerb yVal

x现在你有了一个关于和的明确定义y。将它放在多行而不是使用的原因x (4 : 'expr') y是,如果expr仍然包含字符串文字,您将不得不摆弄转义单引号。

转换第一个名词

由于你之前只有一个管道,所以里面最右边的表达式statement必须是名词。使用以下规则将其转换为分叉:

  • y(])
  • x]x ([)
  • _, __, _9... 9(_:), (__:), (_9:)...(9:)
  • nn"_ (对于任何其他任意名词)

这使整体含义保持不变,因为您刚刚创建的动词会立即被调用并应用于[ y.

无论如何,括号中的这个新的默认动词将成为您将构建的火车的核心。从现在开始,您通过使用语句中最右边的表达式并将其移动到括号内来工作。

叉形范式

从现在开始,我们将假设我们正在创建的默认动词始终是一个叉子。

这个新的默示动词实际上不是叉子,但我们会假装它是,因为任何单词元动词都可以使用以下规则重写为叉子:

v → ([: ] v).

没有理由实际进行这种转换,只是为了简化下面的规则并始终将其称为分叉。

我们不会使用钩子,因为任何钩子都可以通过以下规则重写为分叉:

(uv) → (] u [: v ])

下面的规则应该自动生成这种形式的火车。

转换剩余的令牌

现在我们可以使用以下规则来转换原始管道的其余部分,一次将一项移动到分叉中。

对于所有这些规则,(]x)?不是 J 语法。这意味着]x可能存在也可能不存在。在不改变代码含义的情况下] x转换用法之前,您无法放入。x转换 的实例后x]x是必需的。

遵循 J 约定,uandv表示任意动词,andn是任意名词。请注意,这些包括动词

tokens y u (]x)? (fork) ] y  →  tokens   (]x)? (]  u fork) ] y
tokens x u (]x)? (fork) ] y  →  tokens    ]x   ([  u fork) ] y
tokens n u (]x)? (fork) ] y  →  tokens   (]x)? (n  u fork) ] y
tokens u v (]x)? (fork) ] y  →  tokens u (]x)? ([: v fork) ] y

副词或连词没有规则,因为您应该将它们视为动词的一部分。例如 +:^:3应该被视为单个动词。同样,括号中的任何内容都应单独保留为一个短语。

无论如何,继续应用这些规则,直到你用完令牌。

清理

你最终应该得到:

newVerb =: (4 : 0)
  ] x (fork) ] y
)
(xVal) newVerb yVal

这可以重写为:

(xVal) (fork) yVal

你完成了。

于 2015-03-07T20:33:03.133 回答