Почему smalltalk не является функциональным языком программирования?

С обновленным интересом к функциональным языкам программирования я видел некоторые сходства между Smalltalk и FPL, а именно закрытие (BlockClosures in Smalltalk). Однако Smalltalk не является FPL?

Что нужно, чтобы считать это таковым?

Ответ 1

Программирование с помощью объектно-ориентированной парадигмы - это создание программы путем идентификации и моделирования объектов проблемных доменов как объектов, а затем их совместной работы между собой для решения каждого экземпляра проблемы. Программирование с помощью функциональной парадигмы моделирует проблему как математическую задачу и создает математическую функцию (путем компоновки других функций), которая для каждого экземпляра задачи вычисляет решение проблемы.

На мой взгляд, язык функционального программирования - это язык, который дает решение проблемы, решаемой с использованием парадигмы функционального программирования, язык может выразить это решение точно так, как считалось. Если вам нужно "трансформировать" часть вашего решения, чтобы оно соответствовало тому, что язык может выразить, то он не полностью поддерживает парадигму, которую вы использовали для решения этого решения.

Smalltalk может выражать в большинстве случаев все решения, созданные с использованием парадигмы объектно-ориентированного программирования, но он не может выразить примитивно множество решений, созданных с использованием парадигмы функционального программирования. Поэтому я не считаю это FPL. Несмотря на то, что он не может примириться с любым вариантом решения FPL, Smalltalk является экстремально расширяемым, и вы можете расширить его, чтобы иметь возможность выражать все решения, которые могут иметь FPL.

Ответ 2

Не существует принятого определения языка функционального программирования.

Если вы определяете функциональный язык как язык, поддерживающий функции первого класса, то да, Smalltalk * - это функциональный язык.

Если вы также учитываете такие факторы, как поддержка неизменности, алгебраические типы данных, сопоставление образцов, частичное приложение и т.д., тогда нет, Smalltalk * не является * функциональным языком.


Я бы посоветовал вам прочитать следующие связанные сообщения в блоге (а также комментарии ниже):

Ответ 3

Smalltalk может не быть "чистым функциональным языком" (каким бы он ни был). Однако естественное использование Smalltalk часто приводит к функциональному коду. (Я думаю, что люди Scala будут называть "объектно-функциональными".)

Например, класс Squeak Point имеет функциональный API: такие методы, как [email protected] translateBy: [email protected], возвращают новые точки с новым состоянием, а не изменяют внутреннее состояние. (Это делает Point практически неизменным, так как единственный способ изменить внутреннее состояние объекта - это механизмы отражения, такие как #instVarAt:.)

Совершенно нормально использовать функции более высокого порядка в Smalltalk, такие как карты, фильтры, складки и т.п. Учитывая, что они запекаются в API коллекций, часто проще писать код, который использует Коллекции функциональным способом, чем нет.

Так много людей имеют так много определений "языка функционального программирования", что вопрос "является Foo FPL" столь же бесполезен, как вопрос "является Foo объектно-ориентированным языком".

Сказав это, здесь мои два цента: функциональный язык программирования - это язык, на котором естественным и идиоматическим является использование функциональных методов: первоклассные функции, избегание изменчивого состояния, свободные побочные эффекты, более высокий порядок функции.

В этом описании Smalltalk является функциональным языком программирования. Он вызывает функции первого порядка "методы" или "блоки" в зависимости от того, являются ли они или анонимными. Объекты хранят состояние в переменных экземпляра. Функции более высокого порядка - это просто методы, которые принимают блоки как параметры.

Сказав это, да, вы можете написать Smalltalk нефункциональным способом. Это позволяет изменять состояние. Означает ли это, что Smalltalk называют функциональным языком? Если это так, то эти языки не функционируют: Common Lisp, Erlang (общее состояние через словарь процесса, ets/dets).

Итак, вкратце, Smalltalk - это FPL, потому что:

  • Функции - это первоклассные объекты (объекты, в Smalltalk - CompiledMethods или BlockClosures, если быть точным).
  • Smalltalk поддерживает замыкания (он вызывает их блоки).
  • Smalltalk позволяет писать функционально естественным, идиоматическим образом.

и Smalltalk не является FPL, потому что:

  • Вы, как программист, должны гарантировать, что ваши структуры данных (объекты) являются неизменяемыми (путем установки сеттерами/мутаторами копий объекта с измененным состоянием).
  • Вы, как программист, должны убедиться, что ваши методы (функции) свободны от побочных эффектов.

(Некоторые Smalltalks явно поддерживают неизменяемые объекты. Мой опыт ограничен Squeak, который не поддерживает неизменность VM-уровня.)

Изменить: я не понимаю, что нужно для именованных определений функций, кроме как путем определения методов для объекта. Но в любом случае, здесь мы идем:

Smalltalk at: #func put: [:x | x + 1].
func value: 1.

Ответ 4

Smalltalk - это чисто объектно-ориентированный язык, где почти весь код в основном является объектом обмена сообщениями. Функциональное программирование ориентировано на вызовы функций и композиции между функциями для создания более сложного поведения (избегая состояния для данных, в отличие от внутренних состояний, которые объекты имеют на любом объектно-ориентированном языке).

Ответ 5

Чисто функциональные языки обычно имеют неизменяемые переменные, что делает их больше похожими на переменные в математическом смысле.

Ответ 6

Язык не становится функциональным языком с помощью названных функций - по этому определению 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! Однако для реализации setter-метода вы должны добавить метод, который выполняет (set! InstVar newValue). И, потому что множество! не работает, нарушает "функциональность" схемы.

Резюме: посмотрите на семантику, а не на источник, luke!

Ответ 7

Спасибо всем за ответы.

Я добавлю свое здесь, которое в основном является моим (возможно, отсутствующим) пониманием вашего.

Я думаю, что критерии называть что-то OO или FP - это то, что "материал" построен с использованием языка; не так, как легко или трудно это сделать, я имею в виду ментальную парадигму.

Например, в качестве показанных ссылок может быть сложнее ввести что-то в Scala, чем в OCaml, но это не делает его менее FPL (возможно, неполным или нечистым, но определенно функциональным); потому что целью Scala является использование функций как первичных строительных блоков, а не объектов.

С другой стороны, упрощение написания функции на языке не делает ее функциональной, если стиль или цель - использовать другие артефакты. Например, Smalltalk позволяет легко написать анонимный блок или предоставить подключаемый компаратор сравнения, но это не делает его ЛЮБОЙ функциональной вообще, поскольку основное внимание уделяется использованию объектов и передаче сообщений. Блокировка блоков - это всего лишь механизм кодирования этих сообщений (а не функций), даже если они выглядят так же, как и функции.

Путаница приходит, потому что OO и FP являются ортогональными (как Rahul, указанными через twitter), поэтому, похоже, что это закодированное сообщение в Smalltalk, выглядит довольно как анонимная функция в Scala. Но что-то подобное не превращает язык одной парадигмы в другую.

Чтобы сделать это наихудшим, Scala также использует парадигму OO, чтобы упростить программистам основного (Java, С++, С#), чтобы дать прыжок, и, если вы видите, у него был больше успеха, чем любой из другие FPL. И, конечно же, это было благодарностью Java (IMHO, если Clojure имеет успех по той же причине, JVM)

В заключение. Язык программирования может быть классифицирован по парадигме, которую он использует для построения "вещей". Существуют такие чистые языки, как [Smalltalk: OO, Haskell: Functional, C: Processural] или гибриды, такие как Scala или множественная парадигма, например С++, Ruby, Python.

Тот факт, что вы можете написать один стиль с другим языком, не делает его языком этого стиля. Подобно моделированию объектов с помощью Lisp не делает его OO, а использование функций с Java не делает его функциональным.

Чтобы ответить на вопрос, чтобы считаться функциональным, Smalltalk должен был использовать функции как строительные блоки, а это не потому, что они используют объекты.

Ответ 8

Я видел несколько similitudes между Smalltalk и FPL, а именно замыкания

Здесь есть более основное сходство - каждое сообщение Smalltalk всегда возвращает значение.

Теперь посмотрим на Принципы проектирования за Smalltalk

[Smalltalk] отправляет имя желаемой операции, а также любой аргументы, как сообщение для числа, с пониманием того, что приемник лучше знает, как выполнять желаемая операция.

Описывает ли это то, что вы считаете функциональным программированием?

@Frank Shearar - Это описывает Эрланг слишком. Является ли Erlang теперь нефункциональным?

Erlang - это что-то вроде химеры - последовательное программирование основано на функциях, но параллельное программирование основано на передаче сообщений между процессами. Таким образом, Erlang не является мульти-парадигмой или гибридом в том смысле, что другие языки позволяют использовать разные стили для достижения той же цели - он использует разные стили для разных целей.

Ответ 9

Что нужно, чтобы рассмотреть это как например?

  • способ объявления функций, а не способ объявления методов в классе

  • способ структурирования программы вокруг функций, а не вокруг объектов

@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, который показывает как анонимную функцию, так и именованную функцию.