2013-04-01 16 views
7

Czy istnieje jakiś symbol lub dobrze znany idiom dla funkcji warunkowej, w dowolnym z dialektów APL?Funkcja warunkowa w APL

Jestem pewien, że czegoś mi brakuje, ponieważ jest to taki podstawowy element językowy. W innych językach jest to nazywane Operator warunkowy, ale uniknę tego tutaj, ponieważ operator APL jest czymś zupełnie innym.

na przykład C i przyjaciele mają x ? T : F
LISPs mieć (if x T F)
Python ma T if x else F
i tak dalej.

Wiem, że nowoczesne APL-y mają :If i przyjaciół, ale są bezwzględnymi instrukcjami kontrolującymi przepływ programu: nie zwracają wartości, nie mogą być używane wewnątrz wyrażenia iz pewnością nie mogą być stosowane do tablic bajtów. Mają zupełnie inny cel, co jest w porządku.

Jedyny przyzwoity wyrażenie mogłem wymyślić zrobić wybór funkcjonalnego jest (F T)[⎕IO+x], który nie wygląda szczególnie skróconą lub czytelny dla mnie, mimo że dostaje zadanie, nawet na tablicach:

 ('no' 'yes')[⎕IO+(⍳5)∘.>(⍳5)] 
no no no no no 
yes no no no no 
yes yes no no no 
yes yes yes no no 
yes yes yes yes no 

Próbowałem wymyślić podobne wyrażenie za pomocą składu , ale nie udało się marnie na tablicach booleans. Nawet gdybym mógł, musiałby jeszcze osadzić kod ⎕IO lub kodowany na stałe 1, co jest jeszcze gorsze pod względem czytelności.

Zanim przejdę dalej i zdefiniuję mój własny if i użyję go w każdym programie, jaki kiedykolwiek napiszę, czy jest w tym jakiś kanon? Czy brakuje mi oczywistej funkcji lub operatora?

(Czy są jakieś programiści APL na SO? :-)

Odpowiedz

8

Tak, są programiści APL na SO (ale nie wiele!).

Myślę, że odpowiedź brzmi, że nie ma w tym standardu.

Dla skalarnego rozwiązanie, używam „pick”:

x⊃f t 

Choć dla logicznej tablicy używam indeksowanie jak ty powyżej:

f t[x] 

Zawsze używam pochodzenie indeksem zero, więc nie ma potrzeby dodawania 1, a pareny nie są potrzebne.

Jeśli nie są one wystarczająco proste, myślę, że trzeba je pokryć funkcją o nazwie "jeśli". To również pozwoli ci umieścić prawdę i fałsz w być może bardziej naturalnym uporządkowaniu t f.

+0

Dziękuję. Pochodzę z tła C, więc początek indeksu przy zeru ma dla mnie wiele sensu, ale nie chciałem iść przeciwko "drodze APL". – Tobia

+0

Tony z dokumentów Iversona zakładają pochodzenie zero w całym tekście. Jest to ważny wybór, jeśli upraszcza to, co robisz. –

8

Kłopot z nich:

(f t)[x] 
x⌷f t 
x⊃f t 

jest to, że zarówno t i f się ocenie.

Jeśli chcesz zwarcia rzeczy, można użyć osłony:

{x:t ⋄ f} 

Jest to odpowiednik

if (x) { 
    return t; 
} 
f; 

w języku C-podobne.

+3

Nice. To jest specyficzne dla Dyaloga, prawda? – Tobia

+2

Tak. Którą implementację APL używasz? – ngn

+0

er głupie pytanie. jest wymagany jeden liniowiec? (tak, wiem, że to jest APL), ale jeśli chcesz uniknąć wykonywania obu funkcji, co jest nie tak z prostym wykonaniem warunkowym. (przykro mi, że nie mam klawiatury APL), coś w stylu: ... execute (some_boolean)/'f' execute (~ some_boolean)/'t' klarowność nie jest grzechem! – RFlack

2

Stary, stary idiom, który zrobił coś jak C za potrójnego operatora ? : i zwrócony wynik był następujący:

r←⍎(¯3 3)[x=42]↑'6×8 ⋄ 6×7' 

pamiętać, że jest napisany dla pochodzenia 0 i nawiasy wokół -3 3 istnieją dla jasności.

x = 42 oblicza się na zero lub jeden, w zależności od tej odpowiedzi wybieramy -3 lub 3, a więc wybieramy i wykonujemy albo pierwsze 3 elementy ("6x8"), albo ostatnie 3 elementy ("6x7") strunowy. Diament ⋄ służy tylko do dekoracji.

Nie trzeba dodawać, że prawdopodobnie nie kodowałby w ten sposób, gdyby ktoś miał: if: else available, chociaż forma struktury kontrolnej nie zwróciłaby wyniku.

+0

Czy to trochę nieuporządkowane? (Nienawidzę konieczności liczenia długości wektorów znaków!). Nie mam tutaj klawiatury APL, ale czy nie można użyć zagnieżdżonej tablicy dwóch wektorów char jako rargowania? Podejrzewam, że odpowiedź na PO zależy od kontekstu, który nie był dla mnie całkowicie jasny. – RFlack

+0

Ostatni raz widziałem lub używałem tego około 1979 roku na którymś z systemów Sharpa lub STSC. Zagnieżdżone tablice nie były dostępne w tym czasie. – Lobachevsky

2

W Dyalog APL można użyć:

'value if true' (⊣⍣condition) 'value if false' 

Pomysł ubiega (lewy hals - który zawsze zwraca jego lewy argument, podczas gdy odrzucenie odpowiedniego argumentu) albo 0 (fałsz) lub 1 (dla true) razy - do prawego argumentu. Tak więc, jeśli zostanie zastosowany 0 raz (to jest wcale), prawy argument jest zwracany niezmodyfikowany, ale jeśli zostanie zastosowany (raz), wówczas zastosowany zostanie lewy argument. Np:

 a b←3 5 
     Conditional←⊣⍣(a=b) 
     'match' Conditional 'different' 
different 
     a b←4 4 
     Conditional←⊣⍣(a=b) 
     'match' Conditional 'different' 
match 

lub

 Cond←{⍺(⊣⍣⍺⍺)⍵} 
     bool←a=b 
     'match'(bool Cond)'different' 
match 
+0

Czy drugi wynik nie powinien być "dopasowany"? – Uriel

+0

@Uriel Tak, dziękuję. –

0

To jest częste pytanie, myślę, że powodem nie jest standardowa odpowiedź na to jest fakt, że za to, co można zrobić z APL, jest faktycznie mniejsza potrzeba to niż w innych językach.

Powiedział, że czasami jest to konieczne, i sposób zaimplementować operator w GNU APL IFELSE jest użycie tej funkcji:

∇Z ← arg (truefn IFELSE falsefn) condition ;v 
    v←⍬ 
    →(0=⎕NC 'arg')/noarg 
    v←arg 
noarg: 
    →condition/istrue 
    Z←falsefn v 
    →end 
istrue: 
    Z←truefn v 
end: 
∇ 

Funkcję można nazwać tak:

 3 {'expression is true' ⍵} IFELSE {'was false' ⍵} 0 
was false 3 

Ta konkretna implementacja przechodzi w lewy argument jako do klauzuli, ponieważ czasami może to być przydatne. Bez argumentu z lewej strony przechodzi w .

0

Wyrażenie APL:

(1+x=0)⌷y z 

powinien być odpowiednikiem języka C dla

x?y:z 

I wszyscy inni

(1+x>0)⌷y z 

dla

x<=0?y:z 

Itd W ogóle, jeśli a b c są wyrazem odpowiednich językach wyrażenie APL:

(1+~a)⌷b c 

To powinno być równoznaczne z języka C:

a?b:c