Re[20]: «Собаку съел»
От: alex_public  
Дата: 25.01.17 13:18
Оценка: +1
Здравствуйте, samius, Вы писали:

_>>Ууу) Ты всё же решился свернуть на эту холиварную тему. Вопрос о сути шаблонов C++ уже давно является известной темой для споров. И на этом форуме и на других известных. Повторять все эти потоки флейма нет никакого желания — это всё можно найти на форуме самостоятельно. Так что просто выскажу своё итоговое мнение по данному вопросу, в сравнение с тем же Хаскелем:

S>Прости, но твое итоговое мнение основано на какой именно классификации?

Моё мнение основано на:
— знание определения понятия "параметрический полиморфизм" и целей его возникновения
— знание всех деталей работы шаблонов C++
— знание устройства полиморфизма в Хаскеле (для сравнения), ну и кстати дженериков в Java/C# (это разве для того чтобы посмеяться, т.к. самая убогая реализация из всех упомянутых) тоже.

Этого более чем достаточно для подобных выводов.

_>>Основная цель всего этого механизма в том, чтобы облегчить работу программиста, позволив ему писать один код для всех случаев. Шаблоны из C++ это полностью реализуют. А с учётом ещё и вопроса производительности данное решение выглядит на голову лучше всех остальных реализаций. Ценой же этого (ну никогда не бывает идеала и у всех мощных технологий есть обратная сторона) являются большие сложности с введением в язык модулей.

S>Ну причем тут производительность? Каким образом производительность C++ влияет на классификацию?

А я ни про какие классификации здесь ничего и не говорил. Здесь я высказал своё оценочное суждение, о том что подход C++ (удобство и быстродействие в обмен на модульность) к решению данной проблемы является самым эффективным. Полезнее на практике подхода Хаскеля (удобство и модульность в обмен на быстродействие) и на голову лучше всяких убогих дженериков (где нет ни удобства, ни быстродействия).

S>>>Что значит "для многих типов"? Формально нужна работа для всех типов.

_>>С чего бы это? Откуда такое бредовое требование? Да ещё и формальное... )))
S>Я думаю что к нему можно прийти отсюда:
S>

S>Parametric polymorphism, the topic of this chapter, allows a single piece of code to be typed “generically,” using variables in place of actual types, and then instantiated with particular types as needed. Parametric definitions are uniform: all of their instances behave the same.

S>TAPL


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

S>А откуда требование "для многих"?


Из определения понятия "полиморфизм". )))

_>>Т.е. если я напишу на Хаскеле функцию f вида "f a = xrmbrm a", то она по твоему обязательно будет работать для всех типов? )))

S>может быть и для всех, если у нас "xrmbrm = id"
S>а может и не для всех. Она возьмет ограничения из определения xrmbrm

Совершенно верно. И какую ты тут видишь разницу со случаем equal_to (заменяем его на f, а оператор равенства на xrmbrm)?

_>>>>И так, подводя итоги:

_>>>>1. equal_to — компаратор.
_>>>>2. работает с разными типами — полиморфный.
_>>>>3. имеет одну реализацию для всех типов — параметрический.
S>>>пожалуй, я найду тип, для которого стандартная реализация не работает. Точнее, мешает скомпилироваать проект.
_>>И? ) Это как-то влияет на аргументацию? )
S>что именно здесь не очевидно? если найдется тип, для которого equal_to требует специального уточнения (в исходниках), то это ad hoc (как минимум на уровне исходников), если ты предлагаешь подразделять полиморфизм исходников от полиморфизма исполняемого кода.

Ты похоже чего-то не понял. Ещё раз повторяю, стандартный equal_to (без всяких дополнительных специализаций) работает с любым типом, для которого определён оператор равенства. Из этого следует:

1. Что это параметрический полиморфизм (требования на работу со всеми возможными типами (включая не имеющие оператора равенства) — это лично твоё изобретение и не имеет ничего общего к действительности).
2. Если мы захотим, чтобы equal_to заработал с каким-то нашим новым типом, то мы просто добавим ему этот самый оператор равенства (а не пойдём добавлять специализации для equal_to) и стандартный equal_to мгновенно это подхватит и заработает и с этим типом. Так что при желание без проблем делается так, что equal_to будет работать со всеми типами в проекте, только на практике это обычно просто не нужно (глупо говорить например об операторе равенства для "класса приложения", так же как и глупо думать о манипуляциях с ним в контейнерах).
Re[12]: «Собаку съел»
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.01.17 13:19
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, samius, Вы писали:


S>>>> И чем тебе не нравится?

S>>>> Инлайнинг в рантайме!
S>>>Да все нравится, но где же обещаный инлайниг параметрически полиморфного компаратора?


S>> А это что?


S>>
S>>public static IEnumerable<T> Compose<T, Y>(this IEnumerable<T> src, Expression<Func<T, Y>> propertyExpression, Expression<Func<Y, bool>> func)
S>>        {
S>>            return src.Where(Expression.Lambda<Func<T, bool>>(Expression.Invoke(func, propertyExpression.Body), propertyExpression.Parameters).Compile());
S>>        }
S>>


S>Без понятия. Точнее — это код. Но какое отношение он имеет к инлайнингу параметрически полиморфного компаратора — я все еще пытаюсь выяснить. Даже с учетом того что Func<Y, bool> можно заменить на Func<Y, Y, bool>, все равно не натягивается.


Дело в том, что внутри Expression.Lambda<Func<T, bool>>(Expression.Invoke(func, propertyExpression.Body), propertyExpression.Parameters)
деревья и разворачиваются.
Динамическое построение Linq запроса

public static IQueryable<T> Beetwen<T>(this IQueryable<T> src, string field, DateTime start, DateTime stop) where T: BaseEntity
{
    var p = Expression.Parameter(typeof(T)); // Param_0
    var prop = Expression.PropertyOrField(p, field); //Param_0.field
    var startExpr = Expression.Constant(start);
    var stopExpr = Expression.Constant(stop);

    var firstCondition = Expression.GreaterThanOrEqual(prop, startExpr); // Param_0.field >= start
    var secondCondition = Expression.LessThanOrEqual(prop, stopExpr); // Param_0.field <= stop

    var fullExpression = Expression.AndAlso(firstCondition, secondCondition); // Param_0.field >= start && Param_0.field <= stop

    var func = Expression.Lambda<Func<T,bool>>(fullExpression,p); // Param_0 => Param_0.field >= start && Param_0.field <= stop

    return src.Where(func);
}


 var firstCondition = Expression.GreaterThanOrEqual(prop, startExpr); // Param_0.field >= start
    var secondCondition = Expression.LessThanOrEqual(prop, stopExpr); // Param_0.field <= stop



Применяется именно к T
https://msdn.microsoft.com/ru-ru/library/bb356438(v=vs.110).aspx

The following rules determine the implementing method for the operation:
If the Type property of either left or right represents a user-defined type that overloads the "greater than" operator, the MethodInfo that represents that method is the implementing method.
Otherwise, if left.Type and right.Type are numeric types, the implementing method is null.



Опять же по аналогии с шаблонами для пользовательских функций нужно реализовать перегрузку метода
и солнце б утром не вставало, когда бы не было меня
Re[19]: Бинарная склейка
От: alex_public  
Дата: 25.01.17 13:34
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Подожди. Для меня как автора библиотеки полученный lib-файл — и есть конечный бинарный образ. Дальше я его поставляю прикладному программисту, а он уже линкует. И указанный lib-файл пухнет. Я не вижу тут проявления упомянутого «это позволяет бороться с распуханием кода после применения шаблонов».


Минимизация lib файлов? ) Это конечно весьма забавная идея. Только вот есть один нюанс — она полностью противоречит текущему направлению развития в оптимизации (посмотри например такие вещи как LTO, PGO и т.п.).

Q>То, что такая оптимизация существует, я не спорю. Только я очень скептически отношусь к тому, что она хоть сколь-нибудь заметно влияет на code bloat. В /cpp.applied как раз недавно обсуждение было на примере OpenCV, где с распуханием борятся ручным стиранием типов, не возлагая надежд на «бинарную склейку»: http://rsdn.org/forum/cpp.applied/6676361
Автор: jazzer
Дата: 24.01.17


Вот не стоит выдавать чьи-то предположения за истину. В OpenCV всё гораздо проще, если взглянуть на историю её развития и C-ый интерфейс.
Re[19]: «Собаку съел»
От: alex_public  
Дата: 25.01.17 13:38
Оценка: +2
Здравствуйте, Sinix, Вы писали:

S>Ну да, это чисто обзорный пост. Смысл — наличие нескольких pipelines (llillc (llvm); il2cpp от unity; RyuJit AOT; .net native), которые можно будет использовать для трансляции в натив. Понятно, что в финал пройдут не все, но наличие запасных радует.

S>Про перенос на взрослый .net — сейчас .core становится портом части библиотек дотнета под все платформы, а не форком, как изначально задумано. Т.е. c обратным переносом дела всё легче и легче обстоят.
S>Про перевод на нативные рельсы всего и сразу — не будет в обозримом будущем, ибо совместимость. Будет opt-in поведение: хочешь полноценный рантайм — вот тебе рантайм. Готов смириться с некоторыми ограничениями — вот тебе оптимизированный бинарник.

А ну вот приблизительно так я себе это и представлял. Просто из твоей фразы про "подождать когда .native станет доступен в других версиях .net" мне показалось утверждение о планах перевода "большого .net" на эту технологию, что показалось мне уж слишком революционным. )))
Re[20]: Бинарная склейка
От: Qbit86 Кипр
Дата: 25.01.17 13:55
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Минимизация lib файлов? ) Это конечно весьма забавная идея. :))) Только вот есть один нюанс — она полностью противоречит текущему направлению развития в оптимизации (посмотри например такие вещи как LTO, PGO и т.п.).


Хорошо, а что если lib-файл — не статическая библиотека, а библиотека импорта динамической библиотеки? Бинарный код-то уже есть в dll, он раздут и никуда оттуда не денется при линковке exe-шника конечного пользователя с соответствующей lib-прослойкой.
Глаза у меня добрые, но рубашка — смирительная!
Re[21]: Бинарная склейка
От: alex_public  
Дата: 25.01.17 14:17
Оценка:
Здравствуйте, Qbit86, Вы писали:

_>>Минимизация lib файлов? ) Это конечно весьма забавная идея. Только вот есть один нюанс — она полностью противоречит текущему направлению развития в оптимизации (посмотри например такие вещи как LTO, PGO и т.п.).

Q>Хорошо, а что если lib-файл — не статическая библиотека, а библиотека импорта динамической библиотеки? Бинарный код-то уже есть в dll, он раздут и никуда оттуда не денется при линковке exe-шника конечного пользователя с соответствующей lib-прослойкой.

Нет, dll — это отдельный конечный модуль и для него применяются все конечные оптимизации, так что никаких раздуваний не будет. Единственная разница со статической линковкой в том, что не сработают оптимизации (ни обсуждаемая, ни LTO) между кодом библиотеки и приложения (а они могут быть весьма существенными). Более того, если например использовать dll, но при этом делать статическую линковку стандартной библиотеки (довольно распространённое явление), то мы получим значительное дублирование кода в dll и exe. Но это как бы очевидная цена за возможность динамического подключения.
Re[20]: «Собаку съел»
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.01.17 14:19
Оценка:
Здравствуйте, alex_public, Вы писали:

_>А ну вот приблизительно так я себе это и представлял. Просто из твоей фразы про "подождать когда .native станет доступен в других версиях .net" мне показалось утверждение о планах перевода "большого .net" на эту технологию, что показалось мне уж слишком революционным. )))


А большой .Net и не пейдет. Ибо

https://msdn.microsoft.com/ru-ru/magazine/mt590967.aspx

Наконец, .NET Core — это нижележащая инфраструктура, от которой зависит .NET Native. Когда проектировали .NET Native, стало понятно, что .NET Framework не подойдет в качестве фундамента для библиотек классов этой инфраструктуры. Дело в том, что .NET Native статически связывает инфраструктуру с приложением, а затем удаляет все лишнее, что не нужно приложению. (Здесь я сильно упрощаю общую картину, но идею вы уловили. Подробнее на эту тему см. «Inside .NET Native» по ссылке bit.ly/1UR7ChW.)

Традиционная реализация .NET Framework не предусматривает разбиения на модули, поэтому компоновщик (linker) не может включить в приложение лишь ту часть инфраструктуры, которая нужна приложению. Но .NET Core, по сути, является ответвлением .NET Framework, реализация которой оптимизирована с учетом модульности. Другое преимущество этой реализации — возможность поставлять .NET Core Framework как набор NuGet-пакетов, что позволяет вам обновлять индивидуальные классы вне самой .NET Framework. Однако, прежде чем двигаться дальше, давайте обсудим изменения в NuGet.


Но с развитием NetStandard может конечно и поменяться. Но до этого далеко, или большой .Net так и сдохнет ибо для MS интересна Win 10 и UWP
и солнце б утром не вставало, когда бы не было меня
Re[22]: Бинарная склейка
От: Qbit86 Кипр
Дата: 25.01.17 14:36
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Нет, dll — это отдельный конечный модуль и для него применяются все конечные оптимизации, так что никаких раздуваний не будет.


Как это не будет, если будет. Для всех явных инстанцирований класса внутри dll, кроме некоторых искусственно подобранных примеров вроде std::int32_t/boost::float32_t или каких-нибудь тривиальных функций.
Глаза у меня добрые, но рубашка — смирительная!
Re[14]: «Собаку съел»
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.01.17 14:37
Оценка:
Здравствуйте, vdimas, Вы писали:



V>Я даже уверен, V>Вот как раз из-за топорности системы типов VM нифига так и не случилось.

VM это, что?

Рефлексия и прочие вещи это как раз фичи.
Это сплав динамических языков и статической типизации.
В большинстве скорости хватает.
V>15 лет прошло уже... Дотнет набрал неимоверный вес и инерцию.
V>И при этом активно ПЕРЕДЕЛЫВАЕТСЯ прямо сейчас.
V>Сколько это еще займёт лет, как думаешь?

V>Думаю, еще десяток лет запросто, пока не откажутся окончательно от современной модели VM. Текущую парадигму исполнения VM в лучшем случае оставят как эмулируемую для совместимости.

Так сейчас создается новый .Net Core. Он уже вполне работоспособен. Это и UWP, и Xamarin с выходом NetStandart практически заменят ДотНет
и солнце б утром не вставало, когда бы не было меня
Re[23]: Бинарная склейка
От: alex_public  
Дата: 25.01.17 14:51
Оценка:
Здравствуйте, Qbit86, Вы писали:

_>>Нет, dll — это отдельный конечный модуль и для него применяются все конечные оптимизации, так что никаких раздуваний не будет.

Q>Как это не будет, если будет. Для всех явных инстанцирований класса внутри dll, кроме некоторых искусственно подобранных примеров вроде std::int32_t/boost::float32_t или каких-нибудь тривиальных функций.

Я имел в виду, что при создание dll не будет раздуваний больше, чем при компиляции обычного ехе. В то время как при создание статических lib файлов не просто отсутствуют некоторые оптимизации, но и частенько дополнительно вставляются целые горы дополнительной информации. Так что обсуждать вопрос минимизации lib файлов — это принципиально смешно. А вот для dll и exe такая тема вполне существует и есть набор оптимизаций в этой области. Насколько они эффективны и востребованы — это другой вопрос. Но замечу, что включение максимальных уровней оптимизации (по быстродействию) или подключение таких вещей как LTO обычно заметно увеличивает объём конечного бинарного файла (инлайн и ещё раз инлайн!) и без всяких шаблонов. Но при этом и заметно увеличивает быстродействие. И для многих приложений предпочтителен именно такой вариант.
Re[21]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 25.01.17 15:40
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, samius, Вы писали:


S>>Прости, но твое итоговое мнение основано на какой именно классификации?


_>Моё мнение основано на:

_>- знание определения понятия "параметрический полиморфизм" и целей его возникновения
Знаю, но никому не скажу, особенно про источник.

_>- знание всех деталей работы шаблонов C++

_>- знание устройства полиморфизма в Хаскеле (для сравнения), ну и кстати дженериков в Java/C# (это разве для того чтобы посмеяться, т.к. самая убогая реализация из всех упомянутых) тоже.

_>Этого более чем достаточно для подобных выводов.

Кому — как. Мне этого не достаточно что бы принять твои выводы.

S>>Ну причем тут производительность? Каким образом производительность C++ влияет на классификацию?


_>А я ни про какие классификации здесь ничего и не говорил. Здесь я высказал своё оценочное суждение, о том что подход C++ (удобство и быстродействие в обмен на модульность) к решению данной проблемы является самым эффективным. Полезнее на практике подхода Хаскеля (удобство и модульность в обмен на быстродействие) и на голову лучше всяких убогих дженериков (где нет ни удобства, ни быстродействия).

А ну раз твое оценочное суждение не является аргументом в выборе классификации... Ну и опустим его.

_>Не вижу в этой цитате ничего даже близкого к требованию обеспечения работы для всех типов. Да его и не могло бы быть (иначе все остальные языки с поддержкой параметрического полиморфизма резко перестали бы ими быть)...

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

S>>А откуда требование "для многих"?


_>Из определения понятия "полиморфизм". )))

Ты боишься что ли привести определение, которое знаешь и которым пользуешься?

_>>>Т.е. если я напишу на Хаскеле функцию f вида "f a = xrmbrm a", то она по твоему обязательно будет работать для всех типов? )))

S>>может быть и для всех, если у нас "xrmbrm = id"
S>>а может и не для всех. Она возьмет ограничения из определения xrmbrm

_>Совершенно верно. И какую ты тут видишь разницу со случаем equal_to (заменяем его на f, а оператор равенства на xrmbrm)?

никакой. Потому и заявляю, что equals_to — ad hoc, т.к. требует специализации чуть ли не для всех типов.

_>Ты похоже чего-то не понял. Ещё раз повторяю, стандартный equal_to (без всяких дополнительных специализаций) работает с любым типом, для которого определён оператор равенства. Из этого следует:

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

_>1. Что это параметрический полиморфизм (требования на работу со всеми возможными типами (включая не имеющие оператора равенства) — это лично твоё изобретение и не имеет ничего общего к действительности).

_>2. Если мы захотим, чтобы equal_to заработал с каким-то нашим новым типом, то мы просто добавим ему этот самый оператор равенства (а не пойдём добавлять специализации для equal_to) и стандартный equal_to мгновенно это подхватит и заработает и с этим типом. Так что при желание без проблем делается так, что equal_to будет работать со всеми типами в проекте, только на практике это обычно просто не нужно (глупо говорить например об операторе равенства для "класса приложения", так же как и глупо думать о манипуляциях с ним в контейнерах).
Re[13]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 25.01.17 16:43
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>Без понятия. Точнее — это код. Но какое отношение он имеет к инлайнингу параметрически полиморфного компаратора — я все еще пытаюсь выяснить. Даже с учетом того что Func<Y, bool> можно заменить на Func<Y, Y, bool>, все равно не натягивается.


S> Дело в том, что внутри Expression.Lambda<Func<T, bool>>(Expression.Invoke(func, propertyExpression.Body), propertyExpression.Parameters)

S>деревья и разворачиваются.
S>Динамическое построение Linq запроса

Благодярю за равернутый пример и ссылку.
S>
S> var firstCondition = Expression.GreaterThanOrEqual(prop, startExpr); // Param_0.field >= start
S>    var secondCondition = Expression.LessThanOrEqual(prop, stopExpr); // Param_0.field <= stop
S>

Однако, строим ли мы дерево вручную, или компилятор его строит, способ вызова оператора сравнения будет одним и тем же. Если, конечо, деревья выражений транслируются в IL. Т.е. никакого инлайнинга по сравнению с написанным в обычном C# коде выражением "field >= start".


S>Применяется именно к T

S>https://msdn.microsoft.com/ru-ru/library/bb356438(v=vs.110).aspx
S>

S>The following rules determine the implementing method for the operation:
S>If the Type property of either left or right represents a user-defined type that overloads the "greater than" operator, the MethodInfo that represents that method is the implementing method.
S>Otherwise, if left.Type and right.Type are numeric types, the implementing method is null.

Согласно классификации, которую я приводил (пока нет другой) я считаю что Expression.GreaterThanOrEqual — ad hoc полиморфно ровно в той степени и том качестве, в котором ad hoc полиморфен оператор >=.

S>Опять же по аналогии с шаблонами для пользовательских функций нужно реализовать перегрузку метода

Верно, никто не утверждает обратного.
Re[22]: «Собаку съел»
От: alex_public  
Дата: 25.01.17 17:02
Оценка:
Здравствуйте, samius, Вы писали:

_>>Моё мнение основано на:

_>>- знание определения понятия "параметрический полиморфизм" и целей его возникновения
S>Знаю, но никому не скажу, особенно про источник.

Вообще то несколько раз уже тут озвучивал. Но если ты так и не смог этого увидеть, то озвучу ещё раз, выделено:

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

Подходит такое или и тут будешь спорить? )

_>>- знание всех деталей работы шаблонов C++

_>>- знание устройства полиморфизма в Хаскеле (для сравнения), ну и кстати дженериков в Java/C# (это разве для того чтобы посмеяться, т.к. самая убогая реализация из всех упомянутых) тоже.
_>>Этого более чем достаточно для подобных выводов.
S>Кому — как. Мне этого не достаточно что бы принять твои выводы.

А про тебя никто и не говорил. Для тебя были представлены соответствующие аргументы.

S>>>Ну причем тут производительность? Каким образом производительность C++ влияет на классификацию?

_>>А я ни про какие классификации здесь ничего и не говорил. Здесь я высказал своё оценочное суждение, о том что подход C++ (удобство и быстродействие в обмен на модульность) к решению данной проблемы является самым эффективным. Полезнее на практике подхода Хаскеля (удобство и модульность в обмен на быстродействие) и на голову лучше всяких убогих дженериков (где нет ни удобства, ни быстродействия).
S>А ну раз твое оценочное суждение не является аргументом в выборе классификации... Ну и опустим его.

Ну например потому, что подобные техники оптимизации ради быстродействия применяют и в ML языках (про которые обычно никто не спорит насчёт наличия параметрического полиморфизма). Загляни например сюда http://mlton.org/References.attachments/060916-mlton.pdf. Особенно мне нравится там один термин, который можно увидеть в заголовке 12-го слайда. Он как раз очень хорошо описывает внутреннюю реализацию шаблонов C++.

_>>Не вижу в этой цитате ничего даже близкого к требованию обеспечения работы для всех типов. Да его и не могло бы быть (иначе все остальные языки с поддержкой параметрического полиморфизма резко перестали бы ими быть)...

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

Давай не будем этой демагогии — тут были вполне конкретные примеры. Если принять твоё бредовое требование о небходимости поддерживать все возможные типы, то резко окажется, что и в Хаскеле нет параметрического полиморфизма.

S>>>А откуда требование "для многих"?

_>>Из определения понятия "полиморфизм". )))
S>Ты боишься что ли привести определение, которое знаешь и которым пользуешься?

Определение чего, слова полиморфизм? ))) А то ведь "многие" (в смысле больше одного) требуется не только для параметрического, а вообще для всех видов. Причём об этом можно догадаться даже не зная прямого значения этого слова, просто по его греческому корню. )))

_>>>>Т.е. если я напишу на Хаскеле функцию f вида "f a = xrmbrm a", то она по твоему обязательно будет работать для всех типов? )))

S>>>может быть и для всех, если у нас "xrmbrm = id"
S>>>а может и не для всех. Она возьмет ограничения из определения xrmbrm
_>>Совершенно верно. И какую ты тут видишь разницу со случаем equal_to (заменяем его на f, а оператор равенства на xrmbrm)?
S>никакой.

Т.е. я правильно тебя понял, что возможность написать в Хаскеле функцию вида "f a = xrmbrm a" является проявлением ad hoc полиморфизма? )))

S>Потому и заявляю, что equals_to — ad hoc, т.к. требует специализации чуть ли не для всех типов.


Ну давай, расскажи, зачем может понадобиться специализация equals_to.
Re[14]: «Собаку съел»
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.01.17 17:14
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, samius, Вы писали:


S>>>Без понятия. Точнее — это код. Но какое отношение он имеет к инлайнингу параметрически полиморфного компаратора — я все еще пытаюсь выяснить. Даже с учетом того что Func<Y, bool> можно заменить на Func<Y, Y, bool>, все равно не натягивается.


S>> Дело в том, что внутри Expression.Lambda<Func<T, bool>>(Expression.Invoke(func, propertyExpression.Body), propertyExpression.Parameters)

S>>деревья и разворачиваются.
S>>Динамическое построение Linq запроса

S>Благодярю за равернутый пример и ссылку.

S>>
S>> var firstCondition = Expression.GreaterThanOrEqual(prop, startExpr); // Param_0.field >= start
S>>    var secondCondition = Expression.LessThanOrEqual(prop, stopExpr); // Param_0.field <= stop
S>>

S>Однако, строим ли мы дерево вручную, или компилятор его строит, способ вызова оператора сравнения будет одним и тем же. Если, конечо, деревья выражений транслируются в IL. Т.е. никакого инлайнинга по сравнению с написанным в обычном C# коде выражением "field >= start".

Конечно транслируются Программирование на C# 5.0

Деревья выражений собираются и компилируются в рантайме.
Мы можем собирать SQl выражение из разных кусочков, но на выходе должны получить один Sql запрос.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 25.01.2017 17:29 Serginio1 . Предыдущая версия .
Re[21]: Границы применения
От: vdimas Россия  
Дата: 25.01.17 18:41
Оценка: :)
Здравствуйте, Qbit86, Вы писали:

V>>А действительно ли тебе требуется объяснение от другого человека, почему так?

Q>Я не спрашивал, почему так. Я просто привёл пример того, как хрупка указанная оптимизация, и сколь узки границы её применения.

Порой не понимаю некоторых коллег, реально...
Ну и зачем ты так сильно подставляешься-то?

Твой пример не поддаётся никакой оптимизации ни на одном языке программирования, даже на самых пригодных (теоретически) к агрессивной редукции — к чистым ФП-языкам. И это настолько тривиально/очевидно, что ни сам твой пример ни даже факт его обсуждения не делает чести ни одному из его участников.

Тем не менее, в реальном приложении полно типов с одинаковым размером, а в достаточно большом приложении существует просто чудовищное количество однообразного бинарного кода, работающего над разными типами, даже если эти типы не шаблонные. Тут не надо семи пядей во лбу, чтобы с полутыка понять принцип этой оптимизации и те самые границы её применимости. Конкретно в случае vector<> достаточен одинаковый размер элементов. А где-то у двух и более произвольных типов будет, скажем, одинаковый доступ и/или операции с неким полем по некоторому одинаковому смещению (сами поля могут быть разных типов, в том числе составных). В общем, подобных вещей может быть ОЧЕНЬ много. Достаточно отключить оптимизацию подобного рода и конечный бинарный образ становится в среднем больше раз в 4-6 (на большинстве наших проектах... так-то я наблюдал и до 10 раз, тут уже как карты лягут).


V>>Этот образ не предназначен для исполнения.

Q>>>Дальше я его поставляю прикладному программисту, а он уже линкует.
V>>В этом месте вся магия и происходит.
Q>По-твоему, когда он слинкует и использует эти инстансы, у него не будет распухания из-за генерации кода, назависимого для каждого из этих инстансов?

По-моему, всё нужное для случая статических библиотек, я уже озвучил:

при включенной опции "link time code generation"

Re[23]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 25.01.17 18:46
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, samius, Вы писали:


S>>Знаю, но никому не скажу, особенно про источник.


_>Вообще то несколько раз уже тут озвучивал. Но если ты так и не смог этого увидеть, то озвучу ещё раз, выделено:


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

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

_>Подходит такое или и тут будешь спорить? )

Не подходит, но спорить не буду.


_>>>- знание всех деталей работы шаблонов C++

_>>>- знание устройства полиморфизма в Хаскеле (для сравнения), ну и кстати дженериков в Java/C# (это разве для того чтобы посмеяться, т.к. самая убогая реализация из всех упомянутых) тоже.
_>>>Этого более чем достаточно для подобных выводов.
S>>Кому — как. Мне этого не достаточно что бы принять твои выводы.

_>А про тебя никто и не говорил. Для тебя были представлены соответствующие аргументы.

Ах, соответствующие?

S>>А ну раз твое оценочное суждение не является аргументом в выборе классификации... Ну и опустим его.


_>Ну например потому, что подобные техники оптимизации ради быстродействия

сорри

_>Давай не будем этой демагогии — тут были вполне конкретные примеры. Если принять твоё бредовое требование о небходимости поддерживать все возможные типы, то резко окажется, что и в Хаскеле нет параметрического полиморфизма.

На счет всех возможных — я, видимо, и правда загнул. Пардон

На самом деле вот как:

Strachey [Strachey 67] distinguished, informally, between two major kinds of polymorphism. Parametric
polymorphism is obtained when a function works uniformly on a range of types: these types normally exhibit
some common structure. Ad-hoc polymorphism is obtained when a function works, or appears to work, on
several different types (which may not exhibit a common structure) and may behave in unrelated ways for each
type.

...

Parametric polymorphism is so called because the uniformity of type structure is normally achieved by type parameters, but uniformity can be achieved in different ways, and this more general concept is called universal polymorphism. Universally polymorphic functions will normally work on an infinite number of types (all the types having a given common structure), while an ad-hoc polymorphic function will only work on a finite set of different and potentially unrelated types. In the case of universal polymorphism, one can assert with confidence that some values (i.e., polymorphic functions) have many types, while in ad-hoc polymorphism this is more difficult to maintain, as one may take the position that an ad-hoc polymorphic function is really a small set of monomorphic functions. In terms of implementation, a universally polymorphic function will execute the same code for arguments of any admissible type, while an ad-hoc polymorphic function may execute different code for each type of argument.

http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.117.695


S>>Ты боишься что ли привести определение, которое знаешь и которым пользуешься?


_>Определение чего, слова полиморфизм? ))) А то ведь "многие" (в смысле больше одного) требуется не только для параметрического, а вообще для всех видов. Причём об этом можно догадаться даже не зная прямого значения этого слова, просто по его греческому корню. )))

см цитату

_>>>Совершенно верно. И какую ты тут видишь разницу со случаем equal_to (заменяем его на f, а оператор равенства на xrmbrm)?

S>>никакой.

_>Т.е. я правильно тебя понял, что возможность написать в Хаскеле функцию вида "f a = xrmbrm a" является проявлением ad hoc полиморфизма? )))

Это зависит от определения функции xrmbrm. Если она параметрически полиморфна, то тем же свойством будет обладать "алиас". Если она выдвигает требования к аргументу (инстанс класса), то ad hoc. А уж если она определена мономорфо — то соответственно f будет мономорфна.

S>>Потому и заявляю, что equals_to — ad hoc, т.к. требует специализации чуть ли не для всех типов.


_>Ну давай, расскажи, зачем может понадобиться специализация equals_to.

Ну я не думаю что для тебя это будет откровением. Например, для того, что бы использовать алгоритмы, нуждающиеся в binary_function для типов, у которых нет оператора сравнения и нет возможности определить его. Или для того, что бы использовать способ сравнения типов отличный, от штатного оператора ==.
Re[15]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 25.01.17 18:50
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>Однако, строим ли мы дерево вручную, или компилятор его строит, способ вызова оператора сравнения будет одним и тем же. Если, конечо, деревья выражений транслируются в IL. Т.е. никакого инлайнинга по сравнению с написанным в обычном C# коде выражением "field >= start".


S> Конечно транслируются Программирование на C# 5.0

Это я уточняю вариант. Т.е. пишу что речь не про SQL или еще что-то там. Т.е. когда деревья транслируются в IL, то способ вызова оператора сравнения невозможно отличить от того что получается при обычной компиляции исходника C#. Именно это я хотел сказать.

S> Деревья выражений собираются и компилируются в рантайме.

S> Мы можем собирать SQl выражение из разных кусочков, но на выходе должны получить один Sql запрос.
Это известно со времен LinqToSQL
Re[22]: «Собаку съел»
От: vdimas Россия  
Дата: 25.01.17 19:06
Оценка:
Здравствуйте, samius, Вы писали:

_>>Совершенно верно. И какую ты тут видишь разницу со случаем equal_to (заменяем его на f, а оператор равенства на xrmbrm)?

S>никакой. Потому и заявляю, что equals_to — ad hoc, т.к. требует специализации чуть ли не для всех типов.

Абсолютно верно. Даже Вики подтверждает:

В ряде исчислений, например, в теории квалифицированных типов, ad hoc полиморфизм рассматривается как частный случай параметрического.

"Унутре" ресолвера типов того же Хаскеля параметрический полиморфизм зачастую превращается в сочетание ad hoc + динамического полиморфизма (на основе таблицы ф-ий для классов типов). Но для программиста всё выглядит как чистейшей воды параметрический полиморфизм. А только эта т.з. для нас, программистов, и важна, ИМХО.
Re[23]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 25.01.17 21:41
Оценка: 1 (1)
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


_>>>Совершенно верно. И какую ты тут видишь разницу со случаем equal_to (заменяем его на f, а оператор равенства на xrmbrm)?

S>>никакой. Потому и заявляю, что equals_to — ad hoc, т.к. требует специализации чуть ли не для всех типов.

V>Абсолютно верно. Даже Вики подтверждает:

V>

V>В ряде исчислений, например, в теории квалифицированных типов, ad hoc полиморфизм рассматривается как частный случай параметрического.

О, если вики включить в перечень доверенных источников, то там можно найти еще и такое:

Язык С++ предоставляет подсистему шаблонов, использование которых внешне похоже на параметрический полиморфизм, но семантически реализуется сочетанием ad hoc-механизмов


V>"Унутре" ресолвера типов того же Хаскеля параметрический полиморфизм зачастую превращается в сочетание ad hoc + динамического полиморфизма (на основе таблицы ф-ий для классов типов). Но для программиста всё выглядит как чистейшей воды параметрический полиморфизм. А только эта т.з. для нас, программистов, и важна, ИМХО.


Вот, именно что выглядит "как". Есть даже такое:

Класс типов осуществляет диспетчеризацию статически, сводя параметрический>>> и ad hoc>>> полиморфизм в единую модель[12]. С точки зрения параметрического полиморфизма, класс типов имеет параметр (переменную типа), пробегающий множество типов. С точки зрения ad hoc полиморфизма, это множество не только дискретно, но и задано явным образом до уровня реализации. Проще говоря, сигнатура square :: Num a => a -> a означает, что функция параметрически полиморфна, но спектр типов её параметра ограничен лишь теми типами, что принадлежат к классу типов Num. Благодаря этому, функция типизируется единственным образом, несмотря на обращение к перегруженной функции из её тела.

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

Т.е. я могу согласиться с тем, что equal_to параметрически полиморфна на множестве типов с определенным оператором сравнения, объединенном с множеством типов, для которых существует явная специализация equal_to. Но при этом ее ad hoc природу не спрятать.
Re[22]: «Достаточен одинаковый размер»
От: Qbit86 Кипр
Дата: 25.01.17 22:14
Оценка: 1 (1)
Здравствуйте, vdimas, Вы писали:

V>Ну и зачем ты так сильно подставляешься-то? :xz:


Ты опять за свою риторику?

V>ни сам твой пример


Хорошо, будем рассматривать твой пример.

V>Тем не менее, в реальном приложении полно типов с одинаковым размером,


Одинаковый размер не панацея. Например, в отладчике видно, что для float/int функция `push_back()` склеена, а `emplace_back()` — уже нет.

V>Конкретно в случае vector<> достаточен одинаковый размер элементов.


:) Разумеется, одинаковый размер недостаточен.
#include <memory>
#include <vector>

template <class T> using P = std::shared_ptr<T>;

int main()
{
    static_assert(sizeof(P<char>) == sizeof(double));

    std::vector<P<char>> us;
    std::vector<double> vs;

    auto const u = std::make_shared<char>(1);
    us.push_back(u);
    vs.push_back(1);

    return 0;
}

    us.push_back(u);
011810D8  push        eax  
011810D9  lea         ecx,[us]  
011810DC  call        std::vector<std::shared_ptr<char>,std::allocator<std::shared_ptr<char> > >::emplace_back<std::shared_ptr<char> const &> (01181420h)  
    vs.push_back(1);
011810E1  movsd       xmm0,mmword ptr [__real@3ff0000000000000 (011831D0h)]  
011810E9  lea         eax,[ebp-38h]  
011810EC  push        eax  
011810ED  lea         ecx,[vs]  
011810F0  movsd       mmword ptr [ebp-38h],xmm0  
011810F5  call        std::vector<double,std::allocator<double> >::emplace_back<double> (01181350h)


V>Достаточно отключить оптимизацию подобного рода и конечный бинарный образ становится в среднем больше раз в 4-6 (на большинстве наших проектах... так-то я наблюдал и до 10 раз, тут уже как карты лягут).


Ну то есть при включённой оптимизации распухание обобщённого кода по сравнению с IL (не имеющим такой оптимизации) не сто раз, а всего десять? Huge success. Кстати, скажи, как отключить эту и только эту оптимизацию.

V>По-моему, всё нужное для случая статических библиотек, я уже озвучил:


В том примере «статичность» библиотеки непринципиальна, пусть будет распухшая динамическая библиотека.
Глаза у меня добрые, но рубашка — смирительная!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.