Directe functie - Direct function

Een directe functie ( dfn , uitgesproken als "dee fun") is een alternatieve manier om een ​​functie en operator (een functie van hogere orde ) te definiëren in de programmeertaal APL . Een directe operator kan ook een dop worden genoemd (uitgesproken als "dee op"). Ze werden uitgevonden door John Scholes in 1996. Ze zijn een unieke combinatie van array-programmering , hogere-orde-functie en functionele programmering , en zijn een belangrijke onderscheidende vooruitgang van de vroege 21e-eeuwse APL ten opzichte van eerdere versies.

Een dfn is een reeks van mogelijk bewaakte uitdrukkingen (of alleen een bewaker) tussen {en }, gescheiden door of nieuwe regels, waarbij het linkerargument en het rechterargument worden aangegeven, en recursie (functie-zelfreferentie) aangeeft . De functie test bijvoorbeeld of elke rij van een Pythagoras triplet is (door te testen of de som van de kwadraten gelijk is aan tweemaal het kwadraat van het maximum). 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

De faculteitsfunctie als een 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

Beschrijving

De regels voor dfns worden samengevat door de volgende "referentiekaart":

{ function } {⍺⍺ operator ⍵⍵} :   bewaker
  links argument ⍺⍺  linker operand ::  foutbewaker
  juiste argument ⍵⍵  rechter operand   standaard links argument 
  zelfverwijzing   ∇∇  zelfverwijzing   s  verlegen resultaat

Een dfn is een opeenvolging van mogelijk bewaakte uitdrukkingen (of alleen een bewaker) tussen {en }, gescheiden door of nieuwe regels.

expression
guard: expression
guard:

De uitdrukkingen en/of bewakers worden in volgorde geëvalueerd. Een bewaker moet evalueren naar een 0 of 1; de bijbehorende expressie wordt geëvalueerd als de waarde 1 is. Een dfn eindigt na de eerste onbewaakte expressie die niet eindigt op toewijzing , of na de eerste bewaakte expressie waarvan de guard evalueert tot 1, of als er geen expressies meer zijn. Het resultaat van een dfn is dat van de laatst geëvalueerde uitdrukking. Als die laatst geëvalueerde uitdrukking eindigt in een toewijzing, is het resultaat 'verlegen' en wordt niet automatisch weergegeven in de sessie.

Namen die in een dfn zijn toegewezen, zijn standaard lokaal , met lexicale scope .

geeft het linker functieargument aan en het rechter; ⍺⍺geeft de linker operand en ⍵⍵de rechter aan. Als het ⍵⍵voorkomt in de definitie, dan is de dfn een dyadische operator ; als alleen ⍺⍺voorkomt maar niet ⍵⍵, dan is het een monadische operator; als geen van beide ⍺⍺of ⍵⍵voorkomt, dan is de dfn een functie.

De speciale syntaxis wordt gebruikt om een ​​standaardwaarde aan het linkerargument te geven als een dfn monadisch wordt aangeroepen, dat wil zeggen zonder linkerargument. Het wordt niet anders beoordeeld. expressionexpression

geeft recursie of zelfverwijzing door de functie aan en ∇∇geeft zelfverwijzing door de operator aan. Een dergelijke aanduiding maakt anonieme recursie mogelijk .

Error trapping wordt geleverd door middel van error-guards, . Wanneer een fout wordt gegenereerd, zoekt het systeem dynamisch door de aanroepende functies naar een foutbeveiliging die overeenkomt met de fout. Als er een wordt gevonden, wordt de uitvoeringsomgeving afgewikkeld naar de toestand onmiddellijk voorafgaand aan de uitvoering van de error-guard en wordt de bijbehorende expressie van de error-guard geëvalueerd als het resultaat van de dfn. errnums::expression

Aanvullende beschrijvingen, uitleg en tutorials over dfns zijn beschikbaar in de geciteerde artikelen.

Voorbeelden

De voorbeelden hier illustreren verschillende aspecten van dfns. Aanvullende voorbeelden zijn te vinden in de geciteerde artikelen.

Standaard links argument

De functie voegt aan ( i of -1 ) maal . {+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

De betekenis van deze functie kan als volgt worden gezien:

Complexe getallen kunnen worden geconstrueerd als geordende paren van reële getallen, vergelijkbaar met hoe gehele getallen kunnen worden geconstrueerd als geordende paren natuurlijke getallen en rationale getallen als geordende paren van gehele getallen. Voor complexe getallen speelt dezelfde rol als voor gehele getallen en voor rationale getallen.{+0j1×}-÷

Bovendien, analoog aan die monadische ⇔ ( negate ) en monadic ⇔ ( reciproke ), is een monadische definitie van de functie nuttig, bewerkstelligd door een standaardwaarde van 0 op te geven voor : if , then ⇔ ⇔ . -0-÷1÷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+?100) j (¯0.5+?100)
1 1 1 1 1 1 1 1 1 1

De laatste uitdrukking illustreert de formule van Euler op tien willekeurige getallen met reële en imaginaire delen in het interval .

Enkele recursie

De ternaire constructie van de Cantor-verzameling begint met het interval [0,1] en verwijdert in elke fase het middelste derde deel van elk overblijvend subinterval:

De Cantor- ordereeks gedefinieerd als een dfn:

   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

Cantor 0 t/m Cantor 6 weergegeven als zwarte balken:

Cantor in zeven iteraties.svg

De functie berekent een bitvector van lengte zodat bit (voor en ) 1 is als en slechts als een priemgetal is . sieve i0ii<i

sieve{
  4⍵:⍵0 0 1 1
  r0.5*n
  p2 3 5 7 11 13 17 19 23 29 31 37 41 43
  p(1+(n≤×p)1)p
  b 0@1  {(m)>m1  mn×≢} 1,p
  {r<qb1:bb[]1  b[q,q×⍸bn÷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

   bsieve 1e9
   b
1000000000
   (10*⍳10) (+)0 1 b
0 4 25 168 1229 9592 78498 664579 5761455 50847534

De laatste reeks, het aantal priemgetallen kleiner dan machten van 10, is een eerste segment van OEISA006880 . Het laatste getal, 50847534, is het aantal priemgetallen kleiner dan . Het wordt het getal van Bertelsen genoemd, memorabel beschreven door MathWorld als "een foutieve naam die ten onrechte de foutieve waarde van " heeft gekregen.

sievegebruik van twee verschillende methoden voor markering composieten met 0s, beide uitgevoerd met lokale anonieme dfns: De eerste toepassingen van de zeef van Eratosthenes van een eerste masker 1 en een prefix van de priemgetallen 2 3 ... 43, met het inzetstuk operator ( rechts vouwen ). (De lengte van het voorvoegsel wordt verkregen in vergelijking met de oerfunctie .) De tweede vindt het kleinste nieuwe priemgetal dat overblijft in ( ), en stelt zichzelf in op 0 bit en bits soms de getallen op de resterende 1 bits in een initieel segment van ( ) . Deze tweede dfn gebruikt staartrecursie. ×pqbqb1qqbbn÷q

staart recursie

Meestal wordt de faculteitsfunctie recursief gedefinieerd (zoals hierboven ), maar deze kan worden gecodeerd om staartrecursie te exploiteren door een accumulator-links argument te gebruiken:

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

Evenzo kan de determinant van een vierkante complexe matrix met behulp van Gauss-eliminatie worden berekend met staartrecursie:

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]
}

Meerdere recursie

Een partitie van een niet-negatief geheel getal is een vector van positieve gehele getallen zodat , waarbij de volgorde in niet significant is. Bijvoorbeeld, en zijn partities van 4, en en en worden beschouwd als dezelfde partitie. n = +v2 22 1 12 1 11 2 11 1 2

De partitiefunctie telt het aantal partities. De functie is van belang in de getaltheorie , bestudeerd door Euler , Hardy , Ramanujan , Erdős en anderen. De herhalingsrelatie

afgeleid van de vijfhoekige getalstelling van Euler . Geschreven als een dfn:

   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

De basisstap stelt dat voor , het resultaat van de functie is , 1 als ⍵ 0 of 1 is en anders 0. De recursieve stap is sterk vermenigvuldigd recursief. Zou er bijvoorbeeld toe leiden dat de functie wordt toegepast op elk element van , namelijk: 1⍵:010pn 200rec 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

en vereist meer dan de leeftijd van het universum om te berekenen ( functieaanroepen naar zichzelf). De rekentijd kan worden verminderd door geheugenopslag , hier geïmplementeerd als de directe operator (functie van hogere orde) : pn 200M

M{
  f⍺⍺
  i2+'⋄'t2↓,⎕cr 'f'
  '{T←(1+⍵)⍴¯1 ⋄ ',(it),'¯1≢T[⍵]:⊃T[⍵] ⋄ ⊃T[⍵]←⊂',(it),'⍵}⍵'
}

   pn M 200
3.973E12
   0  pn M 200  ⍝ format to 0 decimal places
 3972999029388

Deze waarde komt overeen met die berekend door Hardy en Ramanujan in 1918. pn M 200

De memo-operator Mdefinieert een variant van zijn operandfunctie ⍺⍺om een cache te gebruiken Ten evalueert deze vervolgens. Met de operand is pnde variant:

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

Directe operator (dop)

Quicksort op een array werkt door willekeurig een "draaipunt" te kiezen uit de belangrijkste cellen, en vervolgens de gesorteerde hoofdcellen die strikt voorafgaan aan het draaipunt, de hoofdcellen gelijk aan het draaipunt en de gesorteerde hoofdcellen die strikt het draaipunt volgen, te rangschikken, zoals bepaald door een vergelijkingsfunctie ⍺⍺. Gedefinieerd als een directe operator (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

Q3is een variant die de drie delen omvat die door de functie worden omsloten in plaats van de delen per se . De drie delen die bij elke recursieve stap worden gegenereerd, zijn duidelijk zichtbaar in de structuur van het eindresultaat. Het Q3meerdere keren toepassen van de functie die is afgeleid van hetzelfde argument geeft verschillende resultaten omdat de pivots willekeurig worden gekozen. Het op volgorde doorlopen van de resultaten levert dezelfde gesorteerde array op.

   Q3{1≥≢⍵:⍵  ( ⌿⍨0>s)(⌿⍨0=s)⍪⊂ ⌿⍨0<s ⍺⍺ ?≢}

   (×-) Q3 x
┌────────────────────────────────────────────┬─────┬┐
│┌──────────────┬─┬─────────────────────────┐│19 19││
││┌──────┬───┬─┐│6│┌──────┬─┬──────────────┐││     ││
│││┌┬─┬─┐│3 34││ ││┌┬─┬─┐│9│┌┬──┬────────┐│││     ││
│││││02││    ││ ││││78││ │││10│┌──┬──┬┐││││     ││
│││└┴─┴─┘│    ││ ││└┴─┴─┘│ │││  ││1415││││││     ││
││└──────┴───┴─┘│ ││       │││  │└──┴──┴┘││││     ││
││               ││       │└┴──┴────────┘│││     ││
││               │└──────┴─┴──────────────┘││     ││
│└──────────────┴─┴─────────────────────────┘│     ││
└────────────────────────────────────────────┴─────┴┘
   (×-) Q3 x
┌───────────────────────────┬─┬─────────────────────────────┐
│┌┬─┬──────────────────────┐│7│┌────────────────────┬─────┬┐│
│││0│┌┬─┬─────────────────┐││ ││┌──────┬──┬────────┐│19 19│││
│││ │││2│┌────────────┬─┬┐│││ │││┌┬─┬─┐│10│┌──┬──┬┐││     │││
│││ │││ ││┌───────┬─┬┐│6│││││ │││││89││  ││1415││││     │││
│││ │││ │││┌┬───┬┐│4│││ │││││ │││└┴─┴─┘│  │└──┴──┴┘││     │││
│││ │││ │││││3 3│││ │││ │││││ ││└──────┴──┴────────┘│     │││
│││ │││ │││└┴───┴┘│ │││ │││││ │└────────────────────┴─────┴┘│
│││ │││ ││└───────┴─┴┘│ │││││                              
│││ │││ │└────────────┴─┴┘│││                              
│││ │└┴─┴─────────────────┘││                              
│└┴─┴──────────────────────┘│                              
└───────────────────────────┴─┴─────────────────────────────┘

Bovenstaande formulering is niet nieuw; zie bijvoorbeeld figuur 3.7 van de klassieker The Design and Analysis of Computer Algorithms . In tegenstelling tot het pidgin- programma ALGOL in figuur 3.7, Qis het echter uitvoerbaar, en de gedeeltelijke volgorde die bij het sorteren wordt gebruikt, is een operand, zoals in de bovenstaande voorbeelden. (×-)

Dfns met operators en treinen

Dfns, vooral anonieme dfns, werken goed met operators en treinen. Het volgende fragment lost een "Programming Pearls"-puzzel op: gegeven een woordenboek met Engelse woorden, hier weergegeven als de karaktermatrix a, vind je alle sets anagrammen.

   a            {[]}1 a        ({[]}1 {} ) a
pats         apst                ┌────┬────┬────┐
spat         apst                patsteasstar
teas         aest                spatsate    
sate         aest                tapsetas    
taps         apst                pastseat    
etas         aest                    eats    
past         apst                    tase    
seat         aest                    east    
eats         aest                    seta    
tase         aest                └────┴────┴────┘
star         arst
east         aest
seta         aest

Het algoritme werkt door de rijen afzonderlijk te sorteren ( ), en deze gesorteerde rijen worden gebruikt als sleutels ("handtekening" in de programmeerparelsbeschrijving) voor de key- operator om de rijen van de matrix te groeperen. De uitdrukking aan de rechterkant is een trein , een syntactische vorm die door APL wordt gebruikt om stilzwijgende programmering te bereiken . Hier is het een geïsoleerde reeks van drie functies zodat ⇔ , vanwaar de uitdrukking aan de rechterkant gelijk is aan . {[]}1 a(f g h) (f ) g (h )({[]}1 a) {} a

Lexicale reikwijdte

Wanneer een innerlijke (geneste) dfn naar een naam verwijst, wordt deze gezocht door naar buiten te kijken door de omsluitende dfns in plaats van langs de call-stack . Dit regime zou lexicale reikwijdte gebruiken in plaats van de gebruikelijke dynamische reikwijdte van APL . Het onderscheid wordt pas duidelijk als er een aanroep wordt gedaan naar een functie die op een extern niveau is gedefinieerd. Voor de meer gebruikelijke inkomende oproepen zijn de twee regimes niet te onderscheiden.

In de volgende functie whichis de variabele tybijvoorbeeld zowel in whichzichzelf als in de innerlijke functie gedefinieerd f1. Wanneer f1naar buiten wordt aangeroepen f2en f2verwijst naar ty, wordt de buitenste (met waarde 'lexical') gevonden in plaats van degene die is gedefinieerd in f1(met waarde 'dynamic'):

which{
  ty'lexical'
  f1{ty'dynamic'  f2 }
  f2{ty,}
  f1 
}

   which ' scope'
lexical scope

Foutbewaking

De volgende functie illustreert het gebruik van foutbeveiligingen:

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 45        ⍝ can't add vector to matrix
catch all

In APL is foutnummer 5 "lengtefout"; foutnummer 11 is "domeinfout"; en foutnummer 0 is een "catch all" voor foutnummers 1 tot 999.

Het voorbeeld toont het afwikkelen van de lokale omgeving voordat de expressie van een error-guard wordt geëvalueerd. De lokale naam txis ingesteld om de reikwijdte van de volgende foutbeveiliging te beschrijven. Wanneer er een fout optreedt, wordt de omgeving afgewikkeld om txde statisch correcte waarde weer te geven.

Dfns versus tradfns

Aangezien directe functies dfns zijn, worden APL-functies die op de traditionele manier zijn gedefinieerd, tradfns genoemd, uitgesproken als "trad funs". Hier worden dfns en tradfns vergeleken door rekening te houden met de functie sieve: Aan de linkerkant is een dfn (zoals hierboven gedefinieerd ); in het midden is een tradfn die controlestructuren gebruikt ; aan de rechterkant is een tradfn met behulp van GOTO's ( ) en lijn labels .

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
∇
  • Een dfn kan anoniem zijn ; er moet een tradfn worden genoemd.
  • Een dfn wordt genoemd door toewijzing ( ); een tradfn wordt benoemd door de naam in de representatie van de functie in te bedden en ⎕fx(een systeemfunctie) op die representatie toe te passen.
  • Een dfn is handiger dan een tradfn als operand (zie voorgaande items: een tradfn moet benoemd worden; een tradfn wordt benoemd door embedding ...).
  • Namen die in een dfn zijn toegewezen , zijn standaard lokaal ; namen toegewezen in een tradfn zijn globaal, tenzij gespecificeerd in een lokale lijst.
  • Locals in een dfn hebben een lexicale scope ; locals in een tradfn hebben een dynamisch bereik , zichtbaar in aangeroepen functies, tenzij overschaduwd door hun lokale lijst.
  • De argumenten van een dfn worden genoemd en en de operanden van een dop worden genoemd ⍺⍺en ⍵⍵; de argumenten en operanden van een tradfn kunnen elke naam hebben, gespecificeerd op de leidende regel.
  • Het resultaat (indien aanwezig) van een dfn is naamloos; het resultaat (indien aanwezig) van een tradfn wordt genoemd in de kop.
  • Een standaardwaarde voor ⍺ is netter gespecificeerd dan voor het linkerargument van een tradfn.
  • Recursie in een dfn wordt bewerkstelligd door het aanroepen van of ∇∇of zijn naam; recursie in een tradfn wordt bewerkstelligd door de naam ervan aan te roepen.
  • Flow control in een dfn wordt bewerkstelligd door bewakers en functieaanroepen; dat in een tradfn is door controlestructuren en (goto) en lijnlabels .
  • Het evalueren van een uitdrukking in een dfn die niet eindigt op toewijzing, veroorzaakt terugkeer van de dfn; het evalueren van een regel in een tradfn die niet eindigt op toewijzing of goto geeft het resultaat van de regel weer.
  • Een dfn keert terug bij het evalueren van een uitdrukking die niet eindigt op een toewijzing, bij het evalueren van een bewaakte uitdrukking, of na de laatste uitdrukking; een tradfn keert terug op (goto) regel 0 of een niet-bestaande regel, of bij evaluatie van een controlestructuur, of na de laatste regel.:Return
  • De eenvoudigere stroomregeling in een dfn maakt het gemakkelijker om staartrecursie te detecteren en te implementeren dan in een tradfn.
  • Een dfn kan een tradfn aanroepen en vice versa ; een dfn kan worden gedefinieerd in een tradfn, en vice versa .

Geschiedenis

Kenneth E. Iverson , de uitvinder van APL, was ontevreden over de manier waarop gebruikersfuncties (tradfns) werden gedefinieerd. In 1974 bedacht hij "formele functiedefinitie" of "directe definitie" voor gebruik in expositie. Een directe definitie bestaat uit twee of vier delen, gescheiden door dubbele punten:

name : expression
name : expression0 : proposition : expression1

Geeft binnen een directe definitie het linkerargument en het rechterargument aan. In eerste instantie is het resultaat van expressionhet resultaat van de functie; in het tweede geval is het resultaat van de functie dat van expression0if propositionevalueert naar 0, of expression1als het evalueert naar 1. Toewijzingen binnen een directe definitie zijn dynamisch lokaal . Voorbeelden van het gebruik van directe definitie zijn te vinden in de Turing Award- lezing van 1979 en in boeken en sollicitatiebrieven.

Directe definitie was te beperkt voor gebruik in grotere systemen. De ideeën werden verder ontwikkeld door meerdere auteurs in meerdere werken, maar de resultaten waren onpraktisch. Hiervan kwam de "alternatieve APL-functiedefinitie" van Bunda in 1987 het dichtst in de buurt van de huidige faciliteiten, maar is gebrekkig in conflict met bestaande symbolen en in foutafhandeling die praktische problemen zou hebben veroorzaakt, en werd nooit geïmplementeerd. De belangrijkste distillaten van de verschillende voorstellen waren dat (a) de functie die wordt gedefinieerd anoniem is, waarbij de latere naamgeving (indien nodig) door middel van toewijzing wordt uitgevoerd; (b) de functie wordt aangeduid met een symbool en maakt daardoor anonieme recursie mogelijk .

In 1996 vond John Scholes van Dyalog Limited directe functies (dfns) uit. De ideeën ontstonden in 1989 toen hij een speciale uitgave van The Computer Journal las over functioneel programmeren. Hij ging toen verder met het bestuderen van functioneel programmeren en raakte sterk gemotiveerd ("ziek van verlangen", zoals Yeats ) om deze ideeën naar APL te brengen. Aanvankelijk opereerde hij onopvallend omdat hij bang was dat de veranderingen te radicaal en een onnodige complicatie van de taal zouden zijn; andere waarnemers zeggen dat hij heimelijk opereerde omdat Dyalog-collega's niet zo gecharmeerd waren en dachten dat hij zijn tijd aan het verspillen was en problemen voor mensen veroorzaakte. Dfns werden voor het eerst gepresenteerd in het Dyalog Vendor Forum op de APL '96 Conference en begin 1997 uitgebracht in Dyalog APL. Acceptatie en erkenning kwamen langzaam op gang. Nog in 2008, in Dyalog op 25 , een publicatie ter gelegenheid van het 25-jarig jubileum van Dyalog Limited, werden dfns nauwelijks genoemd (twee keer genoemd als "dynamische functies" en zonder uitwerking). Vanaf 2019 zijn dfns geïmplementeerd in Dyalog APL, NARS2000 en ngn/apl. Ze spelen ook een sleutelrol bij pogingen om de computercapaciteiten van een grafische verwerkingseenheid (GPU) te benutten .

Referenties

Externe links