Modeluję język programowania dla zabawy, a na składnię ma duży wpływ Scala - w szczególności definicje funkcji.
Wystąpił problem projektowy, ponieważ mój język nie rozróżnia funkcji zdefiniowanych za pomocą def
składni (metody klasowe) i funkcji anonimowych przypisanych do wartości (utworzonych przy użyciu =>
) - usuwa różnice zarówno w implementacji, jak i zachowaniu .
W rezultacie następujące dwie definicje oznaczają to samo:
def square(x: Int) = x*x
val square = (x: Int) => x*x
Nie ma powodu, aby ten drugi formularz (natychmiastowe przypisanie funkcji anonimowej) był używany w normalnej sytuacji - po prostu można go użyć zamiast def
formularza.
Czy posiadanie takiej zduplikowanej składni do definiowania nazwanych funkcji zaszkodziłoby ortogonalności języka lub innemu aspektowi projektowania?
Wolę to rozwiązanie, ponieważ pozwala ono na krótkie i intuicyjne definicje metod i nazwanych funkcji (via def
) oraz krótkie definicje funkcji anonimowych (using =>
).
Edit: Scala czyni rozróżnienia między tymi dwoma - funkcje anonimowe nie są takie same jak z metod określonych def
w Scala. Różnice są jednak stosunkowo subtelne - zobacz posty, które wcześniej podlinkowałem.
źródło
However, assigning existing functions
wydaje się, że brakuje końca zdaniaval
notacji?fun
aby zdefiniować funkcję rekurencyjną.def
. Jest to tylko efekt uboczny tego, że anonimowa funkcja, powiedzmy,(x : Int) => x + 1
jest obiektem, a obiekty można przypisywać do wartości za pomocąval f = ...
. Projektanci języka musieliby zrobić wszystko, aby nie dopuścić do składni. Nie jest to dokładnie to samo, co jednoznaczne włożenie wysiłku w celu obsługi dwóch różnych składni, które wykonują (w przybliżeniu) to samo.Odpowiedzi:
Myślę, że posiadanie dwóch konstrukcji, które oznaczają to samo, ale wyglądają inaczej, powinno być ograniczone do absolutnego minimum w języku. Wszelkie powielanie zwiększa trudność odczytu (a tym samym pisania / modyfikacji kodu) twojego języka. Wyeliminowanie wszelkiego powielania jest nieuniknione w języku, który może tworzyć dowolne konstrukcje (na przykład równoważność iteracji vs. rekurencji).
Więc w tym przypadku myślę, że można by go tutaj lepiej zaprojektować. Jeden sposób definiowania funkcji jest dla mnie najbardziej sensowny. W tym przypadku wygląda na to, że dwie instrukcje Scala, które faktycznie masz, mają nieco inne implikacje, co znowu prawdopodobnie nie jest dobrym projektem (prawdopodobnie najlepiej mieć coś wyraźnego, co określa różnice, na przykład słowo kluczowe).
W rzeczywistości możesz zastosować tę zasadę nie tylko do nazwanych funkcji, ale do dowolnej funkcji. Po co różnica w definiowaniu nazwanych funkcji i funkcji anonimowych? W Limie , funkcje są zawsze zdefiniowane tak:
fn[<arguments>: <statements>]
. Jeśli ma to być „o nazwie” można przypisać ją do zmiennej:var x = fn[<arguments: <statements>]
i jeśli chcesz przekazać go do innej funkcji anonimowo:function[fn[<arguments: <statements>]]
. Jeśli chcesz go podnieść, ustaw go na stałeconst var x = fn[<arguments: <statements>]
. Pojedyncza forma pokazuje, że oznaczają to samo.źródło
const
powoduje podnoszenie, ale ma doskonały sens. W JSfunction myFunc
powoduje podnoszenie, alevar myFunc =
nie robi tego, co może być nieco mniej intuicyjne, ponieważ inaczej zachowują się tak samo.function fnName()...
forma ma w rzeczywistości stworzyć stały, co czyni podnoszenia ważną rzeczą do zrobienia z nim. JavaScript sprawia, że korzystanie z formularza jest dość mylące,var fn = function anotherFnName()...
ponieważ sprawia, że nazwaanotherFnName
nie podnosi się , nawet jeśli jest wyraźnie stała.To, co opublikowałeś, jest prawidłową skalą i działa dobrze.
Biorąc pod uwagę, że podwojenie nie spowodowało problemów ze skalą (o ile mi wiadomo), powiem, że nie będzie to również problem dla twojego języka.
źródło
Znalazłem zasadniczą różnicę między lambdami a
def
metodami w Scali - że nadal nie jestem pewien, czy chcę wdrożyć. Muszę przeprowadzić dalsze badania, a następnie zdam relację z mojej decyzji.Zasadniczo tylko metody mogą
return
- a gdy słowo kluczowe jest używane z lambda, faktycznie wraca z metody obejmującej.Jak powiedziałem, nie jestem pewien, czy tego chcę. Ale to może być wystarczające uzasadnienie dla tej składni. A może zbyt niebezpieczne, ponieważ subtelne różnice mogą nieoczekiwanie powodować szkody.
Detale
źródło