AndrewVK,
> E> Если duck typing встраивается в статически типизированный язык, то получаем те же самые проверки. > > Нет, не получаем, потому что нет формального контракта, связанного с сигнатурой. Совпадение сигнатуры еще ничего не означает. А если мы такой формальный контракт введем, то получим интерфейсы — вид сбоку.
Если речь идет о concepts, то совсем не интерфейсы в смысле C++/C#/Java: указать, что данный тип удовлетворяет заданным ограничениям можно при использовании типа, а не при его определении.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
eao197,
> AVK>Т.е. то, что реальный софт пишут команды, ты в своей оценке не учитываешь? > > Блин, да я же не агитирую всех за тотальное использование duck typing-а. Я хочу понять границы его применимости. > Командная разработка, действительно, вряд ли выиграет от использования duck typing-а. Это очень серьезный минус для duck typing-а.
Зависит от конкретной команды и конкретной задачи. Structural/Latent/Duck typing -- инструмент, вполне полезный и при командной разработке. Использование Smalltalk, Lisp и шаблонов C++ вполне это подтверждает.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
>> Нет, не получаем, потому что нет формального контракта, связанного с сигнатурой. Совпадение сигнатуры еще ничего не означает. А если мы такой формальный контракт введем, то получим интерфейсы — вид сбоку.
ПК>Если речь идет о concepts, то совсем не интерфейсы в смысле C++/C#/Java: указать, что данный тип удовлетворяет заданным ограничениям можно при использовании типа, а не при его определении.
А казалось бы, при чем тут С++?
Нет, речь не о concepts
... << RSDN@Home 1.2.0 alpha rev. 615 on Windows XP 5.1.2600.131072>>
Здравствуйте, Павел Кузнецов, Вы писали:
>> AVK>Т.е. то, что реальный софт пишут команды, ты в своей оценке не учитываешь? >> >> Блин, да я же не агитирую всех за тотальное использование duck typing-а. Я хочу понять границы его применимости. >> Командная разработка, действительно, вряд ли выиграет от использования duck typing-а. Это очень серьезный минус для duck typing-а.
ПК>Зависит от конкретной команды и конкретной задачи. Structural/Latent/Duck typing -- инструмент, вполне полезный и при командной разработке. Использование Smalltalk, Lisp и шаблонов C++ вполне это подтверждает.
Согласен. Но здесь мы с AndrewVK говорили, как мне кажется, о среднестатистических командах.
Кстати, о конкретных командах и конкретных задачах подтвердает и то, что многие проекты на этих языках делаются очень небольшими, сплоченными коллективами, или вообще одиночками.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Зверёк Харьковский, Вы писали:
ЗХ>здесь возникает философский вопрос: а кто должен знать нужный способ? Мне (пока) наиболее изящным и, скажем так, прямым решением кажется концепция traits: ЗХ>
ЗХ>Здесь и интерфейс stream не раздувается, но и решение принимается "тем, кто знает как решать". ЗХ>Грубо говоря, если появится еще один тип потока (предположенный мной), у которого есть функция seek, но смысл ее другой, а сдвигаться вперед надо функцией move — то нужно всего лишь описать traits для типа этого потока, не меняя клиентский код.
А может проще дать пользователю библиотеки просто функцию передать в качестве параметра? Будет в принципе тот же traits:
и никаких расширений языка не потребуется.
В общем, если интерфейс заранее известен, то просто ползуемся ООП. Если нет, то применяем функциональный подход. В итоге все красиво, быстро и без утиных историй.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, eao197, Вы писали:
E>Совсем не точка. Мы с AndrewVK говорили об объектах, которые поддерживают несколько интерфейсов. В частности, чемодан поддерживает: "контейнер для ручной клади", "хранилище хлама", "подставка". Речь шла о том, что если чемодан как подставку использовать для не подходящей вещи, то он сломается, а мы поимеем проблемы. На что я возразил, что интерфейс "подставка", реализованный СтекляннымЖурнальнымСтоликом для того же самого телефизора так же не подойдет, получится исключения. Поэтому все compile-time проверки в этом случае идут лесом.
Прекратите аналогии с реальным миром. Ну, право же демагогия да и только.
Понимаш ли. С нормальными интерфейсами есть две проблемы. Одна психологическая. Другая структураная (сажем так).
Структурная вызвана тем, что иногда бывает, так что объект ссылку на который нужно передать в некий метод неудается туда передать в виду того, что его разработчик не предусмотрел у него нужный интерфейс. Скорее всего нужный интерфейс есть, но его проектировшик видел его несколько иначе нежели чем ользователь. Так же бывает, когда два проектировщика создали два, возможно даже одинаковых, интерфейса предназначенных для одного и того же. Если все это дело происходит в рамках одного проекта (а это очень частая ситауция, так как промышленные библиотеки и фрэймворки обычно проектируются тщательнее и раньше, а как раз "свои" более безолаберно), то можно просто сделать рефакторинг устраня тем самым откровенный косяк в проектировании. Целью рефакторинга будет удаление одно из интерфейсов и замена его на второй. Если же объкт все же находится в чужой бибилиотеке, то можно воспользваться одним из паттернов проектирования (не даром они для ООП и разрабатывались) и создать, к примеру, объект-обертку хранящую в себе ссылку на нужный объект и преобразующую его интерфейс в требуемый для фунции.
Психологическая связана с тем, что все эти рефакторинги и создание оберток геморойны, а обертки еще и скорость могут понизить. Причем забавно, что многих как раз рефакторин не так пугает, как гипотетические тормоза.
Так вот, боязнь рефакторинга при наличии средств вроде IDEA/ReSharper/VS2005 — это просто от серости и лени. Выигрыш тут несравнимо больший чем затрачиваемые усилия. Заключается он в грамотном дизайне приложения. А это, в свою очередь, дает простоту отладки и развития проекта.
С производительностью хуже. Но тут есть два "но". Превое — это то что она по большому счету должна решаться улучшеием компилятора. Так лишние объекты и виртуальные вызовы методов локальных объектов (объектов которые используются только в локалном контексте, например, в одном стэкфрэйме или ссылка на которые находится только в одной переменной и можно вычислить, что эта перменная не меняется в процессе работы приложения) могут попросту устраняться оптимизирующими компиляторами. У джита и преджита есть все шансы определить локальность перменных. Второе — только в довольно редких местах такие промежуточные объекты (и другие решения на базе паттернов проектирования) ощутимо влияют на производительность прилоежния. Их можно отловить с помощью профайлера и уже на конечных этапах разрабокти переписать оптимально журтувя при этом качеством кода. Зато общий дизайн приложения будет куда лучше.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Если речь идет о concepts, то совсем не интерфейсы в смысле C++/C#/Java: указать, что данный тип удовлетворяет заданным ограничениям можно при использовании типа, а не при его определении.
Паш, concepts вводятся в С++ (если конечно вводятся), чтобы уменьшить последствия утиной типизации присутствующей в шаблонах сегодня. Причем средство это не обязательное, и когда все осознают его необходимость баАальшой вопрос.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
E>ООП базируется на трех китах: инкапсуляция, наследование и полиморфизм.
От именно. И добиваясь полиморфности так где не надо ты ломашь не только принцип наследования, но и инкапсуляции, так как допускаешь обращение к данным в обход контракта класса.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
>> Исторически статическая типизаия использовалась как способ дать компилятору подскази для построения эффективного кода. Например, С++ компилятор, строит vtbl для класса размером не на все возможные (в системе) сообщения, а только на определенные в этом классе. В Smalltalk, например, такой оптимизации не делается. По этому если Smalltalk объект получает "непонятное" для него сообщение, то он кидает исключение, а C++ объект начинает вести себя непредсказуемым образом (что почти всегда приводит к GPF, а иногда к порче данных или странному поведению).
ПК>Можно пояснить мысль поподробнее относительно того, что ты понимаешь под передачей объекту C++ "непонятного" для него сообщения?
Наверно нечто вроде:
int i = 0;
double* pd = (double*)&i;
*pd = 1.3;
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
AVK>В С# 3.0 duck typing в нескольких местах есть. Например сокращенная инициализация массива: AVK>
AVK>IList<Bird> birds = new List<Bird> {penguin, eagle, hedgehog};
AVK>
AVK>Преобразуется компилятором в код: AVK>
AVK>List<Bird> l = new List<Bird>();
AVK>l.Add(penguin);
AVK>l.Add(eagle);
AVK>l.Add(hedgehog);
AVK>IList<Bird> birds = l;
AVK>
AVK>Так вот, метод Add подцепляется через тот самый duck typing. Почему так? Очень просто. С одной стороны нельзя привязываться к конкретным существующим интерфейсам, потому что фича сверхуниверсальная, с другой нельзя вводить свой, потому что тогда существующие коллекции не будут работать, с третьей стороны необходимо поддержать extension methods, которые принципиально не могут реализовывать интерфейсы. Но это мера вынужденная, а не некий универсальный принцип.
Серьезно? А мужики то и не знают поди. Я вот тоже попробовал написать вот так:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
A a = new A { 1, 2, 3 };
}
}
class A
{
public void Add(int item)
{
Console.WriteLine(item);
}
}
И мне рассказали, что:
Program.cs(8,20): error CS1801: The member initializer does not have an identifiable name
CSC : fatal error CS0001: Internal compiler error (0x80004005)
Program.cs(8,23): error CS1801: The member initializer does not have an identifiable name
CSC : fatal error CS0001: Internal compiler error (0x80004005)
Done building project "LINQConsoleApplication1.csproj" -- FAILED.
========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========
А вот когда интерфейсик ICollection<int> реализовал:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
A a = new A { 1, 2, 3 };
}
}
class A : ICollection<int>
{
#region ICollection<int> Members
public void Add(int item)
{
Console.WriteLine(item);
}
public void Clear()
{
throw new Exception("The method or operation is not implemented.");
}
public bool Contains(int item)
{
throw new Exception("The method or operation is not implemented.");
}
public void CopyTo(int[] array, int arrayIndex)
{
throw new Exception("The method or operation is not implemented.");
}
public int Count
{
get { throw new Exception("The method or operation is not implemented."); }
}
public bool IsReadOnly
{
get { throw new Exception("The method or operation is not implemented."); }
}
public bool Remove(int item)
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region IEnumerable<int> Members
public IEnumerator<int> GetEnumerator()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
}
...то сразу дали:
1
2
3
Доктор! Что я делаю не так?
Короче, слава богу такой фигни как утиные истории в шарпе все же стараются избегать.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Program.cs(8,15): error CS0117: 'A' does not contain a definition for 'Add'
Program.cs(8,15): error CS0117: 'A' does not contain a definition for 'Add'
Program.cs(8,15): error CS0117: 'A' does not contain a definition for 'Add'
Done building project "LINQConsoleApplication1.csproj" -- FAILED.
========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========
В общем, явно сырая альфа. И не туда, и не сюда. Без интерфйса жить не хотя, но интерфейс тоже не понимют.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Возможно, это и правильно, что конструктор колекции требует публичного метода Add реализующего ICollection<T>.Add(T).
Если метод ICollection<T>.Add(T) скрыт, велика вероятность того, что колекция не допускает модификации.
Если бы привязка шла к явной реализации интерфейса, результат выполнения
var carvedinstone = new ReadOnlyCollection { 1, 2, 3 };
Здравствуйте, VladD2, Вы писали:
VD>А может проще дать пользователю библиотеки просто функцию передать в качестве параметра? Будет в принципе тот же traits: VD>
Нет, в этом случае пользователю load_header_and_data нужно знать о том, что внутри используется skip_data. А от этого пользователя load_header_and_data хотелось бы избавить -- это не его проблемы. Так что вариант с утиными историями или traits-ами гораздо удобнее.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Нет, в этом случае пользователю load_header_and_data нужно знать о том, что внутри используется skip_data. А от этого пользователя load_header_and_data хотелось бы избавить -- это не его проблемы. Так что вариант с утиными историями или traits-ами гораздо удобнее.
Ему и так нужно знать. Только тут хотя бы он может задать то что хочет, а не полагаться на соотвествие имен.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
не "ничего не делает", а проверяет соответствие аргументов шаблона некоторым требованиям. И да, такой код вполне согласуется с понятиями хорошего стиля более, чем у одной команды. Для меня лично польза правил, запрещающих писать код, помогающий отлавливать ошибки на более ранних стадиях, весьма сомнительна.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
eao197,
> ПК> Зависит от конкретной команды и конкретной задачи. Structural/Latent/Duck typing -- инструмент, вполне полезный и при командной разработке. Использование Smalltalk, Lisp и шаблонов C++ вполне это подтверждает.
> Согласен. Но здесь мы с AndrewVK говорили, как мне кажется, о среднестатистических командах.
Средняя температура по больнице?
> Кстати, о конкретных командах и конкретных задачах подтвердает и то, что многие проекты на этих языках делаются очень небольшими, сплоченными коллективами, или вообще одиночками.
Имхо, очень по-разному... Во всяком случае, применительно к Си++ уж точно. О Smalltalk, Python, Ruby, Lisp etc. мне говорить сложно: в командной работе на этих языках я не участвовал.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен