W zależności od składni języka należy rozważyć dwa różne przypadki. Jeśli twój język używa nawiasów do wskazania zastosowania funkcji (np. f(2+1)
), Wówczas pierwszeństwo nie ma znaczenia. Funkcję należy wypchnąć na stos i wyskoczyć po niej (w powyższym przykładzie wynik jest 2 1 + f
). Alternatywnie możesz traktować funkcję jako wartość i wyprowadzać ją natychmiast, a następnie wywołać operację wywołania funkcji po zamkniętym nawiasie (który w przeciwnym razie powinien być traktowany tak samo jak każdy inny nawias), np. f 2 1 + $
Gdzie $
jest operacja wywołania funkcji.
Jeśli jednak twój język nie używa nawiasów w celu wskazania wywołania funkcji, ale zamiast tego umieszcza argument bezpośrednio za funkcją bez specjalnej interpunkcji (np. f 2 + 1
), Jak najwyraźniej ma to miejsce w przypadku Wikipedii, sprawy są nieco bardziej skomplikowane. Zauważ, że wyrażenie, które właśnie podałem, jest niejednoznaczne: czy f jest stosowane do 2 i 1 dodanych do wyniku, czy też dodajemy 2 i 1 razem, a następnie wywołujemy f z wynikiem?
Ponownie istnieją dwa podejścia. Możesz po prostu przesunąć funkcję na stos operatora, gdy ją napotkasz, i przypisać jej dowolny priorytet. Jest to najprostsze podejście i najwyraźniej to, co zrobił cytowany przykład. Istnieją jednak problemy praktyczne. Po pierwsze, jak rozpoznać funkcję? Jeśli masz skończony zestaw, jest to łatwe, ale jeśli masz funkcje zdefiniowane przez użytkownika, oznacza to, że twój parser musi również przesyłać informacje zwrotne do twojego środowiska, które może szybko się popsuć. Jak radzisz sobie z funkcjami z wieloma argumentami?
Mam wrażenie, że dla tego stylu składni używanie funkcji jako wartości obsługiwanych przez operatora aplikacji funkcji ma o wiele większy sens. Następnie możesz po prostu wstrzyknąć operatorowi aplikacji za każdym razem, gdy czytasz wartość, a ostatnią rzeczą, którą czytasz, była również wartością, więc nie potrzebujesz żadnego specjalnego sposobu określania, które identyfikatory są funkcjami. Możesz także pracować z wyrażeniami, które zwracają funkcje (co jest trudne lub niemożliwe ze stylem funkcji jako operacji). A to oznacza, że możesz używać curry do obsługi wielu funkcji argumentów, co jest ogromnym uproszczeniem w stosunku do próby bezpośredniego obsługiwania ich.
Jedyną rzeczą, którą musisz wtedy zdecydować, jest pierwszeństwo zastosowania funkcji. Wybór należy do ciebie, ale w każdym używanym przeze mnie języku, który działa w ten sposób, był to najsilniej wiążący operator w tym języku i miał właściwą asocjację. (Jedyną interesującą odmianą jest Haskell, która oprócz opisanej silnie wiążącej wersji, ma również swój synonim z symbolem, $
który jest najsłabiej wiążącym operatorem w języku, umożliwiając wyrażenia takie jak f 2 + 1
zastosowanie f do 2 i f $ 2 + 1
zastosowanie do reszty wyrażenia)
sin( max( 2 3) / 3 * 3.1415)