J - инверсные вычисления
От: Mikl Kurkov Россия  
Дата: 28.08.06 20:12
Оценка: 89 (7)
В J есть интересная возможность — выполнения инверсных вычислений. То есть по заданному выражению и результату вычисляется недостающий операнд. Реализовано это следующим образом.Каждая функция может быть задана как пара — основная функция и дополнение. Для этого используется стандартная коньюнкция :. (Obverse). При нормальном вычислении выполнятся левый операнд этой конъюнкции, а в других ситуациях вызывается правый операнд — дополнение.Собственно дополнение может быть любой функцией, но обычно это именно инверсия.

Напрямую дополнение можно вызвать с помощью коньюнкции Power ^: . Левый операнд этой конъюнкции функция а правый число. Причем очень интерсно насколько продуман выбор этих чисел. Если число 0 — то функция не будет вызвана ни разу. Если один — то 1, 2 — 2 и так далее. В J есть понятие бесконечности — она представляется нижим подчеркиванием. Вызов Power с бесконечностью приведет к поиску неподвижной точки функции, т.е. функция будет применяться к своему аргументу пока два последних результата не перестанут отличаться. Тогда она остановится. А что будет если вызвать Power с отрицательным числом? Я думаю вы уже догадались — будет вызвано дополнение (если оно конечно есть).

Многие стандартные функцие уже определены с дополнениями. Понятно что некоторые функции не могут иметь инверсий, т.к. их вычисление связано с потерей информации.Например округление. Кроме того дополнения определены для некоторых карированных случаев (когда один операнд уже зафиксирован), а также некоторых каскадов наречий (например имея результат вычисления +/\ — а это не что иное, как сумма нарастающим итогом, можно получить исходный вектор вызвав +/\ ^: _1)

Для демонстрации приведу простой пример.

Пусть у нас есть функция вычисляющая прибыль на счете со сложным банковским процентом
prc =: 8                              NB. процент годовых
fn1 =: (1 + (prc % 100) % 12)&* ^: 12 NB. сумма на счете через год

Подсчитаем сколько будет на счете через год если положить 20000
fn1 20000
21660

А теперь подсчитаем сколько нужно положить на счет чтобы в конце года на счете оказалось 50000
(fn1 ^: _1) 50000
46168.1

Проверим
fn1 46168.1
50000

Но основное применение дополнений лежит в другой плоскости. Есть такая конъюнкция — &. (Under) Ее оба аргумента — функции. И процесс вычисления выглядит следующим образом. Сначала к параметрам (не конънкции а получившейся в результате ее применения функции) применяется правая функция, затем левая и после этого дополнение правой функции.
Т.е. (u &. v) y = (v ^: _1) u v y

Чаще всего это используется для применения функции к содержимому контейнера (box). Есть две операции < (Box) — поместить в контейнер и > (Open) — достать из контейнера.
Соответственно эти две функции являются дополнениями друг друга. Чтобы сложить содержимое двух контейнеров и оставить результат в контейнере можно использовать глагол +&.>
 a =: <100
 b =: <200
 a +&.> b
┌───┐
│300│
└───┘


Собственно интересно есть ли где еще инверсные вычисления? Думаю на Haskell с его монадами можно и более сложную систему реализовать с движением вперед\назад по вычисляемому выражению. Хотя практическое применение пока в голову не приходит.
--
Mikl
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.