Mam na myśli to w ten sposób:
<?php
$number1 = 5; // (Type 'Int')
$operator1 = +; // (Type non-existent 'Operator')
$number2 = 5; // (Type 'Int')
$operator2 = *; // (Type non-existent 'Operator')
$number3 = 8; // (Type 'Int')
$test = $number1 $operator1 $number2 $operator2 $number3; //5 + 5 * 8.
var_dump($test);
?>
Ale także w ten sposób:
<?php
$number1 = 5;
$number3 = 9;
$operator1 = <;
if ($number1 $operator1 $number3) { //5 < 9 (true)
echo 'true';
}
?>
Wydaje się, że nie ma tego w żadnym języku - czy jest dobry powód, dla którego go nie ma?
programming-languages
variables
operators
kgongonowdoe
źródło
źródło
(+)
toNum a => a -> a -> a
IIRC. możesz również zdefiniować funkcje, aby można je było zapisać w postaci nieskorygowanej (a + b
zamiast(+) a b
)Odpowiedzi:
Operatory to tylko funkcje o śmiesznych nazwach, z pewną specjalną składnią.
W wielu językach, tak różnorodnych jak C ++ i Python, można przedefiniować operatory, zastępując specjalne metody klasy. Następnie standardowe operatory (np.
+
) Działają zgodnie z logiką, którą podajesz (np. Łączenie łańcuchów lub dodawanie macierzy lub cokolwiek innego).Ponieważ takie funkcje definiujące operator są tylko metodami, możesz przekazać je tak jak funkcję:
Inne języki pozwalają bezpośrednio definiować nowe operatory jako funkcje i używać ich w formie infix.
Niestety, nie jestem pewien, czy PHP obsługuje coś takiego, i czy wsparcie byłoby dobrą rzeczą. Użyj prostej funkcji, jest bardziej czytelna niż
$foo $operator $bar
.źródło
$
operatorem, który omija nawiasy (szczególnie wiele zagnieżdżonych) - ale to może działać tylko z -funkcje funkcyjne, wykluczając np. Python i Java. Kompozycja funkcji jednoargumentowej OTOH może być ładnie wykonana .operator
moduł, który pozwalałby Ci pisaćaction = operator.add
i pozwalał na pracę z każdym typem, który definiuje+
(nie tylkoint
).+
działa na typie Num, więc możesz zaimplementować+
każdy nowy typ danych, który tworzysz, ale w taki sam sposób, jak robisz cokolwiek innego, np. Fmap dla funktora. To jest tak naturalne dopasowanie dla Haskell, aby umożliwić przeciążenie operatora, że będą musieli ciężko pracować, aby na to nie pozwolić!$operator1 = +
a następnie użyć wyrażenia, nie trzeba wcale przeciążać operatora !Istnieje wiele języków, które pozwalają na pewien rodzaj metaprogramowania . W szczególności jestem zaskoczony brakiem odpowiedzi na temat rodziny języków Lisp .
Z wikipedii:
Później w tekście:
Języki Lisp
Następuje szybkie, zmyślone wprowadzenie do Lisp.
Jednym ze sposobów na zobaczenie kodu jest zestaw instrukcji: zrób to, następnie zrób to, a następnie zrób jeszcze jedną rzecz ... To jest lista! Lista rzeczy do zrobienia dla programu. I oczywiście możesz mieć listy wewnątrz list do reprezentowania pętli i tak dalej ...
Jeśli będziemy reprezentować listę zawierającą elementy a, b, c, d tak: (ABCD) otrzymujemy coś, co wygląda jak Lisp wywołania funkcji, gdzie
a
jest funkcja, ib
,c
,d
są argumenty. Jeśli faktem jest typowy „Hello World!” program można napisać tak:(println "Hello World!")
Oczywiście
b
,c
lubd
mogą to być listy, które również coś oceniają. Następujące:(println "I can add :" (+ 1 3) )
wydrukuje „„ Mogę dodać: 4 ”.Tak więc program to seria zagnieżdżonych list, a pierwszy element to funkcja. Dobra wiadomość jest taka, że możemy manipulować listami! Możemy więc manipulować językami programowania.
Zaleta Lisp
W Lisps jest to nie tylko łatwiejsze do tworzenia nowych operatorów, ale także prawie niemożliwe jest napisanie niektórych operatorów w innych językach, ponieważ argumenty są oceniane po przekazaniu do funkcji.
Na przykład w języku podobnym do C powiedzmy, że chcesz sam napisać
if
operator, coś w stylu:my-if(condition, if-true, if-false)
my-if(false, print("I should not be printed"), print("I should be printed"))
W takim przypadku oba argumenty zostaną ocenione i wydrukowane, w kolejności zależnej od kolejności oceny argumentów.
W Lisps pisanie operatora (nazywamy to makro) i pisanie funkcji jest mniej więcej tym samym i jest używane w ten sam sposób. Główną różnicą jest to, że parametry makra nie są oceniane przed przekazaniem ich jako argumentów do makra. Jest to niezbędne, aby móc napisać niektóre operatory, takie jak
if
powyższe.Prawdziwe języki
Pokazuje, jak dokładnie jest to trochę poza zasięgiem, ale zachęcam do wypróbowania programowania w jednym Lisp, aby dowiedzieć się więcej. Na przykład możesz rzucić okiem na:
A tak przy okazji, Lisp oznacza LISt Processing.
Jeśli chodzi o twoje przykłady
Podam przykłady przy użyciu Clojure poniżej:
Jeśli możesz napisać
add
funkcję w Clojure(defn add [a b] ...your-implementation-here... )
, możesz ją+
tak nazwać(defn + [a b] ...your-implementation-here... )
. To właśnie dzieje się w rzeczywistej implementacji (treść funkcji jest nieco bardziej zaangażowana, ale definicja jest zasadniczo taka sama, jak napisałem powyżej).Co z notacją infix? Cóż, Clojure używa
prefix
notacji (lub polskiej), więc możemy stworzyćinfix-to-prefix
makro, które zamienia prefiks w kod Clojure. Co jest w rzeczywistości zaskakująco łatwe (w rzeczywistości jest to jedno z ćwiczeń makro w kojojach clojure)! Można go również zobaczyć na wolności, na przykład zobacz makro Incanter$=
.Oto wyjaśniona najprostsza wersja z koanów:
Aby jeszcze bardziej rozwinąć sprawę , niektóre cytaty Lisp :
źródło
if
, ale należy zawinąć argumentythen
i zaelse
pomocą lambdas. PHP i JavaScript mająfunction()
, C ++ ma lambdas i istnieje rozszerzenie Apple do C z lambdas.Większość implementacji języków ma krok, w którym analizator składni analizuje kod i buduje z niego drzewo. Na przykład wyrażenie
5 + 5 * 8
zostanie sparsowane jakodzięki wiedzy kompilatora na temat pierwszeństwa. Jeśli podasz zmienne zamiast operatorów, przed uruchomieniem kodu nie znałby właściwej kolejności operacji. W przypadku większości implementacji byłby to poważny problem, więc większość języków na to nie pozwala.
Można oczywiście wymyślić język, w którym analizator składni po prostu analizuje powyższe jako sekwencję wyrażeń i operatorów, które mają być sortowane i oceniane w czasie wykonywania. Prawdopodobnie nie ma na to zbyt wiele zastosowań.
Wiele języków skryptowych pozwala na ocenę dowolnych wyrażeń (lub przynajmniej dowolnych wyrażeń arytmetycznych jak w przypadku
expr
) w czasie wykonywania. Tam możesz po prostu połączyć swoje liczby i operatory w jedno wyrażenie i pozwolić językowi to ocenić. W PHP (i wielu innych) ta funkcja jest wywoływanaeval
.Istnieją również języki, które pozwalają na generowanie kodu w czasie kompilacji. Wyrażenie mixin D przychodzi mi do głowy, gdzie wierzę można napisać coś podobnego
Tutaj
operator1
ioperator2
musiałyby istnieć stałe ciągów, które są znane w czasie kompilacji, np. Parametry szablonu.number1
,number2
Inumber3
pozostawiano w normalnych zmiennych wykonawczych.Inne odpowiedzi już omawiały różne sposoby, w jaki operator i funkcja są mniej więcej tym samym, w zależności od języka. Ale zwykle istnieje różnica składniowa między wbudowanym symbolem operatora infix jak
+
i nazwanym podobnym do wywołaniaoperator1
. Zostawię szczegóły tym innym odpowiedziom.źródło
eval()
konstrukcją językową ” ... Technicznie zapewnia dokładnie pożądany wynik zadany w pytaniu.eval
nie odpowiada na ten aspekt, ponieważ dlaeval
operatorów są to tylko ciągi znaków. Dlatego zacząłem od wyjaśnienia, dlaczego zmienne typu operator powodują problemy, zanim zacznę omawiać alternatywy.Algol 68 miał dokładnie tę funkcję. Twój przykład w Algolu 68 wyglądałby tak:
Twój drugi przykład wyglądałby tak:
Zauważysz, że symbole operatora są zdefiniowane i przypisane ciała metod, które zawierają żądaną operację. Operatory i ich operand są wpisane na maszynie, a operatorom można przypisać priorytety, aby ocena przebiegała w prawidłowej kolejności. Można również zauważyć, że istnieje niewielka różnica w czcionkach między symbolem operatora a symbolem zmiennej.
W rzeczywistości, chociaż język jest pisany przy użyciu czcionek, maszyny dnia nie były w stanie poradzić sobie z czcionkami (taśma papierowa i karty dziurkowane) i zastosowano stropowanie . Program prawdopodobnie zostanie wprowadzony jako:
Możesz także grać w ciekawe gry z tym językiem, w którym możesz zdefiniować własne symbole operatorów, które wykorzystałem raz, wiele lat temu ... [2].
Bibliografia:
[1] Nieformalne wprowadzenie do Algolu 68 autorstwa CHLindsey i SG van der Meulen, Holandia Północna, 1971 .
[2] Algol 68 Phrases, narzędzie wspomagające pisanie kompilatorów w Algolu 68 , BC Tompsett, Międzynarodowa konferencja nt. Zastosowań Algolu 68, na University of East Anglia, Norwich, Wielka Brytania, 1976 .
źródło