С подновения интерес към функционалните езици за програмиране видях някои прилики между Smalltalk и FPL, а именно затваряния ( BlockClosures в Smalltalk ). Все пак Smalltalk не е FPL?
Какво би било необходимо, за да го считаме за такъв?
С подновения интерес към функционалните езици за програмиране видях някои прилики между Smalltalk и FPL, а именно затваряния ( BlockClosures в Smalltalk ). Все пак Smalltalk не е FPL?
Какво би било необходимо, за да го считаме за такъв?
Програмирането с обектно-ориентираната парадигма е създаване на програма чрез идентифициране и моделиране на обектите на проблемната област като обекти и след това ги накара да си сътрудничат помежду си, за да разрешат всеки екземпляр на проблем. Програмирането с функционалната парадигма е моделиране на проблема като математически проблем и създаване на математическа функция (чрез съставяне на други функции), която за всеки екземпляр на проблем изчислява решението на проблема.
Според мен езикът за функционално програмиране е език, който има решение за проблем, решен с помощта на парадигмата за функционално програмиране, езикът може да изрази това решение точно както е мислено. Ако трябва да „преобразувате“ част от решението си, така че да се побере в това, което езикът може да изрази, тогава тя не поддържа напълно парадигмата, която сте използвали, за да мислите за решението.
Smalltalk може да изрази в повечето случаи всички решения, създадени с помощта на парадигмата на обектно-ориентираното програмиране, но не може да изрази примитивно много решения, създадени с помощта на парадигмата на функционалното програмиране. Ето защо не го смятам за FPL. Въпреки че примитивно не може да изрази всяко решение, което FPL може, Smalltalk е изключително разширим и можете да го разширите, за да можете да изразите всички решения, които FPL може.
Няма приета дефиниция за език за функционално програмиране.
Ако дефинирате функционалния език като езика, който поддържа първокласни функции, тогава да, Smalltalk *е* функционален език.
Ако вземете предвид и фактори като поддръжка за неизменност, алгебрични типове данни, съвпадение на шаблони, частично приложение и т.н., тогава не, Smalltalk *не* е функционален език.
Бих ви насърчил да прочетете следните свързани публикации в блогове (както и коментарите под тях):
func
в този пример наименувана функция?
- person missingfaktor; 21.08.2010
Smalltalk може да не е "чист функционален език" (каквото и да е това). Естественото използване на Smalltalk обаче често води до функционален код. (Това, което предполагам, че хората от Scala биха нарекли „обектно-функционално“.)
Например, класът Point на Squeak има функционален API: методи като 1@1 translateBy: 1@1
връщат нови точки с новото състояние, вместо да променят вътрешното състояние. (Това прави Point практически неизменна, тъй като единственият начин да промените вътрешното състояние на обекта е чрез механизми за отразяване като #instVarAt:.)
Съвсем нормално е да използвате функции от по-висок порядък в Smalltalk като карти, филтри, гънки и други подобни. Като се има предвид, че те са вградени в API за колекции, често е по-лесно да се напише код, който използва колекции по функционален начин, отколкото не.
Толкова много хора имат толкова много дефиниции на „функционален език за програмиране“, че въпросът „Foo FPL ли е“ е също толкова безполезен въпрос, колкото „Foo обектно-ориентиран език ли е“.
Като казах това, ето моите два цента: функционалният език за програмиране е език, в който е естествено и идиоматично да се използват функционални техники: първокласни функции, избягване на променливи състояние, функции без странични ефекти, функции от по-висок ред.
Според това описание Smalltalk е функционален език за програмиране. Той извиква функции от първи ред „методи“ или „блокове“ в зависимост от това дали са именувани или анонимни. Обектите съхраняват състоянието в променливи на екземпляр. Функциите от по-висок ред са просто методи, които приемат блокове като параметри.
Като каза това, да, можете да пишете Smalltalk по нефункционален начин. Той позволява променливо състояние. Това спира ли Smalltalk да се нарича функционален език? Ако е така, нито тези езици са функционални: Common Lisp, Erlang (споделено състояние чрез речника на процеса, ets/dets).
И така, накратко, Smalltalk е FPL защото:
и Smalltalk не е FPL защото:
(Някои Smalltalks очевидно поддържат неизменни обекти. Моят опит е ограничен до Squeak, който не поддържа неизменност на ниво VM.)
Редактиране: Не разбирам нуждата на igouy от дефиниции на именувани функции, различни от дефиниране на методи на обект. Но както и да е, започваме:
Smalltalk at: #func put: [:x | x + 1].
func value: 1.
Smalltalk е чисто обектно ориентиран език, където почти целият код е основно обекти, които си обменят съобщения. Функционалното програмиране е ориентирано към извиквания на функции и композиции между функции за създаване на по-сложно поведение (избягване на състояние за данни, за разлика от вътрешните състояния, които обектите имат във всеки обектно-ориентиран език).
Чисто функционалните езици обикновено имат неизменни променливи, което ги прави по-скоро като променливите в математически смисъл.
Един език не се превръща във функционален език, ако има наименувани функции - по тази дефиниция C би бил функционален! По-важна е функционалната семантика в математически смисъл, че резултатът зависи само от аргументите (по-специално: няма странични ефекти). По тази дефиниция обекти, които могат да бъдат модифицирани от сетери, противоречат на функционалния стил на програмиране. Въпреки това, както вече беше посочено, дори обекти могат да се използват във функционален стил (пример с правоъгълник), ако забраните страничните ефекти. И между другото. има двойственост между обекти с методи и набор от функции, които са дефинирани в затваряне над частно състояние (вижте SICP за подробности). Те могат да симулират взаимно:
(def (make_foo initVal1 ... initValN)
(let ((instVar1 initVal1) ... (instVarN initValN))
(define (method1 args) ...)
...
(define (methodN args) ...)
(define (lookup selector)
(cond ((eq? selector 'method1) method1)
...
((eq? selector 'methodN) methodN)
(true doesNotUnderstandCode)))
lookup)) ; returns the lookup function (provides "access into the closure") !
(defMacro (method1 receiver.args)
((receiver selector) args))
(define foo (make_foo 1 2 ...))
(method1 foo ...)
горното е симулация на "чисти" функционални обекти и семантично същото като много код на Smalltalk! Въпреки това, за да приложите сетер-метод, трябва да добавите метод, който прави (set! instVar newValue). И, защото набор! е нефункционална, нарушава "функционалността" на схемата.
Резюме: погледнете семантиката, а не източника, лук!
Благодаря на всички за всички отговори.
Ще добавя моето тук, което основно е моето (вероятно пропуснато) разбиране на вашето.
Мисля, че критериите да се нарече нещо OO или FP е начинът, по който "нещата" са изградени с помощта на езика; не колко лесно или трудно е да го направиш, имам предвид използваната умствена парадигма.
Например, както показват връзките, може да е по-трудно да напишете нещо в Scala, отколкото в OCaml, но това не го прави по-малко FPL (може би непълно или нечисто, но определено функционално); тъй като целта на Scala е да използва функции като основни градивни елементи, а не обекти.
От друга страна, улесняването на писането на функция на език не я прави функционална, ако стилът или целта е да се използват други артефакти. Smalltalk например улеснява писането на анонимен блок или предоставянето на подменяем сортиращ компаратор, но това изобщо не го прави НИКАКЪВ функционален, защото фокусът е върху използването на обекти и предаването на съобщения. Blockclosures са само механизъм за кодиране на тези съобщения (не функции), дори ако изглеждат точно като функции.
Объркването идва, защото OO и FP са ортогонални (както Rahul заяви чрез twitter), така че как изглежда кодирано съобщение в Smalltalk, изглежда доста като анонимна функция в Scala. Но правенето на нещо подобно не преобразува език от една парадигма в друга.
За да бъде най-лошото, Scala също използва парадигмата на OO, за да улесни масовите (Java, C++, C#) програмисти да дадат скок и ако видите, има много по-голям успех от всеки друг FPL. И разбира се, това беше благодарение на Java (IMHO, ако Clojure има някакъв успех, това ще бъде точно поради същата причина, JVM)
В заключение: Езикът за програмиране може да бъде класифициран според парадигмата, която използва за изграждане на „неща“. Има езици, които са чисти като [Smalltalk: OO, Haskell: Functional, C: Procedural], или хибриди, като Scala или мулти парадигма, като C++, Ruby, Python.
Фактът, че можете да пишете един стил с другия език, не го прави този език на този стил. Както симулирането на обекти с Lisp не го прави OO, нито използването на функции с Java го прави функционален.
За да отговори на въпроса, за да се счита за функционален, Smalltalk ще трябва да използва функции като градивни елементи, което не е така, защото използва обекти.
Виждал съм някои прилики между Smalltalk и FPL, а именно затваряния
Има по-основна прилика - всяко съобщение в Smalltalk винаги връща стойност.
Но сега вижте Принципите на проектиране зад Smalltalk
[Smalltalk] изпраща името на желаната операция, заедно с всички аргументи, като съобщение до номера, с разбирането, че получателят знае най-добре как да извърши желаната операция.
Това описва ли това, което смятате за функционално програмиране?
@Frank Shearar - Това описва и Erlang. Сега Erlang не функционира ли?
Erlang е нещо като химера - последователното програмиране се основава на функции, но едновременното програмиране се основава на предаване на съобщения между процеси. Така че Erlang не е мулти парадигма или хибрид по начина, по който другите езици позволяват да се използват различни стилове за постигане на една и съща цел - той използва различни стилове за различни цели.
Какво би било необходимо, за да го считаме за такъв?
начин за деклариране на функции, а не начин за деклариране на методи в клас
начин за структуриране на програма около функции, а не около обекти
@Missing Faktor - но func в този пример не е ли функция с име?
|func v|
func := [:x | x + 1].
v := func value: 5.
Не func
е локална променлива. Свързали сте анонимна функция към локалната променлива func
.
|func v|
func := [:x | x + 1].
func := 2.
v := func value: 5.
За да видите разликата, погледнете този пример за Erlang, който показва както анонимна функция, така и именувана функция.