Użyj operatorów arytmetycznych jako konstruktorów krotek i par wad
Jeśli potrzebujesz przekazać pojedynczą strukturę składającą się z dwóch lub więcej wartości, najbardziej oczywistą rzeczą jest użycie listy, np [A,B]
. Ale to naprawdę gadatliwe.
Istnieje alternatywa. Wartości Prolog mogą przechowywać prawie dowolną zagnieżdżoną strukturę, która nie jest oceniana. Oto przykład pokazujący, jak to działa:
| ?- member(member(A,B),C).
C = [member(A,B)|_] ? ;
C = [_,member(A,B)|_] ? ;
(etc.)
member(A,B)
jest tylko nazwaną krotką w tej sytuacji i na zewnątrz member
(które jest wywołaniem funkcji), traktuje to jako takie.
Chociaż nazwane krotki są dość przydatne w programowaniu Prologa bez gry w golfa, mogą wydawać się bardziej szczegółowe niż podejście oparte na liście. W nazwie konstruktora krotek możemy jednak używać dowolnych znaków (przy założeniu, że są odpowiednio cytowane); zamiast czegoś uroczego member
lub pojedynczej postaci a
, możemy zrobić coś takiego:
| ?- A = '-'('/'(1,2), '/'(3,4)).
A = 1/2-3/4
Tutaj naszymi konstruktorami krotek są '-'
i '/'
. Ciekawe jest to, co zrobiła z nimi ładna drukarka; to za pomocą Infix notacji dla krotek. To jest naprawdę zwięzłe i analizuje w taki sam sposób, jak zrobiłaby to porównywalna operacja arytmetyczna. (To również wyjaśnia, dlaczego arytmetyczne zastosowania is
nie =
; A = 1+2
byłoby ujednolicenie A
z krotki '+'(1,2)
, potrzebna jest więc osobne składnia faktycznie ocenić unevaluated wyrażenia arytmetycznego.) Ponieważ konstruktor krotki musi być nazywany coś , równie dobrze możesz użyć znaku, który ma zwięzłość składnia (i jako bonus -
oraz/
są jednymi z najczęstszych wyborów w kodzie innym niż golfowy, gdy chcą raczej szybkiego konstruktora krotek zamiast czegoś znaczącego, w ten sam sposób, któryi
jest często używany jako zmienna pętli, więc jest całkowicie rozsądny do użycia w danych wejściowych i wyjściowych, jeśli z jakiegoś powodu chcesz mieć krotkę).
'-'
i '/'
są dobrym wyborem dla konstruktorów krotek, ponieważ mają dobrze zachowane i przydatne pierwszeństwo, pozwalając ci na krótkie pisanie krotek. Należy jednak pamiętać, że nie trzeba się martwić o pierwszeństwo, gdy wartości pośrednie są generowane w programie. Prolog przechowuje krotki przechowywane jako drzewo, a nie jako kod źródłowy, a ładne drukarki mogą je wypisać jednoznacznie:
| ?- A = '-'('-'(1,2), '-'(3,4)).
A = 1-2-(3-4)
Ponieważ składnia krotki jest tak zwięzła ( f(A,B)
nie jest krótsza niżf(A-B)
), możesz zastąpić wiele argumentów predykatowych krotkami bez żadnych kosztów, co oznacza, że jeśli predykat musi przekazać dwa lub więcej swoich argumentów do innego predykatu, często możesz je uformować w krotkę i wystarczy przekazać krotkę (chociaż będzie to wymagało zmiany wszystkich wywołań do predykatu, oprócz samego predykatu, w celu użycia odpowiedniej kombinacji konstruktorów krotek i przecinków).
Kolejną zaletą tej składni jest to, że trzeba używać list wewnętrznie (zamiast współdziałać ze standardowymi predykatami); lista jest w zasadzie tylko zestawem zagnieżdżonych komórek Cons, a komórka Cons to tylko krotka z konstruktorem '.'
, jak widać tutaj:
| ?- Q = '.'('.'(A,B),'.'(C,D)).
Q = [[A|B],C|D]
Jeśli Twój kod używa list „ręcznie”, sensowne może być użycie mniej rozbudowanego konstruktora krotek niż '.'
. Częstym wyborem jest dla mnie reprezentowanie komórki przeciwnej jako '/'(Tail,Head)
(ponieważ jest to najbardziej czytelny wynik debugowania bez marnowania znaków). Zauważ, że prawdopodobnie będziesz także chciał mieć swój własny []
odpowiednik; Państwo mogli korzystać[]
, ale to dwa bajty długości i istnieje wiele atomów jedno-bajtowych (wszystkie małe litery), które można używać zamiast.
Na przykład następująca lista:
[1,2,3]
można przekonwertować na ręczne przedstawienie przy użyciu takiej samej liczby znaków, jak ten:
x/3/2/1
zyskując przy tym tę zaletę, że [H|T]
dopasowania do stylu w stylu można teraz pisać bardziej zwięźle jako T/H
, a test na pustej liście jako po prostu x
zamiast dłuższej []
. (Oczywiście, to przychodzi z oczywistą wadę, że member
, append
itp, nie będzie działać na tej reprezentacji).
prolog
Tag jest trochę bezużyteczne. O ile nie mamy wyzwania Interpret Prolog, nie potrzebujemy go.