Лучшие стратегии для чтения кода J

Я использую J в течение нескольких месяцев, и я обнаружил, что чтение незнакомого кода (например, я не писал сам) является одним из самых сложных аспектов языка, особенно когда он скрыт. Через некоторое время я придумал эту стратегию:

1) Скопируйте сегмент кода в текстовый документ

2) Возьмите каждый оператор из (1) и поместите его на отдельной строке, чтобы он читал по вертикали

3) Замените каждого оператора своим словесным описанием на странице "Словарь"

4) Сделайте грубый перевод из синтаксиса J в грамматику английского языка

5) Используйте перевод, чтобы идентифицировать концептуально связанные компоненты и разделить их на разрывы строк

6) Напишите описание того, что должен делать каждый компонент из (5), в простой английской прозе

7) Напишите описание того, что должна делать вся программа, на основе (6)

8) Напишите объяснение того, почему код из (1) можно назвать представляющим концепцию дизайна из (7).

Хотя я многому учусь из этого процесса, я считаю, что он довольно тяжелый и трудоемкий - особенно если кто-то разработал свою программу, используя концепцию, с которой я никогда не сталкивался. Поэтому я задаюсь вопросом: есть ли у других людей в сообществе J любимые способы выяснить скрытый код? Если да, то каковы преимущества и недостатки этих методов?

ИЗМЕНИТЬ:

Примером такого кода, который мне нужно было бы сломать, является следующее:

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

Я сам написал это, поэтому я знаю, что он принимает числовой ввод, переинтерпретирует его как тройной массив и интерпретирует результат как представление числа в базе-2 с максимальным удвоением. (например, binconv 5 = (3 ^ 1) + 2 * (3 ^ 0) → 1 2 → (2 ^ 1) + 2 * (2 ^ 0) = 4.) Но если бы я наткнулся на него без любая предыдущая история или документация, выясняя, что это то, что она делает, было бы нетривиальным упражнением.

Ответ 1

Попробуйте сначала разбить глагол на свои компоненты, а затем посмотреть, что они делают. И вместо того, чтобы всегда ссылаться на vocab, вы могли бы просто попробовать компонент на данных, чтобы посмотреть, что он делает, и посмотреть, можете ли вы это понять. Чтобы увидеть структуру глагола, это помогает узнать, какие части речи вы смотрите, и как идентифицировать основные конструкции, такие как вилки (и, конечно же, в более крупных негласных конструкциях, разделенных скобками). Просто введя глагол в окно ijx и нажав enter, он тоже сломает структуру и, вероятно, поможет.

Рассмотрим следующий простой пример: <[email protected]:@#{/:~

Я знаю, что <. -: # { и /: - все глаголы, ~ - это наречие, а @ - конъюнкция (см. части речевой ссылки в vocab). Поэтому я вижу, что это структура вилки с левым глаголом <[email protected]:@#, правильным глаголом /:~ и dyad {. Это требует некоторой практики, но есть более простой способ: пусть J покажет вам структуру, введя ее в окно ijx и нажав enter:

   <[email protected]:@#{/:~
+---------------+-+------+
|+---------+-+-+|{|+--+-+|
||+--+-+--+|@|#|| ||/:|~||
|||<.|@|-:|| | || |+--+-+|
||+--+-+--+| | || |      |
|+---------+-+-+| |      |
+---------------+-+------+

Здесь вы можете увидеть структуру глагола (или вы сможете после того, как привыкнете смотреть на них). Затем, если вы не можете идентифицировать фигуры, поиграйте с ними, чтобы посмотреть, что они делают.

   10?20
15 10 18 7 17 12 19 16 4 2
   /:~ 10?20
1 4 6 7 8 10 11 15 17 19
   <[email protected]:@# 10?20
5

Вы можете разбить их дальше и поэкспериментировать по мере необходимости, чтобы выяснить их (этот маленький пример - медианный глагол).

J упаковывает много кода в несколько символов, а большие молчаливые глаголы могут выглядеть очень пугающе даже для опытных пользователей. Эксперимент будет быстрее, чем ваш метод документирования, и вы можете очень много узнать о J, пытаясь сломать большие сложные глаголы. Думаю, я бы рекомендовал сосредоточиться на попытке увидеть грамматическую структуру, а затем вычислить фигуры, поэтапно создавая ее (так как вы в конечном итоге будете писать молчаливые глаголы).

Ответ 2

Просто хотел добавить к "Ответ на Иордан" : если вы не включили отображение коробки, вы можете форматировать вещи так явно с помощью 5!:2

   f =. <[email protected]:@#{/:~
   5!:2 < 'f'
┌───────────────┬─┬──────┐
│┌─────────┬─┬─┐│{│┌──┬─┐│
││┌──┬─┬──┐│@│#││ ││/:│~││
│││<.│@│-:││ │ ││ │└──┴─┘│
││└──┴─┴──┘│ │ ││ │      │
│└─────────┴─┴─┘│ │      │
└───────────────┴─┴──────┘

Там также отображается дерево:

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

Смотрите страницу словаря 5!: Представление, а также 9!: Глобальные параметры для изменения значения по умолчанию.

Кроме того, для того, что стоит, мой собственный подход к чтению J состоял в том, чтобы повторно набрать выражение вручную, построив его справа налево и разглядывая фигуры, когда я иду, и используя функции идентификации для формирования временных поездов когда мне нужно.

Итак, например:

   /:~ i.5
0 1 2 3 4
   NB. That didn't tell me anything
   /:~ 'hello'
ehllo
   NB. Okay, so it sorts. Let 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 selecting an item from the sorted list.
   NB. So f is taking the ( <. @ -: @ # )th item, whatever that means...
   <. -: # 'hello'
2
   NB. ??!?....No idea. Let look up the words in the dictionary.
   NB. Okay, so it the floor (<.) of half (-:) the length (#)
   NB. So the whole phrase selects an item halfway through the list.
   NB. Let 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

Ответ 3

(Я помещаю это в раздел ответа вместо редактирования вопроса, потому что вопрос выглядит достаточно долго, как есть.)

Я просто нашел отличную статью на веб-сайте jsoftware, которая хорошо работает в сочетании с ответом Джордана и методом, который я описал в вопросе. Автор делает некоторые соответствующие наблюдения:

1) Глагол, модифицированный наречием, является глаголом.

2) Поезд из более чем трех последовательных глаголов представляет собой серию вилок, которые могут иметь один глагол или крючок в крайней левой части в зависимости от количества глаголов.

Это ускоряет процесс перевода молчаливого выражения на английский язык, поскольку он позволяет группировать глаголы и наречия в концептуальные единицы, а затем использовать вложенную структуру вилок, чтобы быстро определить, является ли экземпляр оператора монадическим или двоичным. Вот пример перевода, который я использовал с помощью уточненного метода:

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

[: +/\

{[email protected]] ,

>:@[ #

(}.-}:)@] %

>:@[
  • cap (плюс префикс префикса)

    (head atop right argument) ravel

    (приращение на левом аргументе) tally

    (бег минус урезание) сверху справа Аргумент

    делится на

    приращение на левом аргументе

  • частичные суммы последовательности определяемый

    первый элемент правильного аргумента, raveled вместе с

    (один плюс левый аргумент) копии из

    (все, кроме первого элемента) минус (все, кроме последнего элемента)

    правильного аргумента, деленного на

    (один плюс левый аргумент).

  • частичные суммы последовательности определяемый

    начиная с той же начальной точки,

    и добавления последовательных копий точки, полученные из правильного аргумента

    вычитание каждого предшественника из его преемник

    и деления результата на число копий, которые будут сделаны

  • Интерполирование значений x-many между элементы y

Ответ 4

Лично я думаю о коде J с точки зрения того, что он делает - если у меня нет аргументов в примере, я быстро теряюсь. Если у меня есть примеры, мне обычно легко увидеть, что делает суб-выражение.

И, когда это усложняется, это означает, что мне нужно найти слово в словаре или, возможно, изучить его грамматику.

Чтение рецептов здесь, я понимаю, что это не слишком отличается от того, как другие люди работают с языком.

Может быть, мы должны назвать это "Test Driven Comprehension"?

Ответ 5

Я просто хочу поговорить о том, как я читаю: < @-:. @# {/: ~

Во-первых, я знал, что если это была функция, из командной строки ее нужно было ввести (для тестирования) как

(< @-:. @# {/: ~)

Теперь я посмотрел на материал в круглых скобках. Я видел a/: ~, который возвращает отсортированный список своих аргументов, {который выбирает элемент из списка, #, который возвращает количество элементов в списке, -: half и <., Floor... и Я начал думать, что он может быть медианным, - половина количества элементов в списке округляется, но как # получил свои аргументы? Я посмотрел на знаки @и понял, что там три глагола - так что это вилка. Список входит справа и сортируется, затем слева вилка достала список в #, чтобы получить количество аргументов, и тогда мы знали, что это занимает половину этого. Итак, теперь у нас есть последовательность выполнения:

сортировать и передавать вывод в средний глагол как правильный аргумент.

Возьмите половину из числа элементов в списке, и это станет левым аргументом среднего глагола.

Сделайте средний глагол.

Это мой подход. Я согласен, что иногда фразы имеют слишком много странных вещей, и вам нужно искать их, но я всегда вычисляю этот материал в командной строке J.