Funkcja bezpośrednia

Funkcja bezpośrednia ( dfn , wymawiana jako „dee fun”) to alternatywny sposób definiowania funkcji i operatora ( funkcja wyższego rzędu ) w języku programowania APL . Bezpośredni operator można również nazwać dopem (wymawiane „dee op”). Zostały wynalezione przez Johna Scholesa w 1996 roku. Stanowią unikalną kombinację programowania tablicowego , funkcji wyższego rzędu i programowania funkcjonalnego i są głównym wyróżnikiem APL z początku XXI wieku w porównaniu z poprzednimi wersjami.

dfn to sekwencja potencjalnie strzeżonych wyrażeń (lub tylko strażnika) między { i } , oddzielonych lub nowymi wierszami, gdzie oznacza lewy argument i prawy, a oznacza rekurencję (odniesienie funkcji do siebie). Na przykład funkcja PT sprawdza, czy każdy wiersz jest trójką Pitagorasa (sprawdzając, czy suma kwadratów jest równa dwukrotności kwadratu maksimum).

    
      

   
     
    
   
   
   
   
    
 0  0 0  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  1  1 

Silnia jako dfn :

    0   
    

        
          fakt  {  =  ⍵:  1  ×  -  1  }  fakt  5  120  fakt  ¨  10  ⍝ fakt zastosowany do każdego elementu od 0 do 9  1  1  2  6  24  120  720  5040  40320  362880 

Opis

Zasady dla dfns są podsumowane przez następującą „kartę referencyjną”:

{ funkcja } { ⍺⍺ operator ⍵⍵ } : strażnik
lewy argument ⍺⍺ lewy operand :: ochrona przed błędami
właściwy argument ⍵⍵ prawy operand domyślny lewy argument
samoodniesienie ∇∇ samoodniesienie s nieśmiały wynik

dfn to sekwencja potencjalnie strzeżonych wyrażeń (lub tylko strażnika) między { i } , oddzielonych lub znakami nowej linii.


 
 strażnik  ekspresji  :  strażnik  ekspresji  : 

Wyrażenia i/lub osłony są oceniane po kolei. Strażnik musi ocenić na 0 lub 1; skojarzone z nim wyrażenie jest oceniane, jeśli wartość wynosi 1. Funkcja dfn kończy się po pierwszym niestrzeżonym wyrażeniu, które nie kończy się na przypisaniu , lub po pierwszym strzeżonym wyrażeniu, którego wartość straży wynosi 1, lub jeśli nie ma więcej wyrażeń. Wynik dfn jest wynikiem ostatniego ocenianego wyrażenia. Jeśli to ostatnie oceniane wyrażenie kończy się przypisaniem, wynikiem jest „nieśmiałość” — nie jest on automatycznie wyświetlany w sesji.

Nazwy przypisane w dfn są domyślnie lokalne , z zakresem leksykalnym .

oznacza lewy argument funkcji, a prawy; ⍺⍺ oznacza lewy operand, a ⍵⍵ prawy. Jeżeli ⍵⍵ , to dfn jest operatorem diadicznym ; jeśli występuje tylko ⍺⍺ , ale nie ⍵⍵ , to jest to operator monadyczny; jeśli nie ⍺⍺ , ani ⍵⍵ , to dfn jest funkcją.

Specjalna składnia wyrażenia jest używana do nadania wartości domyślnej lewemu argumentowi, jeśli dfn jest wywoływana monadycznie, to znaczy wywoływana bez lewego argumentu. . Wyrażenie ⍺ nie jest oceniane inaczej

oznacza rekurencję lub samoodniesienie przez funkcję, a ∇∇ oznacza samoodniesienie przez operatora. Takie oznaczenie pozwala na anonimową rekurencję .

Wychwytywanie błędów jest zapewniane przez strażników błędów, errnums :: expression . Gdy generowany jest błąd, system dynamicznie przeszukuje wywoływane funkcje w poszukiwaniu zabezpieczenia przed błędami, które pasuje do błędu. Jeśli zostanie znaleziony, środowisko wykonawcze jest przywracane do stanu bezpośrednio przed wykonaniem funkcji ochrony przed błędami, a powiązane wyrażenie ochrony przed błędami jest oceniane jako wynik dfn.

Dodatkowe opisy, wyjaśnienia i samouczki dotyczące dfns są dostępne w cytowanych artykułach.

Przykłady

Przykłady tutaj ilustrują różne aspekty dfns. Dodatkowe przykłady można znaleźć w cytowanych artykułach.

Domyślny lewy argument

Funkcja { + 0j1 × } dodaje do 0j1 ( ja lub ) razy .

     

    
    
    
     0    
         
          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  0J1  0J2  1J ¯2  1J¯1  1  1J1  1J2  2J¯2  2J¯1  2  2J1  2J2 

Znaczenie tej funkcji można zobaczyć w następujący sposób:

Liczby zespolone można konstruować jako uporządkowane pary liczb rzeczywistych, podobnie jak liczby całkowite można konstruować jako uporządkowane pary liczb naturalnych, a liczby wymierne jako uporządkowane pary liczb całkowitych. Dla liczb zespolonych { + 0j1 × } pełni taką samą rolę jak - dla liczb całkowitych i ÷ dla liczb wymiernych.

Ponadto, analogicznie do monadycznej - 0 - ( negate ) i monadycznej ÷ 1 ÷ ( reciprocal ), przydatna jest monadyczna definicja funkcji, realizowana poprzez podanie domyślnej wartości 0 dla : if 0 j { + 0j1 × } , potem j 0 jot 0 + 0j1 × .

   0  

       
  

      
  

    
    
           

    0  0
          j  {  +  0j1  ×  }  3  jot  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  sałata  2  Eulera  {  (  *  j  )  ​​=  (  sałata  )  j  (  grzech  )  }  Eulera  (  ¯ 0,5  +?  10  )  j  (  ¯ 0,5  +?  10  )  1  1  1  1  1  1  1  1  1  1 

Ostatnie wyrażenie ilustruje wzór Eulera na dziesięciu liczbach losowych z częściami rzeczywistymi i urojonymi w przedziale .

Pojedyncza rekurencja

Trójskładnikowa konstrukcja zbioru Cantora zaczyna się od przedziału [0,1] i na każdym etapie usuwa środkową tercję z każdego pozostałego podprzedziału:

Zbiór Cantora rzędu określony jako dfn:

    0   0    

    0

    
 0 
    
 0  0 0 0  0 
    
 0  0 0 0  0  0 0 0 0 0 0 0 0 0  0  0 0 0  0  Kantor  {  =  ⍵:  ,  1  ,  1  1  ∘.  -  1  }  Kantor  1  Kantor  1  1  1  Kantor  2  1  1  1  1  Kantor  3  1  1  1  1  1  1  1  1 

Cantor 0 do Cantor 6 przedstawiony jako czarne paski:

Cantor set in seven iterations.svg

Funkcja sito oblicza wektor bitowy o długości tak, że bit i (dla 0 i oraz i < ) wynosi 1 wtedy i tylko wtedy, gdy i jest liczbą pierwszą .


  0 0  
  
               
  
   0     
    0   


       
0 0   0  0  0 0
0  0  0 0 0  0 
0 0 0  0 0 0 0 0 
0  0 0 0 0 0  0 0
0  0  0 0 0  0 0
0 0 0  0 0 0 0 0 
0  0 0 0 0 0  0 0
0  0  0 0 0 0 0 
0 0 0  0 0 0 0 0 
0 0 0 0 0 0 0  0 0

    
   

    0  
0          sito  {  4  ⍵:⍵  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  @  1  {  (  m  )  >  m  1  m  n  ×≢  }  1  ,  p  {  r  <  q  b  1  :  b  b  [  ]  1  b  [  q  ,  q  ×⍸  b  n  ÷  q  ]  ,  q  }  p  }  10  10  sito  100  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  b  sito  1e9  b  1000000000  (  10  *⍳  10  )  (  +  )  1  b  4  25  168  1229  9592  78498  664579  5761455  5084 7534 

Ostatnia sekwencja, liczba liczb pierwszych mniejsza niż potęga 10, jest początkowym segmentem OEIS : A006880 . Ostatnia liczba, 50847534, to liczba liczb pierwszych mniejsza niż . Nazywa się to liczbą Bertelsena, pamiętnie opisaną przez MathWorld jako „błędna nazwa, której błędnie podano błędną wartość ".

sito używa dwóch różnych metod do oznaczania kompozytów zerami, obie realizowane przy użyciu lokalnych anonimowych dfns: Pierwsza wykorzystuje sito Eratostenesa na początkowej masce 1 i przedrostek liczb pierwszych 2 3...43, używając operatora wstawiania ( prawe zagięcie ). (Długość przedrostka uzyskuje się przez porównanie z pierwotną funkcją × p .) Drugi znajduje najmniejszą nową liczbę pierwszą q pozostałą w b ( q b 1 ) i ustawia na 0 sam bit q i bity w q razy liczby na pozostałych 1 bitach w początkowym segmencie b ( b n ÷ q ). Ten drugi dfn używa rekurencji ogona.

Rekurencja ogona

Zazwyczaj funkcja silni jest definiowana rekurencyjnie (jak powyżej ), ale można ją zakodować tak, aby wykorzystywała rekurencję ogona , używając lewego argumentu akumulatora:

  0     fac  {  1  =  : ⍺  (  ×  )  -  1  } 

Podobnie wyznacznik kwadratowej macierzy zespolonej za pomocą eliminacji Gaussa można obliczyć za pomocą rekurencji ogonowej:

                
                  
  0             
      
  
        
 det  {  ⍝ wyznacznik kwadratowej macierzy zespolonej  1  ⍝ iloczyn dotychczasowych współczynników kofaktorów  =≢  ⍵:⍺  ⍝ wynik dla 0 na 0  (  i  j  )  (  )  ⊤⊃⍒|,  ⍝ indeks wiersza i kolumny elementu maksymalnego  k  ⍳≢  (  ×  [  i  ;  j  ]  ×  ¯1  *  i  +  j  )  [  k  ~  i  ;  k  ~  jot  ]  -  [  k  ~  ja  ;  j  ]  ∘.  ×  [  ja  ;  k  ~  jot  ]  ÷  [  ja  ;  j  ]  } 

Wielokrotna rekurencja

Podział nieujemnej liczby = + v wektorem dodatnich całkowitych takich, że n gdzie kolejność w jest znacząca Na przykład 2 2 i 2 1 1 to partycje 4, a 2 1 1 i 1 2 1 i 1 1 2 są uważane za tę samą partycję.

Funkcja partycji zlicza liczbę partycji. Funkcja jest przedmiotem zainteresowania teorii liczb , badanej przez Eulera , Hardy'ego , Ramanujana , Erdősa i innych. Relacja powtarzalności

twierdzenia o liczbach pięciokątnych Eulera . Zapisane jako dfn:

      0   
             

    

        
             pn  {  1  ⍵:  -  +  ¨  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 

Krok bazowy 0 1 ⍵: stwierdza, że ​​dla 1 wynikiem funkcji jest 0 , 1 jeśli ⍵ wynosi 0 lub 1 i 0 w przeciwnym razie. Krok rekurencyjny jest wysoce wielokrotnie rekurencyjny. Na przykład pn 200 spowodowałoby zastosowanie funkcji do każdego elementu rec 200 , którym są:

    
           
            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 

a pn 200 wymaga niż wszechświata do obliczenia ( funkcji do siebie) Czas obliczeń można skrócić przez zapamiętywanie , tutaj zaimplementowane jako operator bezpośredni (funkcja wyższego rzędu) M :


  
   
  


     

   0      
  M  {  fa  ⍺⍺  ja  2  +  '⋄'  t  2  ↓,  ⎕cr  'f'  '{T←(1+⍵)⍴¯1 ⋄'  ,  (  ja  t  )  ,  '¯ 1≢T[⍵]:⊃T[⍵] ⋄ ⊃T[⍵]←⊂'  ,  (  i  t  )  ,  '⍵}⍵'  }  pn  M  200  3.973E12  pn  M  200  ⍝ sformatuj do 0 miejsc po przecinku  3972999029388 

Ta wartość pn M 200 zgadza się z wartością obliczoną przez Hardy'ego i Ramanujana w 1918 roku.

Operator memo M definiuje wariant swojego argumentu funkcji ⍺⍺ , aby użyć pamięci podręcznej T , a następnie ocenia go. Z operandem pn wariant to:

  0      {  T  (  1  +  )  ¯1  {  1  ⍵:  ¯1  T  [  ]  :  T  [  ]  T  [  ]  ⊂-  +  ¨  rec  }  } 

Bezpośredni operator (dop)

Szybkie sortowanie na tablicy działa na zasadzie losowego wybierania „oś obrotu” spośród jej głównych komórek, a następnie łączenia posortowanych komórek głównych, które ściśle poprzedzają oś obrotu, głównych komórek równych osi obrotu i posortowanych komórek głównych, które ściśle podążają za osią obrotu, jak określono za pomocą funkcji porównania ⍺⍺ . Zdefiniowany jako operator bezpośredni (dop) Q :

      00 0  

   
                                    
                                        0

              0   

     
0              Q  {  1  ≥≢  ⍵:⍵  (  ⌿⍨  >  s  )  (  ⌿⍨  =  s  )  ⌿⍨  <  s  ⍺⍺  ?≢  }  ⍝ poprzedza ⍝ następuje ⍝ równa się  2  (  ×-  )  8  8  (  ×-  )  2  8  (  ×-  )  8  ¯1  1  x  2  19  3  8  3  6  9  4  19  7  10  15  14  (  ×-  )  Q  x  2  3  3  4  6  7  8  9  10  14  15  19  19 

Q3 jest wariantem, który łączy trzy części objęte funkcją zamiast części per se . Trzy części generowane w każdym kroku rekurencyjnym są widoczne w strukturze wyniku końcowego. Wielokrotne zastosowanie funkcji wyprowadzonej z Q3 do tego samego argumentu daje różne wyniki, ponieważ punkty obrotu są wybierane losowo. Przechodzenie wyników w kolejności daje tę samą posortowaną tablicę.

      00 0  

     

 
     
       
0           
             
               
                           
                    
     

     


0  
       
          
           
           
     
                                 
                                
                               
                              
 Q3  {  1  ≥≢  ⍵:⍵  (  ⌿⍨  >  s  )  (  ⌿⍨  =  s  )  ⍪⊂  ⌿⍨  <  s  ⍺⍺  ?≢  }  (  ×-  )  Q3  x  ┌───────────────────────────────────── ───────┬─ ────┬┐  │┌──────────────┬─┬─────────────── ────────── ┐│  19  19  ││  ││┌──────┬───┬─┐│  6  │┌──────┬─┬──── ──────────┐ ││  ││  │││┌┬─┬─┐│  3  3  4  ││  ││┌┬─┬─┐│  9  │┌┬──┬─── ─────┐│││  ││  │││││  2  ││  ││  ││││  7  8  ││  │││  10  │┌──┬──┬┐││││  ││  │││└┴─┴─┘│  ││  ││└┴─┴─┘│  │││  ││  14  15  ││││││  ││  ││└────── ┴───┴─┘│  ││  ││ │  │└──┴──┴┘││││  ││  ││  ││  │└┴──┴────────┘│  ││  ││ ││  │└─── ───┴─┴──────────────┘││  ││  │└──────────── ──┴─┴────── ───────────────────┘│  ││  └─────────────── ─────────── ──────────────────┴─────┴┘  (  ×-  )  Q3  x  ┌────────── ─────── ──────────┬─┬───────────────────────────  ──┐ │┌┬─┬── ────────────────────┐│  7  │┌─────────────── ─────┬──── ─┬┐│  │││  │┌┬─┬─────────────────┐││  ││┌──── ──┬──┬───── ───┐│  19  19  │││  │││  │││  2  │┌────────────┬─┬┐│││  │ ││┌┬─┬─┐│  10  │ ┌──┬──┬┐││  │││  │││  │││  ││┌───────┬─┬┐│  6  ││││  │ │││││  8  9  ││  ││  14  15  ││││  │││  │││  │││  │││┌┬───┬┐│  4  │││  │││││  │││└┴─┴─┘│  │└ ──┴──┴┘││  │││  │││  │││  │││││  3  3  │││  │││  │││││  ││ └──────┴──┴─ ───────┘│  │││  │││  │││  │││└┴───┴┘│  │││  │││││  │ └─────────── ─────────┴─────┴┘│  │││  │││  ││└───────┴─┴┘│  │││││  │││  │ ││  │└────────────┴─┴┘│││  │││  │└┴─┴───── ──────────── ┘││  │└┴─┴──────────────────────┘│  └─ ──────────── ──────────────┴─┴─────────────────────── ──────┘ 

Powyższe sformułowanie nie jest nowe; patrz na przykład rysunek 3.7 klasycznej książki The Design and Analysis of Computer Algorithms . Jednak w przeciwieństwie do pidgin ALGOL z rysunku 3.7, Q jest wykonywalny, a kolejność częściowa używana w sortowaniu jest operandem, ( ×- ) w powyższych przykładach.

Dfns z operatorami i pociągami

Dfns, zwłaszcza anonimowe dfns, dobrze współpracują z operatorami i pociągami. Poniższy fragment rozwiązuje zagadkę „Pereł programowania”: biorąc pod uwagę słownik angielskich słów, tutaj przedstawiony jako macierz znaków a , znajdź wszystkie zestawy anagramów.

                           
                         
                         
                             
                             
                             
                                 
                                 
                                 
                                 
                         
         
         
          za  {  [  ]  }  1  za  (  {  [  ]  }  1  {  }  )  a  poklepuje  ┌────┬────┬──  ──┐  splunął  apst  klepie  herbaty  gwiazda  herbaty  aest  splunąć  nasycić  nasycić  aest  taps  etas  taps  apst  przeszłość  siedzenie  etas  aest  zjada  przeszłość  apst  tase  siedzenie  aest  wschód  zjada  aest  seta  tase  aest  └────┴────┴────┘  star  arst  wschód  aest  seta  aest 

Algorytm działa na zasadzie sortowania wierszy indywidualnie ( { [ ] } 1 a ), a te posortowane wiersze są używane jako klucze („podpis” w opisie Pereł Programowania) do głównego operatora do grupowania wierszy macierz. Wyrażenie po prawej stronie to pociąg , forma składniowa stosowana przez APL do programowania cichego . Tutaj jest to izolowana sekwencja trzech funkcji taka, że ​​( f g h ) ( f ) g ( h ) , skąd wyrażenie po prawej stronie jest równoważne ( { [ ] } 1 a ) { } za .

Zakres leksykalny

Kiedy wewnętrzny (zagnieżdżony) dfn odnosi się do nazwy, szuka się go, patrząc na zewnątrz przez otaczające dfns, a nie w dół stosu wywołań . Mówi się, że ten system wykorzystuje zakres leksykalny zamiast zwykłego zakresu dynamicznego APL . Rozróżnienie staje się widoczne dopiero wtedy, gdy wywołana zostanie funkcja zdefiniowana na poziomie zewnętrznym. W przypadku bardziej typowych wezwań przychodzących te dwa systemy są nie do odróżnienia.

Na przykład w następującej funkcji who zmienna ty jest zdefiniowana zarówno w samej what , jak iw funkcji wewnętrznej f1 . Kiedy f1 wywołuje na zewnątrz f2 i f2 odnosi się do ty , znajduje zewnętrzny (o wartości 'lexical' ) zamiast tego zdefiniowanego w f1 (o wartości 'dynamic' ):


  
     
  
   


    
 który  {  ty  'leksykalny'  f1  {  ty  'dynamiczny'  f2  }  f2  {  ty  ,  }  f1  }  który  'zakres'  zakres  leksykalny  

Ochrona przed błędami

Poniższa funkcja ilustruje użycie strażników błędów:


     0
       
        
  
      
                   

          

           

               
  plus  {  tx  „złapać wszystko”  ::  tx  tx  „dziedzina”  11  ::  tx  tx  „długość”  5  ::  tx  +  }  2  plus  3  ⍝ brak błędów  5  2  3  4  5  plus  ' trzy'  ⍝ długości argumentów nie pasują do  długości  2  3  4  5  plus  'cztery'  ⍝ nie można dodać znaków  dziedzina  2  3  plus  3  4  5  ⍝ nie można dodać wektora do macierzy  catch  all 

W APL błąd numer 5 to „błąd długości”; numer błędu 11 to „błąd domeny”; a numer błędu 0 to „catch all” dla numerów błędów od 1 do 999.

Przykład pokazuje odwijanie środowiska lokalnego przed obliczeniem wyrażenia strażnika błędów. Lokalna nazwa tx jest ustawiona tak, aby opisywać zakres następującej po niej ochrony przed błędami. Gdy wystąpi błąd, środowisko jest rozwijane, aby odsłonić poprawną statycznie wartość tx .

Dfns kontra tradfns

Ponieważ funkcje bezpośrednie to dfns, funkcje APL zdefiniowane w tradycyjny sposób są określane jako tradfns, wymawiane jako „trad funs”. Tutaj dfns i tradfns są porównywane przez uwzględnienie funkcji sito : Po lewej stronie jest dfn (jak zdefiniowano powyżej ); pośrodku znajduje się tradfn używający struktur kontrolnych ; po prawej jest tradfn używający gotos ( ) i etykiet linii .


  0 0  
  
               
  
   0     
    0   
 sito  {  4  ⍵:⍵  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  @  1  {  (  m  )  >  m  1  m  n  ×≢  }  1  ,  p  {  r  <  q  b  1  :  b  b  [  ]  1  b  [  q  ,  q  × ⍸  b  n  ÷  q  ]  ,  q  }  p  } 
  
     0 0      
  
               
  
  
           
  0
     0    
  
 b  sito1  n  ;  ja  ;  m  ;  p  ;  q  ;  r  :  Jeśli  4  n  b  n  1  1  :  Powrót  :  Koniec Jeśli  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  :  Dla  q  :  In  p  b  (  m  b  )  >  m  q  1  m  n  q  ×≢  b  :  EndFor  b  [  1  ]  :  Podczas gdy  r  q  b  1  b  [  q  ,  q  × ⍸  b  n  ÷  q  ]  p  q  :  EndWhile  b  [  p  ]  1 
  
      0 0    0
 
  
               
  
  0  
 
    
    
  0
 
      0    
 
  
 b  sito2  n  ;  ja  ;  m  ;  p  ;  q  ;  r  L10  4  <  n  b  n  1  1  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  ja  b  1  L20  :  b  (  m  b  )  >  m  p  [  ja  ]  1  m  n  p  [  ja  ]  ×≢  b  L20  (  p  )  >  ja  1  +  ja  b  [  1  ]  L30  :  L40  r  <  q  b  1  b  [  q  ,  q  × ⍸  b  n  ÷  q  ]  p  q  L30  L40  :  b  [  p  ]  1 
  • Dfn może być anonimowy ; tradfn musi mieć nazwę.
  • dfn jest nazywany przez przypisanie ( ); tradfn jest nazywany przez osadzenie nazwy w reprezentacji funkcji i zastosowanie ⎕fx (funkcja systemowa) do tej reprezentacji.
  • dfn jest wygodniejszy niż tradfn jako operand (patrz poprzednie punkty: tradfn musi mieć nazwę; tradfn jest nazywany przez osadzanie ...).
  • Nazwy przypisane w dfn są domyślnie lokalne ; nazwy przypisane w tradfn są globalne , chyba że określono je na liście locals.
  • Lokalne w dfn mają zakres leksykalny ; locals w tradfn mają dynamiczny zasięg , widoczny w wywoływanych funkcjach, chyba że jest to cień ich listy locals.
  • Argumenty dfn są nazwane i , a operandy dop są nazwane ⍺⍺ i ⍵⍵ ; argumenty i operandy tradfn mogą mieć dowolną nazwę, określoną w jej wiodącym wierszu.
  • Wynik (jeśli istnieje) dfn jest nienazwany; wynik (jeśli istnieje) tradfn jest nazwany w jego nagłówku.
  • Wartość domyślna dla ⍺ jest określona dokładniej niż dla lewego argumentu tradfn.
  • Rekurencja w dfn odbywa się poprzez wywołanie lub ∇∇ lub jego nazwy; rekurencja w tradfn odbywa się poprzez wywołanie jego nazwy.
  • Kontrola przepływu w dfn jest realizowana przez strażników i wywołania funkcji; to w tradfn jest przez struktury kontrolne i (goto) i etykiety linii.
  • Ocena wyrażenia w dfn, które nie kończy się przypisaniem, powoduje powrót z dfn; ocena linii w tradfn nie kończącej się przypisaniem lub goto wyświetla wynik linii.
  • Funkcja dfn zwraca przy ocenie wyrażenia, które nie kończy się przypisaniem, przy ocenie wyrażenia chronionego lub po ostatnim wyrażeniu; tradfn powraca w (goto) 0 lub w nieistniejącej linii, lub po ocenie struktury kontrolnej : Return lub po ostatniej linii.
  • Prostsza kontrola przepływu w dfn ułatwia wykrywanie i wdrażanie rekurencji ogona niż w tradfn.
  • dfn może wywoływać tradfn i vice versa ; dfn może być zdefiniowany w tradfn i vice versa .

Historia

Kenneth E. Iverson , wynalazca APL, był niezadowolony ze sposobu definiowania funkcji użytkownika (tradfns). W 1974 roku opracował „formalną definicję funkcji” lub „definicję bezpośrednią” do wykorzystania w ekspozycji. Definicja bezpośrednia składa się z dwóch lub czterech części oddzielonych dwukropkami:

  
       nazwa  :  nazwa  wyrażenia  :  wyrażenie0  :  propozycja  :  wyrażenie1 

W bezpośredniej definicji oznacza lewy argument, a prawy argument. W pierwszym przypadku wynik wyrażenia jest wynikiem funkcji; w drugim przypadku wynikiem funkcji jest wyrażenie0 , jeśli zdanie ma wartość 0, lub wyrażenie1 , jeśli ma wartość 1. Przypisania w ramach definicji bezpośredniej są dynamicznie lokalne . Przykłady użycia bezpośredniej definicji można znaleźć w Turing Award z 1979 r . oraz w książkach i dokumentach aplikacyjnych.

Definicja bezpośrednia była zbyt ograniczona do użytku w większych systemach. Pomysły były dalej rozwijane przez wielu autorów w wielu pracach, ale wyniki były nieporęczne. Spośród nich „alternatywna definicja funkcji APL” Bundy z 1987 r. Była najbliższa obecnym obiektom, ale zawiera błędy w konfliktach z istniejącymi symbolami i obsługą błędów, które spowodowałyby praktyczne trudności, i nigdy nie została wdrożona. Główne destylaty z różnych propozycji były takie, że (a) definiowana funkcja jest anonimowa, a późniejsze nazewnictwo (jeśli jest wymagane) jest dokonywane przez przypisanie; (b) funkcja jest oznaczona symbolem, a tym samym umożliwia anonimową rekurencję .

W 1996 roku John Scholes z Dyalog Limited wynalazł funkcje bezpośrednie (dfns). Pomysły zrodziły się w 1989 roku, kiedy przeczytał specjalne wydanie The Computer Journal na temat programowania funkcjonalnego. Następnie zaczął studiować programowanie funkcjonalne i był silnie zmotywowany („chory z pragnienia”, jak Yeats ), aby wprowadzić te pomysły do ​​APL. Początkowo działał ukradkiem, ponieważ obawiał się, że zmiany mogą zostać uznane za zbyt radykalne i niepotrzebne skomplikowanie języka; inni obserwatorzy twierdzą, że działał ukradkiem, ponieważ koledzy Dyalog nie byli tak zachwyceni i myśleli, że marnuje czas i sprawia ludziom kłopoty. Dfns zostały po raz pierwszy zaprezentowane na Dyalog Vendor Forum na konferencji APL '96 i wydane w Dyalog APL na początku 1997 roku. Akceptacja i uznanie nadchodziły powoli. Jeszcze w 2008 roku, w Dyalog w 25 , publikacji z okazji 25-lecia Dyalog Limited, prawie nie wspomniano o dfns (wspomniano dwukrotnie jako „funkcje dynamiczne” i bez rozwinięcia). Od 2019 r. dfns są implementowane w Dyalog APL, NARS2000 i ngn/apl. Odgrywają również kluczową rolę w wysiłkach zmierzających do wykorzystania możliwości obliczeniowych procesora graficznego (GPU).

Linki zewnętrzne