阅读J代码的最佳策略

时间:2010-05-02 16:50:07

标签: j tacit-programming

我已经使用J几个月了,我发现阅读不熟悉的代码(例如我自己没有写过)是该语言最具挑战性的方面之一,特别是当它处于默认状态时。过了一会儿,我想出了这个策略:

1)将代码段复制到word文档

2)从(1)中取出每个操作符并将其放在一个单独的行上,使其垂直读取

3)将每个操作符替换为词汇表页面中的口头描述

4)从J语法到英语语法的粗略翻译

5)使用翻译来识别与概念相关的组件,并使用换行符分隔它们

6)用简明的英文散文写出(5)中每个组成部分应该做的描述

7)根据(6)

写出整个程序应该做什么的描述

8)写下为什么(1)中的代码可以表示来自(7)的设计概念的解释。

虽然我从这个过程中学到了很多东西,但我发现它相当艰巨而且耗时 - 特别是如果有人使用我以前从未遇到的概念设计他们的程序。所以我想知道:J社区中的其他人是否有最喜欢的方法来找出晦涩难懂的代码?如果是这样,这些方法的优点和缺点是什么?

编辑:

我需要分解的代码类型的示例如下:

binconv =: +/@ ((|.@(2^i.@#@])) * ]) @ ((3&#.)^:_1)

我自己写了这个,所以我碰巧知道它需要一个数字输入,将它重新解释为一个三元数组,并将结果解释为base-2中一个数字的表示,最多只有一个重复。 (例如,binconv 5 =(3 ^ 1)+ 2 *(3 ^ 0) - > 1 2 - >(2 ^ 1)+ 2 *(2 ^ 0)= 4.)但如果我偶然发现它没有任何先前的历史或文件,弄清楚它的作用将是一项非常重要的练习。

5 个答案:

答案 0 :(得分:10)

只想添加到Jordan's Answer:如果您没有启用框显示,则可以使用5!:2

明确格式化
   f =. <.@-:@#{/:~
   5!:2 < 'f'
┌───────────────┬─┬──────┐
│┌─────────┬─┬─┐│{│┌──┬─┐│
││┌──┬─┬──┐│@│#││ ││/:│~││
│││<.│@│-:││ │ ││ │└──┴─┘│
││└──┴─┴──┘│ │ ││ │      │
│└─────────┴─┴─┘│ │      │
└───────────────┴─┴──────┘

还有一个树形显示:

   5!:4 <'f'
              ┌─ <.
        ┌─ @ ─┴─ -:
  ┌─ @ ─┴─ #       
──┼─ {             
  └─ ~ ─── /:     

请参阅5!: Representation的词汇表页面以及更改默认值的9!: Global Parameters

另外,对于它的价值,我自己阅读J的方法是手动重新输入表达式,从右到左构建它,并在我去的时候查找各个部分,并使用身份函数来形成临时列车当我需要时。

例如:

   /:~ i.5
0 1 2 3 4
   NB. That didn't tell me anything
   /:~ 'hello'
ehllo
   NB. Okay, so it sorts. Let's try it as a train:
   [ { /:~ 'hello'
┌─────┐
│ehllo│
└─────┘
   NB. Whoops. I meant a train:
   ([ { /:~) 'hello'
|domain error
|       ([{/:~)'hello'
   NB. Not helpful, but the dictionary says
   NB. "{" ("From") wants a number on the left.
   (0: { /:~) 'hello'
e
   (1: { /:~) 'hello'
h
   NB. Okay, it's selecting an item from the sorted list.
   NB. So f is taking the ( <. @ -: @ # )th item, whatever that means...
   <. -: # 'hello'
2
   NB. ??!?....No idea. Let's look up the words in the dictionary.
   NB. Okay, so it's the floor (<.) of half (-:) the length (#)
   NB. So the whole phrase selects an item halfway through the list.
   NB. Let's test to make sure.
   f 'radar' NB. should return 'd'
d
   NB. Yay!

附录:

   NB. just to be clear:
   f 'drara' NB. should also return 'd' because it sorts first
d

答案 1 :(得分:9)

首先尝试将动词分解为其组件,然后查看它们的作用。而不是总是提到词汇,你可以简单地尝试一个数据组件,看看它做了什么,看看你是否可以搞清楚。要查看动词的结构,有助于了解您正在查看的词性,以及如何识别叉子等基本结构(当然,在较大的隐性结构中,用括号分开)。只需在ijx窗口中键入动词并按Enter即可细分结构,并可能有所帮助。

请考虑以下简单示例:<.@-:@#{/:~

我知道<. -: # {/:都是动词,~是副词,{{1}是一个连词(见词汇中的词性链接)。因此,我可以看到这是一个包含左动词@,右动词<.@-:@#和dyad /:~的分叉结构。这需要一些练习才能看到,但有一种更简单的方法,让J通过在ijx窗口中键入并按下回车来显示结构:

{

在这里你可以看到动词的结构(或者,你可以在习惯看这些之后)。然后,如果你不能识别这些碎片,可以和它们一起玩,看看它们是做什么的。

   <.@-:@#{/:~
+---------------+-+------+
|+---------+-+-+|{|+--+-+|
||+--+-+--+|@|#|| ||/:|~||
|||<.|@|-:|| | || |+--+-+|
||+--+-+--+| | || |      |
|+---------+-+-+| |      |
+---------------+-+------+

你可以进一步细分它们并根据需要进行实验来计算它们(这个小例子是一个中值动词)。

J将大量代码打包成几个字符,大型默认动词看起来非常令人生畏,即使对于有经验的用户也是如此。尝试将比你的记录方法更快,你可以通过尝试分解大型复杂动词来学到很多关于J的知识。我想我会建议专注于尝试查看语法结构,然后弄清楚各个部分,逐步建立起来(因为这就是你最终会如何编写隐性动词)。

答案 2 :(得分:3)

(我把它放在答案部分,而不是编辑问题,因为这个问题看起来很长。)

我刚刚发现了一篇关于the jsoftware website的优秀论文,它与乔丹的回答以及我在问题中描述的方法相结合。作者提出了一些相关的意见:

1)由副词修饰的动词是动词。

2)一列三个以上连续动词是一系列的分叉,在最左边可能有一个动词或一个钩子,具体取决于动词的数量。

这加快了将默认表达式翻译成英语的过程,因为它允许您将动词和副词分组为概念单元,然后使用嵌套的fork结构快速确定运算符的实例是monadic还是二元。这是我使用精炼方法进行翻译的一个例子:

d28=: [:+/\{.@],>:@[#(}.-}:)@]%>:@[

[: +/\

{.@] ,

>:@[ #

(}.-}:)@] %

>:@[
  • 上限(加上中缀前缀)

    (在右上角的争论中)ravel

    (增加左上角参数)理货

    在右边的

    (斩首减去缩减) 参数

    除以

    在左参数上增加

  • 序列的部分和 由

    定义

    正确论证的第一项, 与

    一起肆虐

    (一加左参数)复制 的

    (除了第一个元素之外的所有元素)减去 (除最后一个元素外)

    正确论证的

    除以

    (一加左参数)。

  • 序列的部分和 由

    定义

    从相同的初始点开始,

    并附加连续的副本

    从正确的论点派生的点数

    从其中减去每个前任 后继

    并将结果除以数字 要制作的副本

  • 在x之间插入x-many值 y
  • 的项目

答案 3 :(得分:1)

我个人认为J代码就它的作用而言 - 如果我没有任何示例参数,我会很快迷失方向。如果我有例子,我通常很容易看到子表达式正在做什么。

而且,当它变得困难时,这意味着我需要在字典中查找一个单词,或者可能研究它的语法。

通过阅读这里的处方,我认为这与其他人使用该语言的方式并无太大差别。

也许我们应该称之为'测试驱动的理解'?

答案 4 :(得分:1)

我只是想谈谈我的阅读方式: &LT; @ - :@#{/:〜

首先,我知道如果它是一个函数,从命令行开始,必须输入(用于测试)

(小于@ - :@#{/:〜)

现在我查看了括号中的内容。我看到了一个/:〜,它返回一个排序的参数列表,{从列表中选择一个项目,#返回列表中的项目数, - :half,&lt;。,floor ...和我开始认为它可能是中位数, - 列表中项目数量的一半向下舍入,但#是如何得到它的论点?我看着@标志 - 并意识到那里有三个动词 - 所以这是一个分叉。列表在右边进行排序,然后在左边,fork将列表输入到#以获取参数的数量,然后我们知道它占了一半的底线。所以现在我们有了执行顺序:

排序,并将输出作为右参数传递给中间动词。

占据列表中元素数量的一半,这将成为中间动词的左参数。

做中间动词。

这是我的方法。我同意有时这些短语有太多奇怪的东西,你需要查找它们,但我总是在J instant命令行中找出这些东西。