Систематически извлекать существительные аргументы из выражения J

Каков систематический подход к извлечению существительных в качестве аргументов из выражения в 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 может быть автоматически преобразована в молчаливую форму, используя, например, 13 : '>:?x#y', Если кто-то может показать мне, как найти определение 13 : Я мог бы ответить на свой вопрос.

2 ответа

Решение

Если ваша цель состоит в том, чтобы научиться молчаливому стилю, лучше просто изучить его с нуля, а не пытаться запомнить явный алгоритм - J4C и Learning J - хорошие ресурсы, потому что общий случай преобразования выражения из явного в молчаливый неразрешимый

Даже игнорируя тот факт, что со времени J4 не было положений о неявных соединениях, в явном определении глагола вы можете (1) использовать контрольные слова, (2) использовать и изменять глобальные переменные, (3) помещать выражения, содержащие x и / или y как операнды наречия или соединения, и (4) ссылаются на себя. Решение (1), (3) или (4) в общем случае очень сложно, а (2) просто невозможно.*

Если ваше J-предложение является одним из небольшого класса выражений, есть простой способ применить правила форка, чтобы сделать его молчаливым, и это то, что более или менее реализовано в 13 :, Напомним, что

  • (F G H) y является (F y) G (H y), а также x (F G H) y является (x F y) G (x H y) (Монад / Диад Форк)
  • ([: G H) y является G (H y), а также x ([: G H) y является G (x H y) (Монад / Диад Укупоренная Вилка)
  • x [ y является x, x ] y является y и оба [ y а также ] y являются y (Левый / правый)

Обратите внимание на то, как вилки используют свои центральные глаголы в качестве "самого внешнего" глагола: вилка дает двоичное приложение 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 ]) y а также x F y эквивалентны. Изучив правила, не составит труда изменить алгоритм, чтобы получить результат [: <. [ %~ ] - |, который является то, что 13 : '<. (y - x | y) % x' дает.

Условие сбоя достигается всякий раз, когда выражение, содержащее x и / или y операнд наречие или соединение. Иногда возможно восстановить молчаливую форму с некоторым глубоким рефакторингом и знанием глагола и герундиальных форм ^: а также } Но я сомневаюсь, что это можно сделать программно.

Это то, что делает (1), (3) и (4) трудным, а не невозможным. Учитывая знание того, как $: работает, молчаливый программист может найти молчаливую форму, скажем, для функции Аккермана без особых проблем, а умный может даже изменить ее для эффективности. Если бы вы могли найти алгоритм, делающий это, вы бы избавились от программистов, точка.

   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

* Это своего рода ложь. Вы можете реорганизовать всю программу, используя такой глагол, с помощью некоторой продвинутой магии вуду, ср. Выступление Пепе Кинтаны на J конференции 2012 года. Это не красиво.

13 : задокументировано в словаре или NuVoc под : (Явный).

Основная идея заключается в том, что ценность, которую вы хотите быть x становится [ и значение, которое вы хотите быть y становится ], Но как только самый правый токен изменится с существительного (значения) на глагол [ или же ], все утверждение становится поездом, и вам может понадобиться использовать глагол [: или союзы @ или же @: чтобы восстановить композиционное поведение, которое вы имели раньше.

Вы также можете заменить значения фактическими именами x а также y, а затем завернуть все это в ((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 это также 3, Я склонен использовать verb : когда я предоставляю монадическую и диадическую версию, и monad когда мне нужен только монадический смысл.

Если ваш глагол однострочный, как этот, вы можете иногда преобразовать его автоматически в молчаливую форму, заменив 3 или же 4 с 13,

У меня есть несколько заметок о факторизации глаголов в j, которые могут помочь вам с пошаговыми преобразованиями.

приложение: psuedocode для преобразования оператора в молчаливую диаду

Это охватывает только один оператор (одну строку кода) и может не работать, если константные значения, которые вы пытаетесь извлечь, передаются в конъюнкцию или наречие.

Кроме того, оператор не должен ссылаться на другие переменные.

  • присоединять [ x=. xVal [ y =. yVal к заявлению.
  • Подставьте соответствующие значения для xVal а также yVal,
  • Перепишите оригинальное выражение с точки зрения нового x а также 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, u а также v представляют произвольные глаголы, и n произвольное существительное. Обратите внимание, что они включают глаголы

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

И вы сделали.

Другие вопросы по тегам