Почему в императивных языках нет сопоставления с образцом?

Итак, сопоставление с образцом в функциональных языках - это довольно круто. Мне интересно, почему в большинстве императивных языков не реализована эта функция? Насколько я понимаю, Scala - единственный «основной» императивный язык, в котором есть сопоставление с образцом. Структура корпуса / переключателя намного менее мощная.

В частности, меня интересует, вызвано ли отсутствие сопоставления с образцом техническими или историческими причинами?


person mollerhoj    schedule 31.07.2014    source источник
comment
Почему Scala является императивным языком? (Язык в щеку, но дело в том, что кто-то так спроектировал.)   -  person user2864740    schedule 31.07.2014
comment
Все это предположения, но я предполагаю, что соответствующие системы типов играют роль. Многие современные императивные языки имеют системы типов, которые не такие жесткие, как у функциональных языков. Сопоставление с образцом быстро сбивает с толку, если в языке есть динамическая типизация.   -  person Wander Nauta    schedule 31.07.2014
comment
@WanderNauta Я не вижу, как это повлияет на сопоставление с образцом больше, чем на другие, просто зная, что эта переменная / выражение является аспектами динамической типизации. В качестве контрпримера: Clojure является динамическим, но поддерживает сопоставление с образцом.   -  person user2864740    schedule 31.07.2014
comment
@ user2864740, а почему нет?   -  person om-nom-nom    schedule 01.08.2014


Ответы (4)


Это в основном историческое. Сопоставление с образцом - а точнее, алгебраические типы данных - было изобретено примерно в 1980 году для функционального языка Hope. Оттуда он быстро превратился в ML, а позже был принят на других функциональных языках, таких как Miranda и Haskell. В господствующем императивном мире обычно требуется на несколько десятилетий больше, чтобы уловить новые идеи языка программирования.

Одна из причин, по которой принятие особенно затруднено, заключается в том, что в мейнстриме долгое время доминировала объектно-ориентированная идеология. В этом мире все, что не выражается объектами и подтипами, считается морально «неправильным». Можно утверждать, что алгебраические типы данных являются своего рода противоположностью этому.

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

  • Регулярные правила определения области видимости и детализированные конструкции привязки для переменных являются нормой для функциональных языков, но менее распространены в основных императивных языках.

  • Тем более, что шаблоны связывают неизменяемые переменные.

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

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

person Andreas Rossberg    schedule 01.08.2014
comment
Из статьи в Википедии «Сопоставление с образцом»: Первыми компьютерными программами, в которых использовалось сопоставление с образцом, были текстовые редакторы. В Bell Labs Кен Томпсон расширил функции поиска и замены редактора QED, чтобы они могли принимать регулярные выражения. Ранние языки программирования с конструкциями сопоставления с образцом включают SNOBOL с 1962 года, SASL с 1976 года, NPL с 1977 года и KRC с 1981 года. Также Prolog имеет сопоставление с образцом через унификацию с 1972 года. - person Shon; 23.06.2016
comment
@ShonFeder, честно, но термин сопоставление с образцом довольно перегружен и расплывчат. В контексте функциональных языков это обычно относится к конструкции, которая различает случаи (алгебраических) типов данных и обобщает такие конструкции, как if, case или switch. AFAII, это был роман в «Надежде». - person Andreas Rossberg; 23.06.2016

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

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

Библиотека сопоставления с образцом, вдохновленная Scala, в которой образцы сами по себе являются первоклассными объектами (вдохновленные активными образцами F #), была добавлена ​​в новояз, очень динамический язык, который требует OO очень серьезно. (В новоязе нет даже переменных, только методы.)

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

person Jörg W Mittag    schedule 01.08.2014
comment
Вы говорите, что Scala сначала изобрела определяемое пользователем сопоставление, также известное как представления, для согласования сопоставления с образцом с абстракцией данных. Это определенно не так, см., Например, Статья Вадлера о представлениях 1987 г. (homepages.inf.ed. ac.uk/wadler/topics/language-design.html#views), который был только первым в длинном списке. - person Andreas Rossberg; 01.08.2014
comment
@AndreasRossberg: это об абстрактных типах данных или объектах? Т.е. абстракция на основе имени типа или процедурная абстракция? - person Jörg W Mittag; 01.08.2014
comment
Это имеет значение? Проблема одинакова, независимо от того, есть ли у вас интенсиональная или экстенсиональная абстракция данных. Решение, естественно, будет использовать преобладающий механизм, то есть объектно-ориентированный язык будет использовать методы, а не функции для преобразования представления. В этом нет ничего удивительного. - person Andreas Rossberg; 01.08.2014

Вот мои 2 цента. Возьмем простое совпадение Option с шаблоном:

val o = Some(1)

o match {
  case Some(i) => i + 1
  case None => 0
}

В Scala происходит так много всего. Компилятор проверяет, есть ли у вас полное соответствие, создает новую переменную i для области действия оператора case и, конечно же, каким-то образом извлекает значение из Option.

Извлечь значение можно на таких языках, как Java. Реализуйте unapply методы некоторого согласованного интерфейса, и все готово. Теперь вы можете возвращать значения вызывающему.

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

Если вы добавите в смесь другие возможности Scala по сопоставлению с образцом, например сопоставление по определенным типам, то есть case i: Int =>; используя предложение по умолчанию _, когда вы хотите (компилятор должен каким-то образом проверять полноту, используете ли вы _ или нет); дополнительные проверки типа case i if i > 0 =>; и так далее он быстро становится очень уродливым для использования со стороны клиента (подумайте о Java).

Если вы отбросите все эти причудливые функции сопоставления с образцом, сопоставление с образцом будет в значительной степени на уровне оператора Java switch.

Похоже, что просто не стоит, даже если это возможно, реализовывать с использованием анонимных классов без поддержки лямбда-выражений и строгой системы типов.

person yǝsʞǝla    schedule 01.08.2014
comment
Ваш ответ относится к тому, как Scala выполняет сопоставление с образцом. Сопоставление с образцом в типичных функциональных языках значительно проще и не требует закрытий (но все же намного лучше, чем переключатель). - person Andreas Rossberg; 01.08.2014
comment
@AndreasRossberg в вопросе конкретно упоминается Scala как основной объектно-ориентированный язык, поддерживающий сопоставление с образцом, поэтому здесь уместно поговорить о реализации сопоставления с образцом в Scala. - person Yawar; 18.06.2015

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

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

Примером современного, в основном императивного языка с сопоставлением с образцом является Rust. Императивен и работает на металле, но по-прежнему имеет алгебраические типы данных, сопоставление с образцом и другие функции, более общие для функциональных языков. Но его реализация компилятора намного сложнее, чем у компилятора C.

person triggerNZ    schedule 01.08.2014