Прямая функция
Прямая функция ( dfn , произносится как «ди-фан») — это альтернативный способ определения функции и оператора ( функции высшего порядка ) в языке программирования APL . Прямой оператор также можно назвать доп (произносится как «ди оп»). Их изобрел Джон Скоулз в 1996 году. [1] Они представляют собой уникальную комбинацию программирования массивов , функций высшего порядка и функционального программирования и являются важным отличием APL начала 21 века по сравнению с предыдущими версиями.
Dfn — это последовательность возможно защищенных выражений (или просто охранников) между {
и }
, разделенные ⋄
или новые строки, где ⍺
обозначает левый аргумент и ⍵
право, и ∇
обозначает рекурсию (самоссылка функции). Например, функция PT
проверяет, является ли каждая строка ⍵
является тройкой Пифагора (путем проверки, равна ли сумма квадратов удвоенному квадрату максимума).
PT← {(+/⍵*2)=2×(⌈/⍵)*2}
PT 3 4 5
1
x
4 5 3
3 11 6
5 13 12
17 16 8
11 12 4
17 15 8
PT x
1 0 1 0 0 1
Функция факториала как dfn:
fact← {0=⍵:1 ⋄ ⍵×∇ ⍵-1}
fact 5
120
fact¨ ⍳10 ⍝ fact applied to each element of 0 to 9
1 1 2 6 24 120 720 5040 40320 362880
Описание
[ редактировать ]Правила для dfns обобщены в следующей «справочной карточке»: [2]
{⍺ function ⍵}
|
{⍺⍺ operator ⍵⍵}
|
: сторожить
|
⍺ левый аргумент
|
⍺⍺ левый операнд
|
:: защита от ошибок
|
⍵ правильный аргумент
|
⍵⍵ правый операнд
|
⍺← левый аргумент по умолчанию
|
∇ самоссылка
|
∇∇ самоссылка
|
s← застенчивый результат
|
Dfn — это последовательность возможно защищенных выражений (или просто охранников) между {
и }
, разделенные ⋄
или новые строки.
expression
guard: expression
guard:
Выражения и/или защитные меры оцениваются последовательно. Охранник должен оценить 0 или 1; связанное с ним выражение оценивается, если значение равно 1. dfn завершается после первого незащищенного выражения, которое не заканчивается присваиванием , или после первого защищенного выражения, значение защиты которого равно 1, или если выражений больше нет. Результатом dfn является результат последнего вычисленного выражения. Если последнее вычисленное выражение заканчивается присвоением, результат будет «застенчивым» и не будет автоматически отображаться в сеансе.
Имена, назначенные в dfn являются локальными , по умолчанию и имеют лексическую область действия .
⍺
обозначает левый аргумент функции и ⍵
право; ⍺⍺
обозначает левый операнд и ⍵⍵
право. Если ⍵⍵
встречается в определении, то dfn — двоичный оператор ; если бы только ⍺⍺
происходит, но не ⍵⍵
, то это монадический оператор; если ни то, ни другое ⍺⍺
или ⍵⍵
происходит, то dfn является функцией.
Специальный синтаксис ⍺←expression
используется для присвоения значения по умолчанию левому аргументу, если dfn вызывается монадически, то есть вызывается без левого аргумента. ⍺←expression
иначе не оценивается.
∇
обозначает рекурсию или ссылку на себя функцией, и ∇∇
обозначает ссылку оператора на самого себя. Такое обозначение допускает анонимную рекурсию .
Перехват ошибок обеспечивается средствами защиты от ошибок. errnums::expression
. При возникновении ошибки система динамически ищет среди вызывающих функций средство защиты от ошибок, соответствующее ошибке. Если он найден, среда выполнения возвращается к состоянию непосредственно перед выполнением защиты от ошибок, а соответствующее выражение защиты от ошибок оценивается как результат dfn.
Дополнительные описания, пояснения и учебные пособия по dfns доступны в цитируемых статьях. [3] [4] [5] [6] [7]
Примеры
[ редактировать ]Приведенные здесь примеры иллюстрируют различные аспекты dfns. Дополнительные примеры можно найти в цитируемых статьях. [8] [9] [10]
Левый аргумент по умолчанию
[ редактировать ]Функция {⍺+0j1×⍵}
добавляет ⍺
к 0j1
( я или ) раз ⍵
.
3 {⍺+0j1×⍵} 4
3J4
∘.{⍺+0j1×⍵}⍨ ¯2+⍳5
¯2J¯2 ¯2J¯1 ¯2 ¯2J1 ¯2J2
¯1J¯2 ¯1J¯1 ¯1 ¯1J1 ¯1J2
0J¯2 0J¯1 0 0J1 0J2
1J¯2 1J¯1 1 1J1 1J2
2J¯2 2J¯1 2 2J1 2J2
Значение этой функции можно увидеть следующим образом:
Комплексные числа могут быть составлены как упорядоченные пары действительных чисел, подобно тому, как целые числа могут быть составлены как упорядоченные пары натуральных чисел, а рациональные числа — как упорядоченные пары целых чисел. Для комплексных чисел
{⍺+0j1×⍵}
играет ту же роль, что и-
для целых чисел и÷
для рациональных чисел. [11] : §8
Более того, аналогично этому монадическому -⍵
⇔ 0-⍵
( отрицание ) и монадическое ÷⍵
⇔ 1÷⍵
( обратное ), полезно монадическое определение функции, осуществляемое путем указания значения по умолчанию 0 для ⍺
: если j←{⍺←0 ⋄ ⍺+0j1×⍵}
, затем j ⍵
⇔ 0 j ⍵
⇔ 0+0j1×⍵
.
j←{⍺←0 ⋄ ⍺+0j1×⍵}
3 j 4 ¯5.6 7.89
3J4 3J¯5.6 3J7.89
j 4 ¯5.6 7.89
0J4 0J¯5.6 0J7.89
sin← 1∘○
cos← 2∘○
Euler← {(*j ⍵) = (cos ⍵) j (sin ⍵)}
Euler (¯0.5+?10⍴0) j (¯0.5+?10⍴0)
1 1 1 1 1 1 1 1 1 1
Последнее выражение иллюстрирует формулу Эйлера для десяти случайных чисел с действительной и мнимой частями в интервале .
Одиночная рекурсия
[ редактировать ]Троичное построение множества Кантора начинается с интервала [0,1] и на каждом этапе удаляет среднюю треть из каждого оставшегося подинтервала:
Канторовский набор порядка ⍵
определяется как dfn: [11] : §2.5
Cantor← {0=⍵:,1 ⋄ ,1 0 1 ∘.∧ ∇ ⍵-1}
Cantor 0
1
Cantor 1
1 0 1
Cantor 2
1 0 1 0 0 0 1 0 1
Cantor 3
1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 1
Кантор от 0 до Кантора 6 изображен в виде черных полос:
Функция sieve ⍵
вычисляет битовый вектор длины ⍵
так что немного i
(для 0≤i
и i<⍵
) равен 1 тогда и только тогда, когда i
является простым числом . [10] : §46
sieve←{
4≥⍵:⍵⍴0 0 1 1
r←⌊0.5*⍨n←⍵
p←2 3 5 7 11 13 17 19 23 29 31 37 41 43
p←(1+(n≤×⍀p)⍳1)↑p
b← 0@1 ⊃ {(m⍴⍵)>m⍴⍺↑1 ⊣ m←n⌊⍺×≢⍵}⌿ ⊖1,p
{r<q←b⍳1:b⊣b[⍵]←1 ⋄ b[q,q×⍸b↑⍨⌈n÷q]←0 ⋄ ∇ ⍵,q}p
}
10 10 ⍴ sieve 100
0 0 1 1 0 1 0 1 0 0
0 1 0 1 0 0 0 1 0 1
0 0 0 1 0 0 0 0 0 1
0 1 0 0 0 0 0 1 0 0
0 1 0 1 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 1
0 1 0 0 0 0 0 1 0 0
0 1 0 1 0 0 0 0 0 1
0 0 0 1 0 0 0 0 0 1
0 0 0 0 0 0 0 1 0 0
b←sieve 1e9
≢b
1000000000
(10*⍳10) (+⌿↑)⍤0 1 ⊢b
0 4 25 168 1229 9592 78498 664579 5761455 50847534
Последняя последовательность, количество простых чисел меньше степени 10, является начальным сегментом OEIS : A006880 . Последнее число 50847534 — это количество простых чисел, меньших . Оно называется числом Бертельсена, которое в MathWorld незабываемо описано как «ошибочное имя, которому ошибочно присвоено ошибочное значение ". [12]
sieve
использует два разных метода для маркировки составных чисел нулями, оба из которых выполняются с использованием локальных анонимных dfns: первый использует решето Эратосфена для начальной маски 1 и префикса простых чисел 2 3...43 с использованием вставки . оператора ⌿
( правый сгиб ). (Длина префикса получается путем сравнения с исходной функцией ×⍀p
.) Второй находит наименьшее новое простое число q
оставшийся в b
( q←b⍳1
) и устанавливается в 0 бит q
себя и биты в q
умножить числа в оставшихся 1 битах в начальном сегменте b
( ⍸b↑⍨⌈n÷q
). Этот второй dfn использует хвостовую рекурсию.
Хвостовая рекурсия
[ редактировать ]Обычно функция факториала определяется рекурсивно (как указано выше ), но ее можно запрограммировать для использования хвостовой рекурсии с использованием левого аргумента аккумулятора: [13]
fac←{⍺←1 ⋄ ⍵=0:⍺ ⋄ (⍺×⍵) ∇ ⍵-1}
Точно так же определитель квадратной комплексной матрицы с использованием метода исключения Гаусса можно вычислить с помощью хвостовой рекурсии: [14]
det←{ ⍝ determinant of a square complex matrix
⍺←1 ⍝ product of co-factor coefficients so far
0=≢⍵:⍺ ⍝ result for 0-by-0
(i j)←(⍴⍵)⊤⊃⍒|,⍵ ⍝ row and column index of the maximal element
k←⍳≢⍵
(⍺×⍵[i;j]ׯ1*i+j) ∇ ⍵[k~i;k~j] - ⍵[k~i;j] ∘.× ⍵[i;k~j]÷⍵[i;j]
}
Множественная рекурсия
[ редактировать ]Раздел числа неотрицательного целого вектор натуральных чисел таких, что n = +⌿v
, где порядок в не является существенным. Например, 2 2
и 2 1 1
являются разделами из 4, и 2 1 1
и 1 2 1
и 1 1 2
считаются одним и тем же разделом.
Функция разделения подсчитывает количество разделов. Функция представляет интерес в теории чисел , которую изучали Эйлер , Харди , Рамануджан , Эрдеш и другие. Рекуррентное соотношение
Эйлера выведено из теоремы о пятиугольных числах . [15] Написано как dfn: [10] : §16
pn ← {1≥⍵:0≤⍵ ⋄ -⌿+⌿∇¨rec ⍵}
rec ← {⍵ - (÷∘2 (×⍤1) ¯1 1 ∘.+ 3∘×) 1+⍳⌈0.5*⍨⍵×2÷3}
pn 10
42
pn¨ ⍳13 ⍝ OEIS A000041
1 1 2 3 5 7 11 15 22 30 42 56 77
Базовый шаг 1≥⍵:0≤⍵
заявляет, что для 1≥⍵
, результат функции 0≤⍵
, 1, если ⍵ равно 0 или 1, и 0 в противном случае. Рекурсивный шаг является сильно рекурсивным. Например, pn 200
приведет к тому, что функция будет применена к каждому элементу rec 200
, которые:
rec 200
199 195 188 178 165 149 130 108 83 55 24 ¯10
198 193 185 174 160 143 123 100 74 45 13 ¯22
и pn 200
для вычисления требуется больше времени, чем возраст Вселенной ( функция вызывает саму себя). [10] : §16 Время вычислений можно сократить за счет мемоизации , реализованной здесь как прямой оператор (функция более высокого порядка). M
:
M←{
f←⍺⍺
i←2+'⋄'⍳⍨t←2↓,⎕cr 'f'
⍎'{T←(1+⍵)⍴¯1 ⋄ ',(i↑t),'¯1≢T[⍵]:⊃T[⍵] ⋄ ⊃T[⍵]←⊂',(i↓t),'⍵}⍵'
}
pn M 200
3.973E12
0 ⍕ pn M 200 ⍝ format to 0 decimal places
3972999029388
Это значение pn M 200
согласуется с расчетами Харди и Рамануджана в 1918 году. [16]
Оператор заметок M
определяет вариант своей функции операнда ⍺⍺
использовать кэш T
и затем оценивает его. С операндом pn
вариант такой:
{T←(1+⍵)⍴¯1 ⋄ {1≥⍵:0≤⍵ ⋄ ¯1≢T[⍵]:⊃T[⍵] ⋄ ⊃T[⍵]←⊂-⌿+⌿∇¨rec ⍵}⍵}
Прямой оператор (доп)
[ редактировать ]Быстрая сортировка массива ⍵
работает путем случайного выбора «опорной точки» среди ее основных ячеек, а затем объединения отсортированных основных ячеек, которые строго предшествуют опорной точке, основных ячеек, равных опорной точке, и отсортированных основных ячеек, которые строго следуют за опорной точкой, как это определено путем сравнения функция ⍺⍺
. Определяется как прямой оператор (dop) Q
:
Q←{1≥≢⍵:⍵ ⋄ (∇ ⍵⌿⍨0>s)⍪(⍵⌿⍨0=s)⍪∇ ⍵⌿⍨0<s←⍵ ⍺⍺ ⍵⌷⍨?≢⍵}
⍝ precedes ⍝ follows ⍝ equals
2 (×-) 8 8 (×-) 2 8 (×-) 8
¯1 1 0
x← 2 19 3 8 3 6 9 4 19 7 0 10 15 14
(×-) Q x
0 2 3 3 4 6 7 8 9 10 14 15 19 19
Q3
это вариант, который объединяет три части, заключенные в функцию ⊂
вместо частей как таковых . Три части, генерируемые на каждом рекурсивном этапе, очевидны в структуре конечного результата. Применяя функцию, полученную из Q3
к одному и тому же аргументу несколько раз дает разные результаты, поскольку опорные точки выбираются случайным образом. по порядку Обход результатов дает тот же отсортированный массив.
Q3←{1≥≢⍵:⍵ ⋄ (⊂∇ ⍵⌿⍨0>s)⍪(⊂⍵⌿⍨0=s)⍪⊂∇ ⍵⌿⍨0<s←⍵ ⍺⍺ ⍵⌷⍨?≢⍵}
(×-) Q3 x
┌────────────────────────────────────────────┬─────┬┐
│┌──────────────┬─┬─────────────────────────┐│19 19││
││┌──────┬───┬─┐│6│┌──────┬─┬──────────────┐││ ││
│││┌┬─┬─┐│3 3│4││ ││┌┬─┬─┐│9│┌┬──┬────────┐│││ ││
│││││0│2││ │ ││ ││││7│8││ │││10│┌──┬──┬┐││││ ││
│││└┴─┴─┘│ │ ││ ││└┴─┴─┘│ │││ ││14│15││││││ ││
││└──────┴───┴─┘│ ││ │ │││ │└──┴──┴┘││││ ││
││ │ ││ │ │└┴──┴────────┘│││ ││
││ │ │└──────┴─┴──────────────┘││ ││
│└──────────────┴─┴─────────────────────────┘│ ││
└────────────────────────────────────────────┴─────┴┘
(×-) Q3 x
┌───────────────────────────┬─┬─────────────────────────────┐
│┌┬─┬──────────────────────┐│7│┌────────────────────┬─────┬┐│
│││0│┌┬─┬─────────────────┐││ ││┌──────┬──┬────────┐│19 19│││
│││ │││2│┌────────────┬─┬┐│││ │││┌┬─┬─┐│10│┌──┬──┬┐││ │││
│││ │││ ││┌───────┬─┬┐│6│││││ │││││8│9││ ││14│15││││ │││
│││ │││ │││┌┬───┬┐│4│││ │││││ │││└┴─┴─┘│ │└──┴──┴┘││ │││
│││ │││ │││││3 3│││ │││ │││││ ││└──────┴──┴────────┘│ │││
│││ │││ │││└┴───┴┘│ │││ │││││ │└────────────────────┴─────┴┘│
│││ │││ ││└───────┴─┴┘│ │││││ │ │
│││ │││ │└────────────┴─┴┘│││ │ │
│││ │└┴─┴─────────────────┘││ │ │
│└┴─┴──────────────────────┘│ │ │
└───────────────────────────┴─┴─────────────────────────────┘
Приведенная выше формулировка не нова; см., например, рисунок 3.7 классической книги «Проектирование и анализ компьютерных алгоритмов» . [17] Однако, в отличие от пиджин -программы АЛГОЛ, показанной на рис. 3.7, Q
является исполняемым, а частичный порядок, используемый при сортировке, является операндом, (×-)
примеры выше. [9]
Dfns с операторами и поездами
[ редактировать ]Dfns, особенно анонимный dfns, хорошо работает с операторами и поездами. Следующий фрагмент решает головоломку «Жемчужины программирования»: [18] дан словарь английских слов, представленный здесь в виде матрицы символов a
, найдите все наборы анаграмм.
a {⍵[⍋⍵]}⍤1 ⊢a ({⍵[⍋⍵]}⍤1 {⊂⍵}⌸ ⊢) a
pats apst ┌────┬────┬────┐
spat apst │pats│teas│star│
teas aest │spat│sate│ │
sate aest │taps│etas│ │
taps apst │past│seat│ │
etas aest │ │eats│ │
past apst │ │tase│ │
seat aest │ │east│ │
eats aest │ │seta│ │
tase aest └────┴────┴────┘
star arst
east aest
seta aest
Алгоритм работает путем индивидуальной сортировки строк ( {⍵[⍋⍵]}⍤1 ⊢a
), и эти отсортированные строки используются как ключи («подпись» в описании «Жемчужины программирования») для ключевого оператора ⌸
сгруппировать строки матрицы. [9] : §3.3 Выражение справа представляет собой поезд , синтаксическую форму, используемую APL для реализации неявного программирования . Здесь это изолированная последовательность трех функций такая, что (f g h) ⍵
⇔ (f ⍵) g (h ⍵)
, откуда выражение справа эквивалентно ({⍵[⍋⍵]}⍤1 ⊢a) {⊂⍵}⌸ a
.
Лексическая область видимости
[ редактировать ]Когда внутренний (вложенный) dfn ссылается на имя, он ищется наружу через включающий dfns, а не вниз по стеку вызовов . Говорят, что этот режим использует лексическую область видимости вместо обычной динамической области видимости APL . Различие становится очевидным только в том случае, если выполняется вызов функции, определенной на внешнем уровне. Для более обычных внутренних звонков эти два режима неотличимы. [19] : стр.137
Например, в следующей функции which
, переменная ty
определяется как в which
себя и во внутренней функции f1
. Когда f1
звонит наружу, чтобы f2
и f2
относится к ty
, он находит внешний (со значением 'lexical'
), а не тот, который определен в f1
(со значением 'dynamic'
):
which←{
ty←'lexical'
f1←{ty←'dynamic' ⋄ f2 ⍵}
f2←{ty,⍵}
f1 ⍵
}
which ' scope'
lexical scope
Защита от ошибок
[ редактировать ]Следующая функция иллюстрирует использование защиты от ошибок: [19] : стр.139
plus←{
tx←'catch all' ⋄ 0::tx
tx←'domain' ⋄ 11::tx
tx←'length' ⋄ 5::tx
⍺+⍵
}
2 plus 3 ⍝ no errors
5
2 3 4 5 plus 'three' ⍝ argument lengths don't match
length
2 3 4 5 plus 'four' ⍝ can't add characters
domain
2 3 plus 3 4⍴5 ⍝ can't add vector to matrix
catch all
В APL ошибка номер 5 — это «ошибка длины»; ошибка номер 11 — «ошибка домена»; а номер ошибки 0 — это «объемный комплекс» для ошибок с номерами от 1 до 999.
В примере показана очистка локальной среды перед вычислением выражения защиты от ошибок. Местное название tx
настроен для описания сферы действия следующей защиты от ошибок. При возникновении ошибки среда разматывается, чтобы выставить tx
статически правильное значение.
Dfns против tradfns
[ редактировать ]Поскольку прямые функции — это dfns, функции APL, определенные традиционным способом, называются tradfns, что произносится как «trad funs». Здесь dfns и tradfns сравниваются путем рассмотрения функции sieve
: Слева находится dfn (как определено выше ); посередине — торговля с использованием управляющих структур ; справа — trafn с использованием gotos ( →
) и метки линий .
sieve←{
4≥⍵:⍵⍴0 0 1 1
r←⌊0.5*⍨n←⍵
p←2 3 5 7 11 13 17 19 23 29 31 37 41 43
p←(1+(n≤×⍀p)⍳1)↑p
b← 0@1 ⊃ {(m⍴⍵)>m⍴⍺↑1 ⊣ m←n⌊⍺×≢⍵}⌿ ⊖1,p
{r<q←b⍳1:b⊣b[⍵]←1 ⋄ b[q,q×⍸b↑⍨⌈n÷q]←0 ⋄ ∇ ⍵,q}p
}
|
∇ b←sieve1 n;i;m;p;q;r
:If 4≥n ⋄ b←n⍴0 0 1 1 ⋄ :Return ⋄ :EndIf
r←⌊0.5*⍨n
p←2 3 5 7 11 13 17 19 23 29 31 37 41 43
p←(1+(n≤×⍀p)⍳1)↑p
b←1
:For q :In p ⋄ b←(m⍴b)>m⍴q↑1 ⊣ m←n⌊q×≢b ⋄ :EndFor
b[1]←0
:While r≥q←b⍳1 ⋄ b[q,q×⍸b↑⍨⌈n÷q]←0 ⋄ p⍪←q ⋄ :EndWhile
b[p]←1
∇
|
∇ b←sieve2 n;i;m;p;q;r
→L10 ⍴⍨ 4<n ⋄ b←n⍴0 0 1 1 ⋄ →0
L10:
r←⌊0.5*⍨n
p←2 3 5 7 11 13 17 19 23 29 31 37 41 43
p←(1+(n≤×\p)⍳1)↑p
i←0 ⋄ b←1
L20:
b←(m⍴b)>m⍴p[i]↑1 ⊣ m←n⌊p[i]×≢b
→L20 ⍴⍨ (≢p)>i←1+i
b[1]←0
L30:
→L40 ⍴⍨ r<q←b⍳1 ⋄ b[q,q×⍸b↑⍨⌈n÷q]←0 ⋄ p⍪←q ⋄ →L30
L40:
b[p]←1
∇
|
- Dfn может быть анонимным ; должен быть назван trafn.
- Имя dfn присваивается (
←
); имя tradfn присваивается путем встраивания имени в представление функции и применения⎕fx
(системная функция) к этому представлению. - В качестве операнда dfn удобнее, чем tradfn (см. предыдущие пункты: tradfn должен быть назван; tradfn именуется путем встраивания...).
- Имена, назначенные в dfn, являются локальными по умолчанию ; имена, назначенные в tradfn, являются глобальными , если они не указаны в списке локальных имен.
- Локальные переменные в dfn имеют лексическую область видимости ; locals в tradfn имеют динамическую область видимости , видимую в вызываемых функциях, если они не затенены списком их locals.
- Аргументы dfn называются
⍺
и⍵
и операнды dop называются⍺⍺
и⍵⍵
; аргументы и операнды tradfn могут иметь любое имя, указанное в его начальной строке. - Результат (если таковой имеется) dfn не имеет имени; результат (если таковой имеется) tradfn указан в его заголовке.
- Значение по умолчанию для ⍺ указано более аккуратно, чем для левого аргумента tradfn.
- Рекурсия в dfn осуществляется вызовом
∇
или∇∇
или его название; рекурсия в tradfn осуществляется вызовом его имени. - Управление потоком в dfn осуществляется средствами защиты и вызовами функций; что в торговле это осуществляется структурами управления и
→
(перейти) и метки линий. - Вычисление выражения в dfn, не заканчивающееся присваиванием, приводит к возврату из dfn; оценка строки в tradfn, не заканчивающейся присваиванием или переходом, отображает результат строки.
- dfn возвращается при вычислении выражения, не заканчивающегося присваиванием, при вычислении защищенного выражения или после последнего выражения; trafn возвращается
→
(перейти) к строке 0 или к несуществующей строке, или при оценке:Return
управляющую структуру или после последней строки. - Более простое управление потоком данных в dfn упрощает обнаружение и реализацию хвостовой рекурсии , чем в tradfn.
- Dfn может вызвать tradfn и наоборот ; dfn может быть определен в tradfn, и наоборот .
История
[ редактировать ]Кеннет Э. Айверсон , изобретатель APL, был недоволен способом определения пользовательских функций (tradfns). В 1974 году он разработал «формальное определение функции» или «прямое определение» для использования в изложении. [20] Прямое определение состоит из двух или четырех частей, разделенных двоеточиями:
name : expression
name : expression0 : proposition : expression1
В прямом определении ⍺
обозначает левый аргумент и ⍵
правильный аргумент. В первом случае результат expression
является результатом функции; во втором случае результатом функции является результат expression0
если proposition
оценивается как 0 или expression1
если его значение равно 1. Присвоения внутри прямого определения являются динамически локальными . Примеры использования прямого определения можно найти в на премию Тьюринга 1979 года. лекции [21] и в книгах и прикладных документах. [22] [23] [24] [25] [9]
Прямое определение было слишком ограничено для использования в более крупных системах. Идеи были развиты несколькими авторами в многочисленных работах. [26] : §8 [27] [28] : §4.17 [29] [30] [31] [32] но результаты были громоздкими. Из них «альтернативное определение функции APL» Бунда в 1987 г. [31] наиболее близок к текущим возможностям, но имеет недостатки, связанные с конфликтами с существующими символами и обработкой ошибок, что могло бы вызвать практические трудности, и так и не был реализован. Основные выводы из различных предложений заключались в том, что (а) определяемая функция является анонимной, с последующим присвоением имени (если требуется) путем присвоения; (б) функция обозначается символом и тем самым обеспечивает анонимную рекурсию . [9]
В 1996 году Джон Скоулз из Dyalog Limited изобрел прямые функции (dfns). [1] [6] [7] Идея возникла в 1989 году, когда он прочитал специальный выпуск The Computer Journal, посвященный функциональному программированию. [33] Затем он приступил к изучению функционального программирования и почувствовал сильную мотивацию («больной желанием», как Йейтс ) перенести эти идеи в APL. [6] [7] Первоначально он действовал скрытно, потому что опасался, что изменения могут быть сочтены слишком радикальными и ненужным усложнением языка; другие наблюдатели говорят, что он действовал скрытно, потому что коллеги «Диалога» не были в восторге и считали, что он зря тратит время и доставляет людям неприятности. Dfns были впервые представлены на форуме поставщиков Dyalog на конференции APL '96 и выпущены в Dyalog APL в начале 1997 года. [1] Принятие и признание пришли медленно. Еще в 2008 году в «Диалоге» в 25 лет [34] в публикации, посвященной 25-летию Dyalog Limited, dfns почти не упоминались (упоминались дважды как «динамические функции» и без подробностей). По состоянию на 2019 год [update], dfns реализованы в Dyalog APL, [19] НАРС2000, [35] и нгн/апл. [36] Они также играют ключевую роль в использовании вычислительных возможностей графического процессора (GPU). [37] [9]
Ссылки
[ редактировать ]- ^ Перейти обратно: а б с Скоулз, Джон (октябрь 1996 г.). «Прямые функции в Dyalog APL» (PDF) . Вектор . 13 (2) . Проверено 16 сентября 2019 г.
- ^ Скоулз, Джон (1998–2019), Справочная карта по прямым функциям , получено 26 сентября 2019 г. [ постоянная мертвая ссылка ]
- ^ Скоулз, Джон (апрель 2001 г.). «D: Функциональное подмножество Dyalog APL» . Вектор . 17 (4) . Проверено 21 сентября 2019 г.
- ^ Скоулз, Джон (13 сентября 2009 г.). Введение в D-функции: 1 из 2 (видео). Конференция пользователей Dialog '09 . Проверено 21 сентября 2019 г.
- ^ Скоулз, Джон (13 сентября 2009 г.). Введение в D-функции: 2 из 2 (видео). Конференция пользователей Dialog '09 . Проверено 21 сентября 2019 г.
- ^ Перейти обратно: а б с Скоулз, Джон (31 октября 2018 г.). Dfns — прошлое, настоящее и будущее (видео). Встреча пользователей Dialog '18 . Проверено 21 сентября 2019 г.
- ^ Перейти обратно: а б с Скоулз, Джон (31 октября 2018 г.), Dfns — Past, Present and Future (текст) (PDF) , Встреча пользователей Dyalog '18 , получено 21 сентября 2019 г.
- ^ Скоулз, Джон (1998–2019), Рабочая область прямых функций , получено 15 сентября 2019 г.
- ^ Перейти обратно: а б с д и ж Хуэй, Роджер; Кромберг, Мортен (июнь 2020 г.). «АПЛ с 1978 года» . Труды ACM по языкам программирования . 4 (ХОПЛ): 1–108. дои : 10.1145/3386319 . S2CID 218517570 .
- ^ Перейти обратно: а б с д Хуэй, Роджер (27 ноября 2016 г.), История APL в 50 функциях , получено 17 сентября 2019 г.
- ^ Перейти обратно: а б Хуэй, Роджер (18 июля 2016 г.), APL учения , дата обращения 24 сентября 2019 г.
- ^ Вайсштейн, Эрик В., Число Бертельсена , MathWorld, веб-ресурс Wolfram , получено 26 сентября 2019 г.
- ^ Скоулз, Джон (1998–2019), «Факториал» , DFNS Workspace , получено 20 сентября 2019 г.
- ^ Скоулз, Джон (1998–2019), «Определитель» , DFNS Workspace , получено 20 сентября 2019 г.
- ^ Вайсштейн, Эрик В., Функция распределения P, уравнение 11 , MathWorld, Веб-ресурс Wolfram , получено 3 октября 2019 г.
- ^ Харди, GH; Рамануджан, С. (1918), «Асимптотические формулы в комбинаторном анализе» (PDF) , Труды Лондонского математического общества , 17 (2) , получено 24 декабря 2019 г.
- ^ Где, АВ ; Хопкрофт, JE ; Уллман, JD (1974), Разработка и анализ компьютерных алгоритмов , Аддисон-Уэсли
- ^ Бентли, Джон (август 1983 г.). «Жемчужины программирования». Коммуникации АКМ . 26 (8 и 9).
- ^ Перейти обратно: а б с Диалог (15 августа 2019 г.). Справочное руководство по программированию Dyalog, версия 17.1, Dfns & Dops, стр. 133–147 (PDF) . ООО "Диалог" . Проверено 30 сентября 2019 г.
- ^ Айверсон, Кеннет Э. (1974), «Глава 10, Определение формальной функции» , Элементарные функции , IBM Corporation , получено 18 сентября 2019 г.
- ^ Айверсон, Кеннет Э. (август 1980 г.). «Нотация как инструмент мышления» . Коммуникации АКМ . 23 (8): 444–465. дои : 10.1145/358896.358899 . Проверено 8 апреля 2016 г.
- ^ Айверсон, Кеннет Э. (1976). Элементарный анализ . АПЛ Пресс.
- ^ Орт, Д.Л. (1976). Исчисление в новом ключе . АПЛ Пресс.
- ^ Хуэй, Роджер (май 1987 г.). «Некоторые варианты использования { и }» . Материалы конференции APL 87 . Проверено 15 апреля 2016 г.
- ^ Макдоннелл, Э.Э. (май 1987 г.), «Жизнь: отвратительная, жестокая и короткая» , Материалы конференции APL 87 , получено 6 октября 2019 г. [ постоянная мертвая ссылка ]
- ^ Айверсон, Кеннет Э. (26 апреля 1978 г.), «Операторы и функции» , номер отчета об исследовании № RC7091 , IBM Corporation , получено 19 сентября 2019 г.
- ^ Айверсон, Кеннет Э .; Вустер, Питер (сентябрь 1981 г.). «Оператор определения функции». Материалы конференции APL81, APL Quote Quad . 12 (1).
- ^ Чейни, Карл М. (март 1981 г.), Справочное руководство по системе вложенных массивов APL * Plus (PDF) , STSC, Inc. , получено 18 сентября 2019 г.
- ^ Айверсон, Кеннет Э. (6 января 1983 г.), Rationalized APL , IP Sharp Associates , получено 19 сентября 2019 г.
- ^ Айверсон, Кеннет Э. (сентябрь 1987 г.). «Словарь АПЛ» . APL Котировка Quad . 18 (1): 5–40. дои : 10.1145/36983.36984 . S2CID 18301178 . Проверено 19 сентября 2019 г.
- ^ Перейти обратно: а б Бунда, Джон (май 1987 г.). «Обозначение определения функции APL». Материалы конференции APL87, APL Quote Quad . 17 (4).
- ^ Хуэй, Роджер ; и др. (июль 1990 г.). "АПЛ\?" . Материалы конференции APL 90: За будущее . Том. 20. стр. 192–200. дои : 10.1145/97808.97845 . ISBN 089791371X . S2CID 235453656 . Проверено 10 сентября 2019 г.
- ^ Уодлер, Филип Л.; и др. (1 января 1989 г.). «Специальный выпуск по функциональному программированию». Компьютерный журнал . 32 (2).
- ^ Диалог (сентябрь 2008 г.). «Диалог в 25» (PDF) . Вектор . Проверено 20 сентября 2019 г.
- ^ Смит, Боб (2006–2019), NARS2000 , получено 18 сентября 2019 г.
- ^ Николов, Ник (сентябрь 2013 г.). «Компиляция APL в JavaScript» . Вектор . 26 (1) . Проверено 19 сентября 2019 г.
- ^ Сюй, Аарон (2019). Параллельный компилятор данных, размещенный на графическом процессоре (PDF) (кандидатская диссертация). Университет Индианы . Проверено 25 декабря 2019 г.
Внешние ссылки
[ редактировать ]- Официальный сайт , Диалог