Утиный набор текста, он должен быть динамичным?

Википедия раньше говорила * о утином наборе:

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

(* Примечание редактора: с тех пор, как этот вопрос был опубликован, статья в Википедии была отредактирована, чтобы удалить слово «динамический».)

В нем говорится о структурной типизации:

Система структурных типов (или система типов на основе свойств) - это основной класс систем типов, в которых совместимость и эквивалентность типов определяются структурой типа, а не явными объявлениями.

Он противопоставляет структурное подтипирование и утиную типизацию следующим образом:

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

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

Название концепции [duck-typing] относится к тесту на утку, приписываемому Джеймсу Уиткомбу Райли. который можно сформулировать следующим образом: «когда я вижу птицу, которая ходит, как утка, плавает, как утка, и крякает, как утка, я называю эту птицу уткой».

Итак, мой вопрос: почему я не могу назвать структурное подтипирование утиной типизацией? Существуют ли вообще языки с динамической типизацией, которые нельзя отнести к категории «утино-типизированные»?

Постскриптум:

Как кто-то назвал daydreamdrunk на reddit.com, поэтому красноречиво put-it "Если он компилируется как утка и звенит как утка ..."

Пост-постскриптум

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


person Community    schedule 22.12.2009    source источник
comment
Просто любопытно, что случилось с псевдотэгами, основанными на заголовках, которые появляются в последнее время?   -  person aehiilrs    schedule 22.12.2009
comment
Я пометил это как [CW], потому что обнаружил, что не всегда достаточно очевидно, что что-то является вики сообщества. Иногда я усердно работаю, чтобы ответить на вопросы, но не замечаю, что это CW, не получаю бонуса репутации (называйте меня репутационной шлюхой, если хотите). Я подумал, что помечу заголовок, чтобы сделать его очевидным для любых возможных ответов, что да, я считаю это субъективным, несколько открытым, но в то же время с моей стороны это не захват репутации.   -  person cdiggins    schedule 22.12.2009
comment
Ааа, в этом есть смысл. Спасибо!   -  person aehiilrs    schedule 22.12.2009
comment
Похоже, утверждение о том, что утиная печать должна быть динамической, не полностью исчезло из Википедии - см. ru .wikipedia.org / wiki /   -  person Brilliand    schedule 17.04.2014


Ответы (8)


Шаблоны C ++ и D - прекрасный пример нединамической утиной печати. Это определенно:

типизация, при которой текущий набор методов и свойств объекта определяет допустимую семантику, а не его наследование от определенного класса или реализации определенного интерфейса.

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

person Community    schedule 22.12.2009
comment
Структурная типизация - это термин, который лучше всего выражает эту тему. См. Функцию структурной типизации Gosu: gosu-lang. github.io/2014/04/22/structural-types-in-gosu.html - person Scott; 20.02.2016

Система структурного типа

Система структурных типов сравнивает один полный тип с другим целым типом, чтобы определить, совместимы ли они. Чтобы два типа A и B были совместимы, A и B должны иметь одинаковую структуру, то есть все методы на A и B должны иметь одинаковую сигнатуру.

Утка Печатает

Утиная печать рассматривает два типа как эквивалентные для текущей задачи, если они оба могут справиться с этой задачей. Чтобы два типа A и B были эквивалентны фрагменту кода, который хочет записать в файл, A и B оба должны реализовывать метод записи.

Резюме

Системы структурных типов сравнивают каждую сигнатуру метода (всю структуру). Утиная печать сравнивает методы, относящиеся к конкретной задаче (структура, относящаяся к задаче).

person Community    schedule 22.12.2009
comment
Это определенно ясное объяснение того, что кажется общепринятой мудростью, и той, которую использует Википедия. Однако я все еще сомневаюсь в этом определении. Каждый язык с динамической типизацией удовлетворяет требованиям "утка", так почему бы не использовать исходный термин, динамически типизированный для этих языков, и не использовать "утк-типизацию", чтобы охватить их плюс структурное подтипирование. В противном случае, если у вас есть структурные подтипы в вашем языке, что для большинства программистов фактически то же самое, что утиная типизация, с добавлением сбивающего с толку имени. в моем затруднительном положении есть какой-то смысл? - person cdiggins; 22.12.2009
comment
Динамическая типизация описывает нечто совершенно иное. Язык с динамической типизацией все еще может быть строго типизированным. Конечно, переменная foo может быть либо объектом Teacher, либо объектом Convict, но во время выполнения тип foo может быть определенно известен. Утиный ввод описывает поведение объекта. foo может быть либо Teacher, либо Convict, но меня это не волнует, пока foo может sing(carol). Динамическая типизация означает, что мы знаем тип объекта во время выполнения; Утиная печать означает, что нас волнует только то, может ли объект вести себя определенным образом. - person Wesley; 24.12.2009
comment
Мне очень понравился этот пост, а также ваш комментарий. Хотел бы я дать ему больше одного голоса. - person Nawaz; 02.01.2011
comment
Ваше описание структурной типизации совершенно неверно для OCaml. let foo bar = bar#baz 1 подразумевает тип val foo: <baz : int -> 'a; .. > -> 'a, что означает, что он может иметь дополнительные методы, пока существует метод baz, который принимает int. Таким образом, применимо и к поставленной задаче. (Однако я не утверждаю, что говорю от имени ST, найденного в Scala). - person new123456; 13.12.2012

Утиный ввод означает Если он подходит, все в порядке

Это относится как к динамически типизированным

def foo obj
    obj.quak()
end

или статически типизированные, скомпилированные языки

template <typename T>
void foo(T& obj) {
    obj.quak();
}

Дело в том, что в обоих примерах не было никакой информации о приведенном типе. Просто при использовании (во время выполнения или во время компиляции!) Типы проверяются, и, если все требования выполнены, код работает. Значения не имеют явного типа в момент объявления.

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

Структурно типизированный код (в стиле Scala) для приведенного выше примера будет выглядеть так:

def foo(obj : { def quak() : Unit }) {
    obj.quak()
}

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

person Community    schedule 22.12.2009
comment
Пример Scala хорошо иллюстрирует, что такое структурная типизация. Также обратите внимание, что при утином вводе, если у вас есть if-ветка, объекту нужны только методы, используемые в одной или другой ветке. При структурной типизации тип объекта должен включать все методы, которые функция может вызывать. - person Chuck; 22.12.2009
comment
Мне нравится предложенное вами определение, но откуда оно взялось? Вы только что определились с этим, или есть какой-нибудь авторитетный источник, который я могу использовать? - person cdiggins; 22.12.2009

Я не уверен, действительно ли он отвечает на ваш вопрос, но ...

Шаблонный код C ++ очень похож на утиную типизацию, но является статическим, структурным во время компиляции.

template<typename T>
struct Test
{
    void op(T& t)
    {
        t.set(t.get() + t.alpha() - t.omega(t, t.inverse()));
    }
};
person Community    schedule 22.12.2009

Насколько я понимаю, структурная типизация используется модулями вывода типов и т. П. Для определения информации о типе (подумайте о Haskell или OCaml), в то время как утиная типизация не заботится о «типах» как таковых, просто эта вещь может обрабатывать вызов определенного метода / доступ к свойствам и т. д. (подумайте о respond_to? в Ruby или о проверке возможностей в Javascript).

person Community    schedule 22.12.2009

Всегда будут примеры из некоторых языков программирования, которые нарушают некоторые определения различных терминов. Например, ActionScript поддерживает программирование в стиле «утка» для экземпляров, которые технически не являются динамическими.

var x:Object = new SomeClass();
if ("begin" in x) {
    x.begin();
}

В этом случае мы проверили, есть ли у экземпляра объекта в "x" метод "begin" перед его вызовом вместо использования интерфейса. Это работает в ActionScript и в значительной степени похоже на утиную типизацию, хотя класс SomeClass () сам по себе не может быть динамическим.

person Community    schedule 22.12.2009

Существуют ситуации, в которых динамическая типизация утки и аналогичный код со статической типизацией (например, C ++) ведут себя по-разному:

template <typename T>
void foo(T& obj) {
    if(obj.isAlive()) {
        obj.quak();
    }
}

В C ++ объект должен иметь методы isAlive и quak для компиляции кода; для эквивалентного кода на языках с динамической типизацией объект должен иметь метод quak только в том случае, если isAlive() возвращает значение true. Я интерпретирую это как разницу между структурой (структурная типизация) и поведением (утиная типизация).

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

person Community    schedule 17.04.2014

Я считаю «утиную типизацию» больше стилем программирования, тогда как «структурная типизация» - это особенность системы типов.

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

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

Так что я мог использовать структурные типы для кодирования в стиле «утка», формально объявив свои «утиные типы» как структурные типы. Но я мог бы также использовать структурные типы без "утиного ввода". Например, если я пишу интерфейсы для множества связанных функций / методов / процедур / предикатов / классов / чего угодно, объявляя и называя общий структурный тип, а затем использую его повсюду, весьма вероятно, что некоторые из модулей кода не нуждаются в все функции структурного типа, поэтому я без необходимости ограничил некоторые из них, чтобы они отклоняли значения, с которыми они теоретически могли бы работать правильно.

Итак, хотя я вижу, что есть точки соприкосновения, я не думаю, что утиная типизация подразумевает структурную типизацию. Я думаю о них, утиная типизация - это даже не то, что можно было бы отнести к структурной типизации, потому что это разные вещи. Думая о утиной типизации в динамических языках как о «неявных, непроверенных структурных типах», что-то упускает, ИМХО. Утиная печать - это стиль программирования, который вы решаете использовать или нет, а не просто техническая особенность языка программирования.

Например, в Python можно использовать isinstance проверки для имитации ограничений типа «класс или подкласс» в стиле объектно-ориентированного программирования. Также можно проверить определенные атрибуты и методы, подделать ограничения структурного типа (вы даже можете поместить проверки во внешнюю функцию, таким образом эффективно получив именованный структурный тип!). Я бы сказал, что ни один из этих вариантов не иллюстрирует утиную типизацию (если только структурные типы не достаточно мелкозернистые и не синхронизируются с проверяемым им кодом).

person Community    schedule 24.04.2014