С возрождением интереса к функциональным языкам программирования я заметил некоторое сходство между 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 назвали бы «объектно-функциональным».)
Например, класс Squeak's Point имеет функциональный API: такие методы, как 1@1 translateBy: 1@1
, возвращают новые Points с новым состоянием вместо изменения внутреннего состояния. (Это делает Point практически неизменяемым, поскольку единственный способ изменить внутреннее состояние объекта — использовать механизмы отражения, такие как #instVarAt:.)
Вполне нормально использовать в Smalltalk функции более высокого порядка, такие как карты, фильтры, складки и тому подобное. Учитывая, что они встроены в API коллекций, часто проще написать код, который функционально использует коллекции, чем не использовать их.
Так много людей имеют так много определений «функционального языка программирования», что вопрос «является ли Foo FPL» столь же бесполезен, как и вопрос «является ли Foo объектно-ориентированным языком».
Сказав это, вот мои два цента: функциональный язык программирования — это язык, в котором естественно и идиоматично использовать функциональные методы: первоклассные функции, избегание изменяемых состояние, функции без побочных эффектов, функции высшего порядка.
Согласно этому описанию, Smalltalk является функциональным языком программирования. Он вызывает функции первого порядка «методы» или «блоки» в зависимости от того, являются ли они именованными или анонимными. Объекты хранят состояние в переменных экземпляра. Функции высшего порядка — это просто методы, которые принимают блоки в качестве параметров.
Сказав это, да, вы можете написать Smalltalk нефункциональным способом. Это позволяет изменять состояние. Мешает ли это тому, чтобы Smalltalk называли функциональным языком? Если это так, то эти языки не работают: Common Lisp, Erlang (общее состояние через словарь процесса, ets/dets).
Итак, вкратце, Smalltalk — это FPL, потому что:
и Smalltalk не является FPL, потому что:
(Некоторые Smalltalk, по-видимому, поддерживают неизменяемые объекты. Мой опыт ограничен Squeak, который не поддерживает неизменность на уровне VM.)
Изменить: я не понимаю потребности iguy в определениях именованных функций, кроме определения методов для объекта. Но в любом случае, вот:
Smalltalk at: #func put: [:x | x + 1].
func value: 1.
Smalltalk — это чисто объектно-ориентированный язык, где почти весь код в основном представляет собой объекты, обменивающиеся сообщениями. Функциональное программирование ориентировано на вызовы функций и композиции между функциями для создания более сложного поведения (избегая состояния для данных, в отличие от внутренних состояний, которые имеют объекты в любом объектно-ориентированном языке).
Чисто функциональные языки обычно имеют неизменяемые переменные, что делает их более похожими на переменные в математическом смысле.
Язык не становится функциональным, если у него есть имена функций — по этому определению C будет функциональным! Более важной является функциональная семантика в математическом смысле, что результат зависит только от аргументов (в частности: никаких побочных эффектов). По этому определению объекты, которые могут быть изменены сеттерами, противоречат функциональному стилю программирования. Однако, как уже отмечалось, даже объекты можно использовать в функциональном стиле (пример Rectangle), если запретить побочные эффекты. И, кстати. существует двойственность между объектами с методами и набором функций, которые определены в замыкании над приватным состоянием (подробности см. в 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, например, позволяет очень легко написать анонимный блок или предоставить подключаемый компаратор сортировки, но это вообще не делает его ЛЮБЫМ функциональным, потому что основное внимание уделяется использованию объектов и передаче сообщений. Блокировка — это всего лишь механизм для кодирования этих сообщений (не функций), даже если они выглядят так же, как и функции.
Путаница возникает, потому что OO и FP ортогональны (как заявил Rahul через twitter), так что это выглядит закодированное сообщение в Smalltalk очень похоже на анонимную функцию в Scala. Но выполнение чего-то подобного не превращает язык одной парадигмы в другую.
Что еще хуже, Scala также использует парадигму объектно-ориентированного программирования, чтобы упростить для основных (Java, C++, C#) программистов переход, и, если вы видите, он имел гораздо больший успех, чем любой другой FPL. И, конечно же, это было благодаря Java (ИМХО, если Clojure будет иметь какой-либо успех по той же причине, JVM)
В заключение: язык программирования можно классифицировать по парадигме, которую он использует для создания "вещей". Существуют чистые языки, такие как [Smalltalk: OO, Haskell: функциональный, C: процедурный], или гибриды, такие как Scala или мультипарадигмальные, такие как C++, Ruby, Python.
Тот факт, что вы можете написать один стиль на другом языке, не делает его языком этого стиля. Например, моделирование объектов с помощью Lisp не делает его объектно-ориентированным, а использование функций с 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, в котором показаны как анонимная функция, так и названная функция.