Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, samius, Вы писали:
_>>>Кстати, в C++ имеется своя, полностью безопасная техника стирания типа: http://www.boost.org/doc/libs/1_63_0/doc/html/boost_typeerasure.html. И с помощью неё можно элементарно написать аналог equal_to, который будет демонстрировать параметрический полиморфизм не только на уровне исходного кода, но и на уровне машинного: S>>вот тут я по поводу машинного не согласен. S>>Ты Вадлера88 посмотрел? Ввел он типы классов, перестало быть сравнение ad hoc? Нет, статья прям и называется "Как из ad hoc сделать меньше ad hoc". Т.е. типы классов в Хаскеле — ad hoc, как ни крути, но в меньшей степени, чем перегрузка. И это не я придумал.
_>В смысле не согласен? Машинный код одинаков для всех типов с точностью до бита (эту функции в отличие от шаблонной можно скомпилировать в отдельный бинарный модуль). Это просто факт, с которым ничего нельзя поделать.
Машинный код сравнения двух значений не может быть независимым от типов этих значений. Эти значения просто нельзя начинать сравнивать, не зная их тип. Значит, если код твоей функции от типов не зависит, то он должен принять нечто, что позволит косвенно перейти к специализации сравнения. Классы типов хаскеля — это и есть эта косвенность.
А раз есть косвенность, значит есть и зависимость от специализации. А значит — ad hoc.
_>Если же ты снова намекаешь на то, что данная реализация функции определена не для всех возможных типов (а только для имеющих оператор равенства), то это ничего не меняет. Потому что только для таких типов эта функция и будет использоваться — других вариантов (которые теоретически могли бы создать тот самый ad hoc через перегрузку) не будет в принципе.
Но для тех типов будет выполнен разный код сравнения, специальный для каждого типа? Я не про верхнюю функцию я про именно самый низкий уровень сравнения. Если разный — значит функция верхнего уровня, использующая эти разные коды — ad hoc. И я тут не намекаю уже. КРИЧУ!
S>>Я верю тебе что transform перестает умножаться в таком случае. Но для float и int будет вызываться все же одна машинная инструкция? Или все-таки разные за счет косвенности? Если разные — значит ad hoc (см Wadler88).
_>Естественно разные, но это всё будет происходить не в теле функции my_equal_to, так что не имеет к ней отношения. Если же ты будешь настаивать в своём определение на учёт внутреннего устройства ещё и всех других функций (вызываемых из обсуждаемой), то тогда у тебя автоматически получится, что вокруг абсолютно всё ad hoc полиморфизм, а параметрического не существует вовсе (потому что на самом низком уровне всё ad hoc).
1) я не знаю, почему ты определение называешь моим, оно везде. А вот твое я нигде не нашел более (а источник ты не указал).
2) нет, не получается автоматически. Ты передергиваешь.
Разреши, я тебе подскажу лайфках. Есть такая страничка https://wiki.haskell.org/Polymorphism и в частности https://wiki.haskell.org/Polymorphism#Ad-hoc_polymorphism.
Там написано, какие функции в Хаскеле параметрически (абсолютно) полиморфны, а какие — ad hoc.
И на тот случай, если ты не станешь читать (а vdimas не стал), я процитирую оттуда параграф (vdimas-у уже цитировал, но ты ведь не читаешь мои ответы ему).
You can recognise the presence of ad-hoc polymorphism by looking for constrained type variables: that is, variables that appear to the left of =>, like in elem :: (Eq a) => a -> [a] -> Bool. Note that lookup :: (Eq a) => a -> [(a,b)] -> Maybe b exhibits both parametric (in b) and ad-hoc (in a) polymorphism.
Я не знаю, будешь ли ты спорить с хаскельвики, но эта цитата по-крайней мере является свидетельством того, что не я один придерживаюсь определения, авторство которого ты приписываешь мне. Если, конечно, я не подправил хаскельвики.
_>Более того, при таком подходе у тебя возникает противоречие с собственными же предыдущими утверждениями. Например ты признал что обсуждаемая ранее функция apply (в Хаскеле) — это чистый параметрический полиморфизм без всяких оговорок. Но ведь в том примере в зависимости от типа второго параметра apply (int или float) выполнялся разный код (если смотреть на весь стек вызова, а не только на само тело apply). Т.е. по твоему подходу выше та apply — это тоже ad hoc.
Prelude> apply f a = f a
Prelude> :t apply
apply :: (t -> t1) -> t -> t1
Видишь? вовсе не ad hoc.
_>Похоже что ты не смотря на готовность привести различные цитаты других специалистов так и не сумел сформировать у себя в голове непротиворечивое определение для данного явления.
Вовсе нет. То что оно противоречит с твоими убеждениями (и vdimas-а тоже) — не беда вовсе. Для меня важнее что оно не противоречит с классикой, википедией и даже хаскельвики.
_>Аналогом my_equal_to в мире Хаскеля будет такой очевидный код: _>
_>my_equal_to a b = a==b
_>
_>Причём данные реализации (C++ и Хаскель) не только выглядят одинаково на уровне исходного кода (и даже имеют по сути одинаковые типы), но и будут крайне похожи на уровне машинного.
тадам....
Prelude> my_equal_to a b = a==b
Prelude> :t my_equal_to
my_equal_to :: Eq a => a -> a -> Bool
ad hoc.
S>>А бесплатного ничего не бывает.
_>Бесплатно в смысле производительности и размера программы. Т.е. все эти абстракции живут только на уровне исходного кода, а в машинный не попадают в принципе. Ну а ценой этого можно назвать разве что более долгое (по сравнению с другими языками) время компиляции.
О, расплата за бесплатное все-таки существует.
S>>Ок. Осталось выяснить, есть ли вообще в природе классификация полиморфизма, отталкивающаяся от исходных кодов, а не от необходимости выполнения специального кода для разных типов при одинаковой записи.
_>Выше мы уже выяснили, что если отталкиваться от твоей особенной классификации (которая хочет учитывать наличие специализации кода на всю глубину стека вызовов), то абсолютно всё вокруг является ad hoc полиморфизмом. )))
Я надеюсь, что мы все же выяснили, что это не моя классификация.
apply — не является (см цитату выше). Ну и в хаскельвики еще пару примеров упомянуто.
А с помощью :t, я думаю, ты сможешь найти достаточное количество примеров, что бы твой переход от моего лица к "абсолютно все является ad hoc" выглядел бы наигранным.
Здравствуйте, samius, Вы писали:
_>>В смысле не согласен? Машинный код одинаков для всех типов с точностью до бита (эту функции в отличие от шаблонной можно скомпилировать в отдельный бинарный модуль). Это просто факт, с которым ничего нельзя поделать. S>Машинный код сравнения двух значений не может быть независимым от типов этих значений. Эти значения просто нельзя начинать сравнивать, не зная их тип. Значит, если код твоей функции от типов не зависит, то он должен принять нечто, что позволит косвенно перейти к специализации сравнения. Классы типов хаскеля — это и есть эта косвенность. S>А раз есть косвенность, значит есть и зависимость от специализации. А значит — ad hoc.
Да, естественно my_equal_to неявно параметризуется (знакомое слово, не так ли?) указателем на оператор сравнения для нужного типа. И приблизительно так же работают внутренние механизмы, позволяющие функционировать Хаскелю. А в чём собственно проблема то? Или ты снова пытаешься подправить определения, так что бы они укладывались под твоё противоречивое мировоззрение? ) Изначально у нас было очевидное определение "единый код для всех типов", а небольшой спор был лишь на тему стоит ли тут учитывать только исходный код (на мой вкус только это и важно) или надо учитывать ещё и генерируемый для функции машинный код. Ну вот тут мы имеем пример с одинаковым для всех типов и исходным и машинным кодом, и теперь ты пытаешься добавить ещё какие-нибудь оговорки. )))
_>>Если же ты снова намекаешь на то, что данная реализация функции определена не для всех возможных типов (а только для имеющих оператор равенства), то это ничего не меняет. Потому что только для таких типов эта функция и будет использоваться — других вариантов (которые теоретически могли бы создать тот самый ad hoc через перегрузку) не будет в принципе. S>Но для тех типов будет выполнен разный код сравнения, специальный для каждого типа? Я не про верхнюю функцию я про именно самый низкий уровень сравнения. Если разный — значит функция верхнего уровня, использующая эти разные коды — ad hoc. И я тут не намекаю уже. КРИЧУ!
Ага, ага, только смотрим на этот код на Хаскеле:
apply f a = f a
f a = a + 1
apply f 1 -- выполняется код сложения для Int
apply f 1.0 -- выполняется код сложения для Float
и видим, что следуя твое логике apply — это очевидный ad hoc. Ой. Вот уж действительно повод для криков. )
_>>Естественно разные, но это всё будет происходить не в теле функции my_equal_to, так что не имеет к ней отношения. Если же ты будешь настаивать в своём определение на учёт внутреннего устройства ещё и всех других функций (вызываемых из обсуждаемой), то тогда у тебя автоматически получится, что вокруг абсолютно всё ad hoc полиморфизм, а параметрического не существует вовсе (потому что на самом низком уровне всё ad hoc). S>1) я не знаю, почему ты определение называешь моим, оно везде. А вот твое я нигде не нашел более (а источник ты не указал).
Ну ка покажи где это было указано, что для проверки функции на принадлежность к одному из видов полиморфизма надо проверять не только тело самой функции (одно оно для всех типов или нет), но тела всех других функций, вызываемых из данной.
S>2) нет, не получается автоматически. Ты передергиваешь.
Очень даже получается. Потому что на низком уровне только ad hoc и существует. Соответственно если ты придерживаешься точки зрения, что надо проверять функции на полную глубину стека вызова, то мы абсолютно всегда найдём какой-то ad hoc.
S>Разреши, я тебе подскажу лайфках. Есть такая страничка https://wiki.haskell.org/Polymorphism и в частности https://wiki.haskell.org/Polymorphism#Ad-hoc_polymorphism. S>Там написано, какие функции в Хаскеле параметрически (абсолютно) полиморфны, а какие — ad hoc. S>И на тот случай, если ты не станешь читать (а vdimas не стал), я процитирую оттуда параграф (vdimas-у уже цитировал, но ты ведь не читаешь мои ответы ему). S>
S>You can recognise the presence of ad-hoc polymorphism by looking for constrained type variables: that is, variables that appear to the left of =>, like in elem :: (Eq a) => a -> [a] -> Bool. Note that lookup :: (Eq a) => a -> [(a,b)] -> Maybe b exhibits both parametric (in b) and ad-hoc (in a) polymorphism.
S>Я не знаю, будешь ли ты спорить с хаскельвики, но эта цитата по-крайней мере является свидетельством того, что не я один придерживаюсь определения, авторство которого ты приписываешь мне. Если, конечно, я не подправил хаскельвики.
Ну вообще говоря мнение из внутреннего мирка Хаскеля при обсуждение глобальных вопросов для меня вообще не аргумент. Но в данном конкретном случае материалы по указанной тобой ссылке опять же противоречит другим твоим позициям. Потому как согласно им apply является параметрически полиморфной. А согласно твоей "кричащей" позиции — нет. )
_>>Более того, при таком подходе у тебя возникает противоречие с собственными же предыдущими утверждениями. Например ты признал что обсуждаемая ранее функция apply (в Хаскеле) — это чистый параметрический полиморфизм без всяких оговорок. Но ведь в том примере в зависимости от типа второго параметра apply (int или float) выполнялся разный код (если смотреть на весь стек вызова, а не только на само тело apply). Т.е. по твоему подходу выше та apply — это тоже ad hoc. S>
S>Prelude> apply f a = f a
S>Prelude> :t apply
S>apply :: (t -> t1) -> t -> t1
S>
S>Видишь? вовсе не ad hoc.
Это согласно определению из вики Хаскеля. А по твоей позиции (что надо учитывать весь стек вызова) как раз получается ad hoc.
_>>Похоже что ты не смотря на готовность привести различные цитаты других специалистов так и не сумел сформировать у себя в голове непротиворечивое определение для данного явления. S>Вовсе нет. То что оно противоречит с твоими убеждениями (и vdimas-а тоже) — не беда вовсе. Для меня важнее что оно не противоречит с классикой, википедией и даже хаскельвики.
Очень даже противоречит. Просто ты сейчас пытаешься сделать банальнейшую манипуляцию с двойными стандартами, чтобы скрыть это. Для проверки C++ ты предлагаешь использовать одни критерии (весь оригинальные, с анализом всего стека вызова), а для проверки кода на Хаскеле (а конкретно функции apply) ты предлагаешь использовать совсем другие критерии (которые ты взял из вики Хаскеля, о наличие Eq a). Подобные дешёвые фокусы совсем не подходят для приличной дискуссии...
_>>Аналогом my_equal_to в мире Хаскеля будет такой очевидный код: _>>
_>>my_equal_to a b = a==b
_>>
_>>Причём данные реализации (C++ и Хаскель) не только выглядят одинаково на уровне исходного кода (и даже имеют по сути одинаковые типы), но и будут крайне похожи на уровне машинного. S>тадам.... S>
S>Prelude> my_equal_to a b = a==b
S>Prelude> :t my_equal_to
S>my_equal_to :: Eq a => a -> a -> Bool
S>ad hoc.
А я разве где-то писал, что согласен с подобными критериями? ) Данная функция выглядит одинаково для всех типов и в исходных и в машинных кодах. Покажи что конкретно по твоему не укладывается в ней в цитируемое тобой же определение параметрического полиморфизма (например из TAPL).
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, samius, Вы писали:
S>>А раз есть косвенность, значит есть и зависимость от специализации. А значит — ad hoc.
_>Да, естественно my_equal_to неявно параметризуется (знакомое слово, не так ли?) указателем на оператор сравнения для нужного типа. И приблизительно так же работают внутренние механизмы, позволяющие функционировать Хаскелю. А в чём собственно проблема то? Или ты снова пытаешься подправить определения, так что бы они укладывались под твоё противоречивое мировоззрение? ) Изначально у нас было очевидное определение "единый код для всех типов", а небольшой спор был лишь на тему стоит ли тут учитывать только исходный код (на мой вкус только это и важно) или надо учитывать ещё и генерируемый для функции машинный код. Ну вот тут мы имеем пример с одинаковым для всех типов и исходным и машинным кодом, и теперь ты пытаешься добавить ещё какие-нибудь оговорки. )))
Я тут вижу только одну проблему. ЧТо ты в одном абзаце снчала говоришь что my_equal_to неявно параметризуется указателем на оператор сравнения для нужного типа, а потом утверждаешь что исходя из необходимости учета машинного кода, выходит что код одинаков. Однако, для разных типов выполняется разный машинный код, именно потому и есть необходимость в указании указателя на оператор сравнения.
_>>>Если же ты снова намекаешь на то, что данная реализация функции определена не для всех возможных типов (а только для имеющих оператор равенства), то это ничего не меняет. Потому что только для таких типов эта функция и будет использоваться — других вариантов (которые теоретически могли бы создать тот самый ad hoc через перегрузку) не будет в принципе. S>>Но для тех типов будет выполнен разный код сравнения, специальный для каждого типа? Я не про верхнюю функцию я про именно самый низкий уровень сравнения. Если разный — значит функция верхнего уровня, использующая эти разные коды — ad hoc. И я тут не намекаю уже. КРИЧУ!
_>Ага, ага, только смотрим на этот код на Хаскеле: _>
_>apply f a = f a
_>f a = a + 1
_>apply f 1 -- выполняется код сложения для Int
_>apply f 1.0 -- выполняется код сложения для Float
_>
_>и видим, что следуя твое логике apply — это очевидный ad hoc. Ой. Вот уж действительно повод для криков. )
apply по моей логике — очевидный параметрический полиморфизм. Но apply f — это уже другая функция. И она ad hoc.
Prelude> apply f a = f a
Prelude> :t apply
apply :: (t -> t1) -> t -> t1
Prelude> f a = a + 1
Prelude> :t apply f
apply f :: Num t1 => t1 -> t1
_>>>Естественно разные, но это всё будет происходить не в теле функции my_equal_to, так что не имеет к ней отношения. Если же ты будешь настаивать в своём определение на учёт внутреннего устройства ещё и всех других функций (вызываемых из обсуждаемой), то тогда у тебя автоматически получится, что вокруг абсолютно всё ad hoc полиморфизм, а параметрического не существует вовсе (потому что на самом низком уровне всё ad hoc). S>>1) я не знаю, почему ты определение называешь моим, оно везде. А вот твое я нигде не нашел более (а источник ты не указал).
_>Ну ка покажи где это было указано, что для проверки функции на принадлежность к одному из видов полиморфизма надо проверять не только тело самой функции (одно оно для всех типов или нет), но тела всех других функций, вызываемых из данной.
Про тела — не скажу. Но одинаковое поведение для разных типов требуется в TAPL (приведу ниже). А твоей my_equal_to очевидно не может обеспечить одинаковое поведение для разных типов. Нужен пример?
S>>2) нет, не получается автоматически. Ты передергиваешь.
_>Очень даже получается. Потому что на низком уровне только ad hoc и существует. Соответственно если ты придерживаешься точки зрения, что надо проверять функции на полную глубину стека вызова, то мы абсолютно всегда найдём какой-то ad hoc.
Зачем? это же очевидно легко бьется.
Prelude> let myConst :: t -> Int ; myConst t = 0
Prelude> :t myConst
myConst :: t -> Int
Найди здесь хоть какой-то ad hoc. Или нам с тобой надо будет еще рулиться за понимание сочетания слов "абсолютно всегда"?
S>>Я не знаю, будешь ли ты спорить с хаскельвики, но эта цитата по-крайней мере является свидетельством того, что не я один придерживаюсь определения, авторство которого ты приписываешь мне. Если, конечно, я не подправил хаскельвики.
_>Ну вообще говоря мнение из внутреннего мирка Хаскеля при обсуждение глобальных вопросов для меня вообще не аргумент. Но в данном конкретном случае материалы по указанной тобой ссылке опять же противоречит другим твоим позициям. Потому как согласно им apply является параметрически полиморфной. А согласно твоей "кричащей" позиции — нет. )
ты как-то не поймешь все мою позицию, пытаешься выдвигать за меня тезисы. Нет у меня кричащей позиции о том что apply ad hoc. Это ты подставить меня желаешь зачем-то. apply параметрически полиморфна (точка). ad hoc полиморфна apply f, а не apply. Надо объяснять что это разные функции?
_>>>Более того, при таком подходе у тебя возникает противоречие с собственными же предыдущими утверждениями. Например ты признал что обсуждаемая ранее функция apply (в Хаскеле) — это чистый параметрический полиморфизм без всяких оговорок. Но ведь в том примере в зависимости от типа второго параметра apply (int или float) выполнялся разный код (если смотреть на весь стек вызова, а не только на само тело apply). Т.е. по твоему подходу выше та apply — это тоже ad hoc. S>>
S>>Prelude> apply f a = f a
S>>Prelude> :t apply
S>>apply :: (t -> t1) -> t -> t1
S>>
S>>Видишь? вовсе не ad hoc.
_>Это согласно определению из вики Хаскеля. А по твоей позиции (что надо учитывать весь стек вызова) как раз получается ad hoc.
Вообще не получается. Это твои выдумки. Весь стек вызовов функции apply заканчивается на возврате функции, которой ты подашь int или float. И ты либо об этом знаешь, либо никудышный знаток Хаскеля.
_>>>Похоже что ты не смотря на готовность привести различные цитаты других специалистов так и не сумел сформировать у себя в голове непротиворечивое определение для данного явления. S>>Вовсе нет. То что оно противоречит с твоими убеждениями (и vdimas-а тоже) — не беда вовсе. Для меня важнее что оно не противоречит с классикой, википедией и даже хаскельвики.
_>Очень даже противоречит. Просто ты сейчас пытаешься сделать банальнейшую манипуляцию с двойными стандартами, чтобы скрыть это. Для проверки C++ ты предлагаешь использовать одни критерии (весь оригинальные, с анализом всего стека вызова), а для проверки кода на Хаскеле (а конкретно функции apply) ты предлагаешь использовать совсем другие критерии (которые ты взял из вики Хаскеля, о наличие Eq a). Подобные дешёвые фокусы совсем не подходят для приличной дискуссии...
Я не предлагал использовать буквально "весть стек вызова", но мне что-то кажется что использование всего стека вызовов для C++ и проверки наличия Eq a дадут ровно те же результаты со скидкой на эквивалентность проверяемых функций. То есть, наличие Eq указывает на то, что в стеке вызовов (если Eq не введен избыточно) есть специальное поведение для разных типов. Так что, я тут невижу проблемы.
S>>тадам.... S>>
S>>Prelude> my_equal_to a b = a==b
S>>Prelude> :t my_equal_to
S>>my_equal_to :: Eq a => a -> a -> Bool
S>>ad hoc.
_>А я разве где-то писал, что согласен с подобными критериями? ) Данная функция выглядит одинаково для всех типов и в исходных и в машинных кодах. Покажи что конкретно по твоему не укладывается в ней в цитируемое тобой же определение параметрического полиморфизма (например из TAPL).
Ок, давай я его процитирую, что бы под рукой было.
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.
Вот поведение-то и не укаладывается, т.к. оно различное для разных типов. Так же как и различен набор машинных кодов, которые выполнятся (на всю глубину стека) при инстанциации разными типами.
А вот в это определение:
Ad-hoc polymorphism, by contrast, allows a polymorphic value to exhibit different behaviors when “viewed” at different types.
твоя my_equal_to абсолютно и полностью укладывается.
Чую, ответишь что я и Пирса в свою секту перетянул.
Здравствуйте, Sinix, Вы писали:
V>>Проблема исключительно и только в рефлексии всего и вся. S>Ну... не совсем так. Главный затык _сейчас_ — инлайнинг делегатов / интерфейсов (хотя бы итераторов для начала) и stackallock объектов (не факт, что он появится в .native раньше, чем в .net core).
В компиляторе С++ всё это порешали уже лет 15 назад. Т.е. дело лишь за тем, чтобы перенести наработки в дотнетный Native.
S>"Сейчас" — это с хайпом на облака акторов
Что есть выделенное?
S>А вот когда (и если) дело пойдёт в сторону числодробилок, тогда — да, cross-assembly optimizations в полный рост.
Без "числобробилок" платформа не может считаться "зрелой", "взрослой" и т.д.
S>>>* когда по качеству оптимизации транслированный код будет выигрывать у выхлопа JIT-а (ещё позднее). V>>А вот это тогда, когда перейдут на принципиально другую VM. Собсно, унутре майкрософтных оптимизирующих продуктов есть промежуточное представление навроде LLVM. S>В смысле перейдут? у .net native свой runtime прямо сейчас.
Модель VM та же.
Я же говорил, что Net Native даёт сразу конечный не-кроссплатформенный результат и это способно немного сбить с толку. Но получают его (конечный результат) через некий промежуточный, который является кроссплатформенным — через модель той же самой VM. Для получения нейтивного кода не надо компилять в облаке, можно компилять локально и смотреть, что происходит. В облаке — это когда отправляешь готовое приложение в Магазин.
V>>Более того, с выпуском VS 15 они теперь могут поддерживать оптимизацию байт-кода LLVM. S>llilc даже до беты не дошёл ещё. Кто его там в релиз собирался впихивать??? Или речь про IL2CPP от unity?
Здравствуйте, vdimas, Вы писали:
S>>"Сейчас" — это с хайпом на облака акторов V>Что есть выделенное?
Архитектура, заточенная на кучу микросервисов, каждый из которых может умирать / переподниматься прозрачно для клиентов.
Azure Service Fabric или Orleans как пример.
S>>А вот когда (и если) дело пойдёт в сторону числодробилок, тогда — да, cross-assembly optimizations в полный рост. V>Без "числобробилок" платформа не может считаться "зрелой", "взрослой" и т.д.
Ну вот как хайп на это дело будет — вот тогда и приходите. Сейчас от "взрослой" другого хотят.
V>>>А вот это тогда, когда перейдут на принципиально другую VM. S>>В смысле перейдут? у .net native свой runtime прямо сейчас. V>Модель VM та же.
А давай конкретику А то я сколько ни слышу рассказов про плашки не той системы, так регулярно оказывается, что обсуждается не фактическое положение дел, а Карузо в перепеве Рабиновича. Как в этой ветке
например.
V>Я же говорил, что Net Native даёт сразу конечный не-кроссплатформенный результат и это способно немного сбить с толку.
Не совсем так. net native — наследник целого семейство технологий перевода в натив. Там предусмотрено несколько моделей распространения, от annotated il и mdil и до готового бинарника. Ну, т.е. я вообще не вижу, как связаны друг с другом способ получения бинарника и "принципиально другая" VM.
MS — он большой По ссылке — проект ms vc++ team. Он давно уже поддерживается и развивается параллельно порту (портам) CLR VES на LLVM. Практически никак не связаны друг с другом.
Re[13]: Visual C# vs C++. Надо сравнить перспективы.
Здравствуйте, samius, Вы писали:
V>>К сожалению, первые 8 лет — вообще не туда. Дотнет был разработан полупрофессиональными программистами, полуинженерами. Почти нубами. Это не попытка наезда, это медицинский факт. Эти люди получили почти безграничный кредит доверия на волне той самой шумихи "ява в интернете". Они оказались неспособны рассмотреть вопросы организации вычислений в комплексе, не смогли промоделировать реальные пути развития вычислительных сугубо программных технологий. Сам проект дотнета "выстрелил" лишь благодаря фантастическим потраченным на проект человекочасам в сочетании с, скажем прямо, недостижимым авторитетом MS на начало 2000-х. S>У меня вопросы: где были полноценные (не полу-) профессионалы и инженеры?
Профессионалы были отодвинуты от принятия стратегических решений.
Ну реально. Мы все почитывали одно время блоги того же Липперта. Тот самый показатель того, НАСКОЛЬКО случайные в отрасли люди могут оказаться на столь ответственных должностях. Липперт — отличный увлекательный болтун. В глубине души остроумный исследователь всяких мелочей, но на практике полезен лишь как администратор. Т.е. не тот человек, который придумал некую машину, а который способен тщательно организовать процедуру её обслуживания. И ни в коем случае не более. Потому что когда более, то получаем второго Вовку-морковку, т.е. человека, который не способен понять (или принять) реальность такой, какова она есть, поэтому придумывает более удобную для себя реальность и носится с её рекламированием: https://habrahabr.ru/post/166341/
Извини, но по ссылке содержатся откровения сказочного долб оленя, чья высокая должность превратила всю эту сказочность одно время в натуральную религию (помнишь тут на сайте обсуждения 2004-2008-хх годов? )
Понимаешь. Каждый хорош на своём месте. Вот мне было интересно когда-то дорасти до своих 40+ — до возраста тех дядек, которые когда-то сделали VM дотнета такой, какая он есть до сих пор (НИЧЕГО серьезного с ПЕРВОЙ бета-версии так и не произошло, заметь). Мне было любопытно посмотреть на все эти косяки глазами человека с примерно таким же багажом опыта. И да, чуда не произошло, ес-но. Никаких оправданий всему этому беспределу инженерных ошибок я так и не увидел.
Вот взять даже несовместимость делегатов по сигнатурам. Т.е., тип делегата задаётся его ИМЕНЕМ, а не сигнатурой функционального типа. А ведь это не 70-е года 20-го века, эту фишку сделали серьезные дядьки (якобы серьёзные) в первый год 21-го века (я внимательно прочитал книжку по истории разработки дотнета от одного из его авторов).
Ну вот представляю себе живую ситуацию — пусть я в этом участвую и принимаю решения. Пусть даже за пивом (чтобы сразу дураком не выставили) один из подчинённых инженеров мне предлагает: "а ваще, если для делегатов использовать ровно такое же описание в метаинформации, как для обычных классов, то мы сможем сэкономить на кол-ве сущностей в метаинформации нашей приблуды". Ну я бы поржал, похлопал бы парнишку по плечу и за 10 мин на салфетке разрисовал бы ему, какой катастрофой обернется подобная "экономия" в будущем. И ожидал бы увидеть понимание в глазах, ес-но, а не беспроветную муть... Потому что, если бы он продолжил настаивать... ну не знаю, тут оставалось бы только смотреть сквозь человека и думать о чём-то своём, например, о странных перепитиях судьбы, когда совершенно случайные в отрасли люди оказываются в столь опасной близости от ответственных постов... В случае дотнета случилось непоправимое — такие люди (требующие обязательного контроля и направления своей работы) оказались на САМЫХ верхних технических должностях и сами направляли работу других (зачастую БОЛЕЕ ГРАМОТНЫХ) коллег. Ну что тут сказать?.. Мои соболезнования...
S>Что они создали за это время, что смогли промоделировать, на что равняемся?
Например, они создали нейтивный аналог WPF менее, чем за полтора года — как только их об этом попросили. Причем, создали этот аналог удивительно скромными ресурсами, развенчав, собсно, главный миф о "затратности" нейтивной разработки. Причем, степень продуманности нового АПИ Win 8+ (взгляни хотя бы на концепцую строкового типа на уровне АПИ ОС) — приятно удивляет.
Хороший инженер должен быть по совместительству оракулом, как ни крути. "Принимая решения" ты определяешь вложения усилий тысяч людей на ближайшие десятилетия. Тут, всё-таки, требуется определённая продуманность (не знаю какой лучший термин подобрать), умение увидеть картинку целиком.
Здравствуйте, samius, Вы писали:
_>>Да, естественно my_equal_to неявно параметризуется (знакомое слово, не так ли?) указателем на оператор сравнения для нужного типа. И приблизительно так же работают внутренние механизмы, позволяющие функционировать Хаскелю. А в чём собственно проблема то? Или ты снова пытаешься подправить определения, так что бы они укладывались под твоё противоречивое мировоззрение? ) Изначально у нас было очевидное определение "единый код для всех типов", а небольшой спор был лишь на тему стоит ли тут учитывать только исходный код (на мой вкус только это и важно) или надо учитывать ещё и генерируемый для функции машинный код. Ну вот тут мы имеем пример с одинаковым для всех типов и исходным и машинным кодом, и теперь ты пытаешься добавить ещё какие-нибудь оговорки. ))) S>Я тут вижу только одну проблему. ЧТо ты в одном абзаце снчала говоришь что my_equal_to неявно параметризуется указателем на оператор сравнения для нужного типа, а потом утверждаешь что исходя из необходимости учета машинного кода, выходит что код одинаков. Однако, для разных типов выполняется разный машинный код, именно потому и есть необходимость в указании указателя на оператор сравнения.
У тебя похоже какие-то проблемы с пониманием термина "код функции", хотя раньше я что-то не встречал никаких разночтений с ним у других программистов. Точнее с понятием "исходный код функции" у тебя вроде всё нормально, а вот с понятием "машинный код функции" явно какие-то сложности. Потому как ты постоянно приплетаешь машинный код операторов сравнения (совершенно других функций и на уровне исходного и на уровне машинного кода) к my_equal_to.
Если же ты говоришь о том, что для анализа вида полиморфизма некой функций на уровне машинных кодов (кстати, как мы уже обсудили, вообще не важный для программиста факт, но почему бы не поболтать и о такой ерунде) необходимо сравнить не только машинный код самой этой функции (для разных типов), но и код всех функций вызываемых из неё (и так далее, на всю глубину стека вызовов), то это уже совсем другой вопрос. И кстати, надо зафиксировать твою позицию (а то ты как-то увиливаешь постоянно) по данному вопросу. И так, по твоему надо анализировать машинный код:
1. только изучаемой функции
2. всего стека вызовов на полную глубину
Самое забавное, что какой бы варианты ты не указал, он будет противоречить одному из твоих предыдущих утверждений. Но об это позже, после того, как ты зафиксируешь свою позицию.
_>>Ага, ага, только смотрим на этот код на Хаскеле: _>>
_>>apply f a = f a
_>>f a = a + 1
_>>apply f 1 -- выполняется код сложения для Int
_>>apply f 1.0 -- выполняется код сложения для Float
_>>
_>>и видим, что следуя твое логике apply — это очевидный ad hoc. Ой. Вот уж действительно повод для криков. ) S>apply по моей логике — очевидный параметрический полиморфизм. Но apply f — это уже другая функция. И она ad hoc.
Где-то в моём примере объявлена или используется функция вида "g = apply f"? ) Не надо подобных дешёвых фокусов.
_>>Ну ка покажи где это было указано, что для проверки функции на принадлежность к одному из видов полиморфизма надо проверять не только тело самой функции (одно оно для всех типов или нет), но тела всех других функций, вызываемых из данной. S>Про тела — не скажу. Но одинаковое поведение для разных типов требуется в TAPL (приведу ниже). А твоей my_equal_to очевидно не может обеспечить одинаковое поведение для разных типов. Нужен пример?
У my_equal_to абсолютно одинаковое поведение для всех типов — она вызывает (и это вся её деятельность) оператор равенства соответствующего типа.
_>>Очень даже получается. Потому что на низком уровне только ad hoc и существует. Соответственно если ты придерживаешься точки зрения, что надо проверять функции на полную глубину стека вызова, то мы абсолютно всегда найдём какой-то ad hoc. S>Зачем? это же очевидно легко бьется. S>
S>Prelude> let myConst :: t -> Int ; myConst t = 0
S>Prelude> :t myConst
S>myConst :: t -> Int
S>
S>Найди здесь хоть какой-то ad hoc. Или нам с тобой надо будет еще рулиться за понимание сочетания слов "абсолютно всегда"?
А, ну да) Остроумно. ))) И много таких функций встречается в твоих приложениях? )
_>>Ну вообще говоря мнение из внутреннего мирка Хаскеля при обсуждение глобальных вопросов для меня вообще не аргумент. Но в данном конкретном случае материалы по указанной тобой ссылке опять же противоречит другим твоим позициям. Потому как согласно им apply является параметрически полиморфной. А согласно твоей "кричащей" позиции — нет. ) S>ты как-то не поймешь все мою позицию, пытаешься выдвигать за меня тезисы. Нет у меня кричащей позиции о том что apply ad hoc. Это ты подставить меня желаешь зачем-то. apply параметрически полиморфна (точка). ad hoc полиморфна apply f, а не apply. Надо объяснять что это разные функции?
Функции apply f не существует в природе, пока ты не определил где-то что-то вроде g=apply f. В этом случае на уровне машинных кодов появится отдельная функция с поведение как у apply f, но при этом она будет всего лишь обёрткой над apply.
_>>Это согласно определению из вики Хаскеля. А по твоей позиции (что надо учитывать весь стек вызова) как раз получается ad hoc. S>Вообще не получается. Это твои выдумки. Весь стек вызовов функции apply заканчивается на возврате функции, которой ты подашь int или float. И ты либо об этом знаешь, либо никудышный знаток Хаскеля.
Ты вот что, серьёзно верил, что каррирование реально существует на уровне машинных кодов? Да если бы кто-то и попытался сделать подобное, то оно работало бы не просто медленно (как нынешний Хаскель), а вообще почти не шевелилось бы (наверное хуже чем какой-нибудь bash).
https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/HaskellExecution/FunctionCalls — на вот, просвещайся как обстоят дела в реальности, чтобы не писать больше подобных глупостей.
_>>А я разве где-то писал, что согласен с подобными критериями? ) Данная функция выглядит одинаково для всех типов и в исходных и в машинных кодах. Покажи что конкретно по твоему не укладывается в ней в цитируемое тобой же определение параметрического полиморфизма (например из TAPL). 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>Вот поведение-то и не укаладывается, т.к. оно различное для разных типов. Так же как и различен набор машинных кодов, которые выполнятся (на всю глубину стека) при инстанциации разными типами.
Так где тут указано про "всю глубину стека"?
S>А вот в это определение: S>
S>Ad-hoc polymorphism, by contrast, allows a polymorphic value to exhibit different behaviors when “viewed” at different types.
S>твоя my_equal_to абсолютно и полностью укладывается.
Не укладывается, т.к. поведение абсолютно одинаковое: вызов оператора равенства для соответствующего типа. )
S>Чую, ответишь что я и Пирса в свою секту перетянул.
У меня к его определениям никаких особых возражений нет. Более того, это его абстрактное piece of code как раз в точности соответствует моей формулировке и позволяет сделать два отдельных применения: на уровне исходных кодов (на мой вкус только это и важно) и на уровне машинных кодов (вообще не важно, но можно тоже поанализоровать для развлечения).
Здравствуйте, Qbit86, Вы писали:
V>>Вместо этого фигней маешься, пытаешься "схватить за руку". Q>Мнительный ты какой-то. Я делаю вполне безобидные утверждения, сопровождаю примерами.
Ты маешься откровенной фигней:
Не наблюдаю такого в отладчике после лёгкой модифиации кода
Будь ты студентом и показывай подобные мыслительные возможности преподу, он бы влепил тебе неуд сходу.
Q>Ты же стремишься уличить в некомпетентности, глумиться над невеждами и всё такое.
Потому что ты знанял такую странную позицию из разряда "вот объясните мне, дураку".
Неинтересно. Нудятина.
Оппонентам интересно ровно противоположное.
V>>Цель-та какова? Разобраться с материалом или поиграть в эти игры? Q>Только ты провоцируешь «эти игры» в треде. Твоё поведение токсично, разберись с этим.
Т.е. это я топики переименовываю и строю из себя "непонимающего"? ))
Твоё поведение иррационально, а моё всего лишь раздражительно. Причем, моё хоть имеет причину.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>У меня вопросы: где были полноценные (не полу-) профессионалы и инженеры?
V>Профессионалы были отодвинуты от принятия стратегических решений.
... V>Ну что тут сказать?.. Мои соболезнования...
Имхо, ты немного гипертрофируешь уровень ответственности. Я 8 лет проработал в одном НИИ цитологии и генетики. Там бомбы когда-то делали, но и сейчас еще пытаются. А более помолчу.
Делегаты, кстати, не Липперта наследие. На сколько мне помнится.
S>>Что они создали за это время, что смогли промоделировать, на что равняемся?
V>Например, они создали нейтивный аналог WPF менее, чем за полтора года — как только их об этом попросили. Причем, создали этот аналог удивительно скромными ресурсами, развенчав, собсно, главный миф о "затратности" нейтивной разработки. Причем, степень продуманности нового АПИ Win 8+ (взгляни хотя бы на концепцую строкового типа на уровне АПИ ОС) — приятно удивляет.
Еще не видел, если честно. Но мне почему-то кажется что опыт WPF был таки там учтен, т.е. не с нуля разрабатывалось.
V>Хороший инженер должен быть по совместительству оракулом, как ни крути. "Принимая решения" ты определяешь вложения усилий тысяч людей на ближайшие десятилетия. Тут, всё-таки, требуется определённая продуманность (не знаю какой лучший термин подобрать), умение увидеть картинку целиком.
Так вот, в том институте (где я работал) очень не любили оракулов. Чем точнее прогнозы, тем короче дорога на выход. Ну или, по крайней мере, дыр, которых надо было заткнуть, их было куда больше, чем хороших инженеров (но меньше, чем плохих). И хорошие инженеры очень часто становились хорошими затычками. А плохие — легко оказывались в руководстве.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, samius, Вы писали:
S>>Я тут вижу только одну проблему. ЧТо ты в одном абзаце снчала говоришь что my_equal_to неявно параметризуется указателем на оператор сравнения для нужного типа, а потом утверждаешь что исходя из необходимости учета машинного кода, выходит что код одинаков. Однако, для разных типов выполняется разный машинный код, именно потому и есть необходимость в указании указателя на оператор сравнения.
_>У тебя похоже какие-то проблемы с пониманием термина "код функции", хотя раньше я что-то не встречал никаких разночтений с ним у других программистов. Точнее с понятием "исходный код функции" у тебя вроде всё нормально, а вот с понятием "машинный код функции" явно какие-то сложности. Потому как ты постоянно приплетаешь машинный код операторов сравнения (совершенно других функций и на уровне исходного и на уровне машинного кода) к my_equal_to.
_>Если же ты говоришь о том, что для анализа вида полиморфизма некой функций на уровне машинных кодов (кстати, как мы уже обсудили, вообще не важный для программиста факт, но почему бы не поболтать и о такой ерунде) необходимо сравнить не только машинный код самой этой функции (для разных типов), но и код всех функций вызываемых из неё (и так далее, на всю глубину стека вызовов), то это уже совсем другой вопрос. И кстати, надо зафиксировать твою позицию (а то ты как-то увиливаешь постоянно) по данному вопросу. И так, по твоему надо анализировать машинный код: _>1. только изучаемой функции _>2. всего стека вызовов на полную глубину
_>Самое забавное, что какой бы варианты ты не указал, он будет противоречить одному из твоих предыдущих утверждений. Но об это позже, после того, как ты зафиксируешь свою позицию.
Дада, я вот тоже для тебя западню заготовил, но вот беда (и смешно и обидно вышло... ) переоценил уровень твоего бэкграунда. И ты пролетел мимо этой засады, даже не поморщился. Ну что ж, попробую тебя оттормозить, оттащить назад и все-таки посадить в эту лужу.
Хорошо, зафиксируем. Пирс говорит о поведении куска кода. Не знаю, станешь спорить или нет, но поведение куска кода определяется в том числе машинным кодом (если мы говорим о некой машине как исполнителе). Но не каждой инструкцией. Таким образом, есть инструкции, не влияющие на поведение куска кода, а есть — непосредственно влияющие.
Когда люди из академической/научной и околонаучной среды говорят о поведении кода, они говорят не о том, как ведет себя исполнитель кода, они говорят о некой процедурной абстракции, которая есть мысленная модель того, что люди ожидают от кода, но в виде того, что они хотят получить и из чего, а не каким образом. Именно опираясь на ожидаемое поведение, компиляторы могут заниматься компиляцией и оптимизацией, суперкомпиляторы могут заменять конкретные вызовы значением или таблицей результатов. Одну и ту же функцию, описанную текстом, компилятор имеет право вставить в нескольких местах вызова совершенно различными наборами инструкций. В одном месте заинлайнить, в другом заменить, в третьем подставить код вызова. Таким образом, функция в тексте может быть одна, но наборов инструкций, ей соответствующих может быть несколько. С другой стороны, комипляторы вольны нагородить лишнего говна, которое работать будет, но менять поведение, при этом, не должно.
Чем определяется поведение кода? Для этого, например, можно использовать математическую абстракцию функции — соответствие между множеством определения и множеством значений. Не для всякого кода такая абстракция удобна, потому можно перейти к множествам состояний исполнителя до/после/или даже во время выполнения кода. С точностью до побочных эффектов, если они есть. Но все равно используется некий абстрактный исполнитель, и чем выше уровень языка, тем более значительна разница между абстрактным исполнителем и конкретным исполнителем. Вторичнымм вопросом по отношению к поведению кода является оценка кол-ва шагов, требуемая для его выполнения. Почему вторичным? Потому что это не влияет на возмножность подмены одной процедуры другой.
И вот тут я с тобой соглашусь в том, что программистам (по большей части) пофигу на машинные коды, сколько их вариантов, что они там вызывают, а что инлайнят и т.д. Но без машинных кодов конкретный исполнитель "машина" не может обеспечить корректную подмену текста исходника кодом исполнителя. Т.е. код исполнителя имеет значение. Но лишь тот, который ответственен за поведение. То есть, если код функции определения длины списка length по ходу вычислений длины вычислит еще и число пи до тысячного знака и выкинет его, то это не повлияет на поведение кода с точки зрения процедурной абстракции, но, вероятно, при этом введет кого-то в заблуждение в отношении полиморфизма функции length.
Так вот, возвращаясь к фиксации (выше я просто подстелил соломку, но в другом месте, не в том, где ты мне яму нарыл): Пирс использует в определении поведение куска кода. Но ты мне предложил лишь два варианта, полагаю что мне нужно выбрать из двух. Я выбираю 2, но с оговоркой. Лишь тот машинный код имеет значение, который влияет на поведение функции. Да, при этом, на всю глубину. Если влияет, то на всю глубину. Если что-то не влияет на поведение — не имеет значение, что там.
_>>>и видим, что следуя твое логике apply — это очевидный ad hoc. Ой. Вот уж действительно повод для криков. ) S>>apply по моей логике — очевидный параметрический полиморфизм. Но apply f — это уже другая функция. И она ad hoc.
_>Где-то в моём примере объявлена или используется функция вида "g = apply f"? ) Не надо подобных дешёвых фокусов.
В том, что касается дешевых фокусов, используя понятие процедурной абстракции, можно верить тому, что поведение функции apply f не отличимо от поведения функции f, и оно же неотличимо от "g = apply f". Если бы это было не так, то функцию apply с аргументом f нельзя было бы использовать вместо функции f. Но ты ее как раз используешь исходя из сохранения поведения. Значит, должен быть удовлетворен любой подстановкой с сохранением его. Если нет — выполняй f сам.
_>>>Ну ка покажи где это было указано, что для проверки функции на принадлежность к одному из видов полиморфизма надо проверять не только тело самой функции (одно оно для всех типов или нет), но тела всех других функций, вызываемых из данной. S>>Про тела — не скажу. Но одинаковое поведение для разных типов требуется в TAPL (приведу ниже). А твоей my_equal_to очевидно не может обеспечить одинаковое поведение для разных типов. Нужен пример?
_>У my_equal_to абсолютно одинаковое поведение для всех типов — она вызывает (и это вся её деятельность) оператор равенства соответствующего типа.
Ее поведение разное в терминах процедурной абстракции.
S>>Найди здесь хоть какой-то ad hoc. Или нам с тобой надо будет еще рулиться за понимание сочетания слов "абсолютно всегда"?
_>А, ну да) Остроумно. ))) И много таких функций встречается в твоих приложениях? )
О, рад что ты оценил. Да, параметрически полиморфных функций в моих приложениях встречается много.
_>>>Ну вообще говоря мнение из внутреннего мирка Хаскеля при обсуждение глобальных вопросов для меня вообще не аргумент. Но в данном конкретном случае материалы по указанной тобой ссылке опять же противоречит другим твоим позициям. Потому как согласно им apply является параметрически полиморфной. А согласно твоей "кричащей" позиции — нет. ) S>>ты как-то не поймешь все мою позицию, пытаешься выдвигать за меня тезисы. Нет у меня кричащей позиции о том что apply ad hoc. Это ты подставить меня желаешь зачем-то. apply параметрически полиморфна (точка). ad hoc полиморфна apply f, а не apply. Надо объяснять что это разные функции?
_>Функции apply f не существует в природе, пока ты не определил где-то что-то вроде g=apply f. В этом случае на уровне машинных кодов появится отдельная функция с поведение как у apply f, но при этом она будет всего лишь обёрткой над apply.
О, если поведение как у apply f, то я спокоен. Ты ведь все-таки оперириуешь понятием поведение функции? Почему же при словах "поведение куска кода" ты переходишь к исполнителю?
_>>>Это согласно определению из вики Хаскеля. А по твоей позиции (что надо учитывать весь стек вызова) как раз получается ad hoc. S>>Вообще не получается. Это твои выдумки. Весь стек вызовов функции apply заканчивается на возврате функции, которой ты подашь int или float. И ты либо об этом знаешь, либо никудышный знаток Хаскеля.
_> _>Ты вот что, серьёзно верил, что каррирование реально существует на уровне машинных кодов? Да если бы кто-то и попытался сделать подобное, то оно работало бы не просто медленно (как нынешний Хаскель), а вообще почти не шевелилось бы (наверное хуже чем какой-нибудь bash).
Ну причем тут "медленно"?
_>https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/HaskellExecution/FunctionCalls — на вот, просвещайся как обстоят дела в реальности, чтобы не писать больше подобных глупостей.
Вот видишь, согласно понятию процедурной абстракции хаскель может генерить несколько различных тел для одной функции и вызывать их в зависимости от обстоятельств вызова. Сохраняя, при этом поведение, соответствующее execution model. Если завтра технические детали реализации поменяются с "просто медленно" на "вообще почти не шевелилось бы", но сохранится execution model, то на поведение функций apply, f, apply f это не повлияет. Следовательно, сохранится их параметрическая классификация. Будь уверен в этом.
_>>>А я разве где-то писал, что согласен с подобными критериями? ) Данная функция выглядит одинаково для всех типов и в исходных и в машинных кодах. Покажи что конкретно по твоему не укладывается в ней в цитируемое тобой же определение параметрического полиморфизма (например из TAPL). 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>>Вот поведение-то и не укаладывается, т.к. оно различное для разных типов. Так же как и различен набор машинных кодов, которые выполнятся (на всю глубину стека) при инстанциации разными типами.
_>Так где тут указано про "всю глубину стека"?
А тут нет глубины стека, т.к. это техдетали реализации.
S>>А вот в это определение: S>>
S>>Ad-hoc polymorphism, by contrast, allows a polymorphic value to exhibit different behaviors when “viewed” at different types.
S>>твоя my_equal_to абсолютно и полностью укладывается.
_>Не укладывается, т.к. поведение абсолютно одинаковое: вызов оператора равенства для соответствующего типа. )
Выше ты использовал понятие поведения функции в фразе "В этом случае на уровне машинных кодов появится отдельная функция с поведение как у apply f, но при этом она будет всего лишь обёрткой над apply."
Это как у тебя получилось что поведение обертки и функции одинаковое, притом что тут ты под поведением подразумеваешь лишь "вызов оператора"? Сам себя поймал, однако.
S>>Чую, ответишь что я и Пирса в свою секту перетянул.
_>У меня к его определениям никаких особых возражений нет. Более того, это его абстрактное piece of code как раз в точности соответствует моей формулировке и позволяет сделать два отдельных применения: на уровне исходных кодов (на мой вкус только это и важно) и на уровне машинных кодов (вообще не важно, но можно тоже поанализоровать для развлечения).
Я полагаю что его абстрактное поведение инстансов (кусков кода, параметризованных конкретными типами) употреблено в том же смысле, как и у тебя, когда ты говоришь "с поведение как у apply f, но при этом она будет всего лишь обёрткой" — согласно процедурной абстракции.
Здравствуйте, vdimas, Вы писали:
V>Ты маешься откровенной фигней: V>
V>Не наблюдаю такого в отладчике после лёгкой модифиации кода
Твой пример с `push_back()` может ввести неискушённого читателя в заблуждение, дескать, распухание кода побеждено «бинарной склейкой». Долг любого сознательного гражданина обратить внимание читателей на сильные ограничения условий подобной оптимизации, желательно с конкретным проверяемым примером. «Не наблюдаю такого в отладчике после лёгкой модифиации кода» как раз и предоставляет такой конкретный пример.
V>Будь ты студентом и показывай подобные мыслительные возможности преподу, он бы влепил тебе неуд сходу. :xz:
В данной ситуации скорее ты уподобляешься нерадивому студенту, из которого без наводящих вопросов признания не вытянешь.
V>Потому что ты знанял такую странную позицию из разряда "вот объясните мне, дураку".
Я вообще не просил объяснять или обсуждать, почему в данных примерах не сработала оптимизация — я подбирал примеры осознанно и исходил из того, что происходящее понятно. Просто их предъявлял.
V>Т.е. это я топики переименовываю
Законом не запрещено, переименовываю где хочу. Не вижу смысла игнорировать столь удобную фичу форумного движка. Это позволяет быстрее ориентироваться в уведомлениях о новых сообщениях.
Данный тред не исключение, где я специально заполняю поле «Тема» — это для меня обычная практика.
Здравствуйте, samius, Вы писали:
S>Дада, я вот тоже для тебя западню заготовил, но вот беда (и смешно и обидно вышло... ) переоценил уровень твоего бэкграунда. И ты пролетел мимо этой засады, даже не поморщился. Ну что ж, попробую тебя оттормозить, оттащить назад и все-таки посадить в эту лужу. S>Хорошо, зафиксируем. Пирс говорит о поведении куска кода. Не знаю, станешь спорить или нет, но поведение куска кода определяется в том числе машинным кодом (если мы говорим о некой машине как исполнителе). Но не каждой инструкцией. Таким образом, есть инструкции, не влияющие на поведение куска кода, а есть — непосредственно влияющие. S>Когда люди из академической/научной и околонаучной среды говорят о поведении кода, они говорят не о том, как ведет себя исполнитель кода, они говорят о некой процедурной абстракции, которая есть мысленная модель того, что люди ожидают от кода, но в виде того, что они хотят получить и из чего, а не каким образом. Именно опираясь на ожидаемое поведение, компиляторы могут заниматься компиляцией и оптимизацией, суперкомпиляторы могут заменять конкретные вызовы значением или таблицей результатов. Одну и ту же функцию, описанную текстом, компилятор имеет право вставить в нескольких местах вызова совершенно различными наборами инструкций. В одном месте заинлайнить, в другом заменить, в третьем подставить код вызова. Таким образом, функция в тексте может быть одна, но наборов инструкций, ей соответствующих может быть несколько. С другой стороны, комипляторы вольны нагородить лишнего говна, которое работать будет, но менять поведение, при этом, не должно. S>Чем определяется поведение кода? Для этого, например, можно использовать математическую абстракцию функции — соответствие между множеством определения и множеством значений. Не для всякого кода такая абстракция удобна, потому можно перейти к множествам состояний исполнителя до/после/или даже во время выполнения кода. С точностью до побочных эффектов, если они есть. Но все равно используется некий абстрактный исполнитель, и чем выше уровень языка, тем более значительна разница между абстрактным исполнителем и конкретным исполнителем. Вторичнымм вопросом по отношению к поведению кода является оценка кол-ва шагов, требуемая для его выполнения. Почему вторичным? Потому что это не влияет на возмножность подмены одной процедуры другой. S>И вот тут я с тобой соглашусь в том, что программистам (по большей части) пофигу на машинные коды, сколько их вариантов, что они там вызывают, а что инлайнят и т.д. Но без машинных кодов конкретный исполнитель "машина" не может обеспечить корректную подмену текста исходника кодом исполнителя. Т.е. код исполнителя имеет значение. Но лишь тот, который ответственен за поведение. То есть, если код функции определения длины списка length по ходу вычислений длины вычислит еще и число пи до тысячного знака и выкинет его, то это не повлияет на поведение кода с точки зрения процедурной абстракции, но, вероятно, при этом введет кого-то в заблуждение в отношении полиморфизма функции length. S>Так вот, возвращаясь к фиксации (выше я просто подстелил соломку, но в другом месте, не в том, где ты мне яму нарыл): Пирс использует в определении поведение куска кода. Но ты мне предложил лишь два варианта, полагаю что мне нужно выбрать из двух. Я выбираю 2, но с оговоркой. Лишь тот машинный код имеет значение, который влияет на поведение функции. Да, при этом, на всю глубину. Если влияет, то на всю глубину. Если что-то не влияет на поведение — не имеет значение, что там.
Давно не видел такого длинного и при этом бессмысленного (одна вода) текста на данном форуме. Ну да ладно, попытаюсь вычленить из него хоть какие-то тезисы.
Для начала напомню, что все последние сообщения у нас идёт дискуссия исключительно о полиморфизме на уровне машинных кодов. Потому что на уровне исходных кодов мы уже давно всё обсудили и пришли к консенсусу, что все версии equal_to (включая шаблонную std::equal_to, с которой всё началось) реализуют параметрический полиморфизм. Сейчас же мы уже обсуждаем исключительно генерируемый этими функциями машинный код, т.е. совсем низкий уровень (ассемблерные инструкции и т.п.). И если ты не готов к дискуссии на таком уровне (например оказалось, что ты даже смутно не представляешь какой код генерируется по тем примерам на Хаскеле, что мы обсуждали), то возможно и не стоило её начинать?
Далее, если говорить про анализ машинных кодов, то там опять же не всё так страшно (произвольно), как тебе мерещится. Во-первых все ключевые вопросы чётко зафиксированы в документациях (открой например стандарт C++ — там чётко указано какие нюансы отдаются на откуп оптимизатору, а каких должны быть фиксированы — на них можно рассчитывать и при программирование под микроконтроллер и под мейнфрейм). А во-вторых, даже если говорить о нюансах зависящих от оптимизатора, то их точно так же можно без проблем обсуждать в деталях. Только при этом необходимо фиксировать в разговоре версии компилятора и опции его запуска, а так же не бояться такой штуки как дизассемблер. И кстати на этом форуме было уже множество дискуссий на таком уровне, с собеседниками имеющими нормальные познания в области оптимизации. Однако мы с тобой в данной дискуссии даже отдалённо не приблизились к подобному уровню — все наши примеры полностью укладывались в самые базовые сценарии генерации кода.
Ну и возвращаясь к твоему ответу на мой вопрос. И так, ты значит выбрал позицию, что для анализа вида полиморфизма некой функции, надо проанализировать не только её машинный код, но и машинный код всех функций в её стеке вызова. Ну правда с какой-то там оговоркой, но это даже веселее в итоге будет. )))
Раз так, то тогда тебя конечно же не затруднит расшифровать почему ad hoc оператор сложения (находящийся в стеке вызова функции apply из нашего примера на Хаскеле) не должен учитываться при анализе функции apply (она же у нас параметрически полиморфная в том числе и по твоему мнению). Видимо это действие той самой магической оговорки? Или нет?
Ну а после твоего ответа я конечно же ещё спрошу почему эти же аргументы не применимы для абсолютно аналогичного случая ad hoc оператора равенства, находящегося в стеке вызова функции my_equal_to.
_>>Где-то в моём примере объявлена или используется функция вида "g = apply f"? ) Не надо подобных дешёвых фокусов. S>В том, что касается дешевых фокусов, используя понятие процедурной абстракции, можно верить тому, что поведение функции apply f не отличимо от поведения функции f, и оно же неотличимо от "g = apply f". Если бы это было не так, то функцию apply с аргументом f нельзя было бы использовать вместо функции f. Но ты ее как раз используешь исходя из сохранения поведения. Значит, должен быть удовлетворен любой подстановкой с сохранением его. Если нет — выполняй f сам.
Объясняю ещё раз на доступном языке. Мы здесь изучаем поведение машинных кодов. Если ты нигде не использовал явно функцию вида "apply f" (а в моём примере такого не было), то в машинных кодах её не будет существовать в принципе. Более того, даже если ты где-то в проекте и используешь её (так что в итоге подобный код будет существовать в итоговом исполняемом файле), то в процессе выполнения моих примеров она всё равно вызываться не будет (всё равно будет прямой вызов нормальной apply с двумя параметрами). Теперь понятно? )
_>>А, ну да) Остроумно. ))) И много таких функций встречается в твоих приложениях? ) S>О, рад что ты оценил. Да, параметрически полиморфных функций в моих приложениях встречается много.
Ну если следовать твоему определению (с исследованием всего стека вызова), то скорее всего ровно ноль. Потому что я что-то сомневаюсь в наличие в твоём приложение этой очаровательной константной функции. )))
S>>>Вообще не получается. Это твои выдумки. Весь стек вызовов функции apply заканчивается на возврате функции, которой ты подашь int или float. И ты либо об этом знаешь, либо никудышный знаток Хаскеля. _>> _>>Ты вот что, серьёзно верил, что каррирование реально существует на уровне машинных кодов? Да если бы кто-то и попытался сделать подобное, то оно работало бы не просто медленно (как нынешний Хаскель), а вообще почти не шевелилось бы (наверное хуже чем какой-нибудь bash). S>Ну причем тут "медленно"?
Притом что:
1. Именно по это причине Хаскель работает не так, как тебе воображалось
2. Именно по этой причине любой вменяемый (знающий хотя бы основы функционирования современных ЦПУ) программист знал бы правильный ответ без обращения к документации ghc. Так что твои заблуждения в данной области наводят на определённые мысли...
_>>https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/HaskellExecution/FunctionCalls — на вот, просвещайся как обстоят дела в реальности, чтобы не писать больше подобных глупостей. S>Вот видишь, согласно понятию процедурной абстракции хаскель может генерить несколько различных тел для одной функции и вызывать их в зависимости от обстоятельств вызова. Сохраняя, при этом поведение, соответствующее execution model. Если завтра технические детали реализации поменяются с "просто медленно" на "вообще почти не шевелилось бы", но сохранится execution model, то на поведение функций apply, f, apply f это не повлияет. Следовательно, сохранится их параметрическая классификация. Будь уверен в этом.
Эм, ты даже такой очевидный текст не можешь нормально воспринять? ) Генерируется ровно один машинный код данной функции. Самый обычный (не с одним аргументом), который ты можешь положить в отдельный бинарный файл. И все вызовы вида "apply f 1" и т.п. (с полным набором аргументов) будут осуществлять прямой вызов этой функции. 80% кода на Хаскеле попадает именно в эту категорию (по этому и более менее шевелится). Плюс к этому, если где-то в приложение встретится отдельная конструкция вида "apply f", то будет сгенерирована (в уже другом бинарном модуле) ещё одна функция, реализующая частичное применение функции apply (естественно через вызов изначальной).
Здравствуйте, itslave, Вы писали:
I>Здравствуйте, alex_public, Вы писали: I>... кстате на счет десктопа. ДЛя дот нета существует множество библиотек визуальных компонентов, всякие там телерики, девекпрессы и прочие инфраджистики. I>А как с этим в мире С++?
Ну ты как раз перечислил нужные конторы, зайди к ним на сайты.
Здравствуйте, Qbit86, Вы писали:
Q>Это в нормальных языках. В C++ исходные коды шаблонов компилятор автора библиотеки в испольняемые файлы не преобразует. Библиотека поставляются пользователю в текстовом виде как есть.
Можно экспортировать специализации шаблонов.
Q>Могут быть свои, могуть быть общие. В Visual Studio двигаются в сторону использования платформы Roslyn как для собственно компиляции, так и сервисов анализа кода.
8 лет пилить библиотеку парсинга C#...
_>>...и какие конкретно примеры в ней работают не так, как тебе нравится. Q>Навигация по разным функциям в Boost Graph Library и в окрестности.
VA или Resharper C++ спасут.
_>>Возможно тебе подскажут IDE, которая делает всё как надо. Q>Надо не мне, а топикстартеру, который озвучивал Visual C++.
Если действительно надо, то купит нужный тул за смешные деньги.
Здравствуйте, itslave, Вы писали:
_>>Ну т.к. стандартной GUI библиотек у C++ нет, то всё зависит от того, какую ты выбрал. Если это скажем Qt (в последнее время претендует на звание лидера в данной области) и базовых контролов не хватает (что довольно редко, т.к. в самой Qt всё крайне кастомизируемо) I>Если взять https://www.devexpress.com/products/net/controls/winforms/grid/ и сравнить со стандартным qt гридом, то сколько % фичеров покроет грид qt из коробки?
Опять ты эту фигню пишешь ))
А если взять тот же teleric grid для Windows UWP, то чем devexpress лучше?
И да, речь идёт о нейтивных контролах для WinRT 8.1+ API.
Здравствуйте, Qbit86, Вы писали:
Q>В C++ огромное множество врождённых недостатков, независимых от «современных инструментов».
У дотнета-то косяков больше намного.
Но ты же им пользуешься и не жужжишь...
А в С++ всего лишь требуется больше контекста для каждого сниппета.
Q>Если топикстартер по твоему совету выберет C++, он просто хлебнёт **вна на ровном месте, по причинам совсем не обусловленным необходимостью.
Тяжелое детство, деревянная обувь.
Бывает.
Q>Прекрасно; а что насчёт препроцессора?
... Q>Если ты откроешь заголовок — какая версия `some_function()` будет «активная»?
Такая же, какая во время компиляции компилятором.
Например, Resharper C++ смотрит в настройки проекта, т.е. делает ровно то же, что делал бы компилятор С++ с этим исходником.
Q>Работает ли навигация внутри «неактивного» фрагмента? Если по F12 Go To Definition внутри открытого заголовочного файла перейти к объявлению/определению функции, к какому из этих двух вариантов перейдёт IDE?
Теперь можешь догадаться.
Q>Вполне может быть — в окружающей меня реальности окологеймдев.
Геймдев разный бывает.
Кто-то скрипты пишет, а кто-то физические движки.
Т.е. кто-то нуб, а кто-то профи.
Q>Но всё-таки: лидер (согласно alex_public) Eclipse CDT перестал бы кривым **вном, каким был несколько лет назад, когда я его в последний раз запускал?
Эклипс не кривой ни разу, он тормозной, а это чуть другое.
Потому что Джава и в Африке Джава. Гуй на ней делать нельзя было.
А так-то вполне сносная лошадка, если не обращать внимание на тормознутость.
Может, тебе после MS VC он показался непривычным?
Сам Эклипс — это ж просто платформа, на которую надо поставить добрый десяток расширений (или специально подготовленную их сборку) и потом уже работать в нём. И прекрасно потом в нём работается.
А что и как ты там смотрел — одному богу известно. Учитывая твои дедуктивные способности, которыми ты тут блещешь, я думаю, что ты просто поставил, запустил, ничего не понял, снёс, а теперь мечешь словами навроде "кривым **вном".
Здравствуйте, vdimas, Вы писали:
Q>>Это в нормальных языках. В C++ исходные коды шаблонов компилятор автора библиотеки в испольняемые файлы не преобразует. Библиотека поставляются пользователю в текстовом виде как есть. V>Можно экспортировать специализации шаблонов.
А если специализаций нет, весь код обобщённый? Или под «специализации шаблонов» ты имел в виду «явные инстансы шаблонов»?
Экспортировать можно только для типов, известных заранее автору библиотеки. Явные инстанцирования для пользовательских типов так не сделать. Такой подход обсуждался в ветке про распухание бинарного кода.
Здравствуйте, Qbit86, Вы писали:
V>>Ты маешься откровенной фигней: V>>
V>>Не наблюдаю такого в отладчике после лёгкой модифиации кода
Q>Твой пример с `push_back()` может ввести неискушённого читателя в заблуждение, дескать, распухание кода побеждено «бинарной склейкой».
Так и есть.
Q>Долг любого сознательного гражданина обратить внимание читателей на сильные ограничения условий подобной оптимизации, желательно с конкретным проверяемым примером. «Не наблюдаю такого в отладчике после лёгкой модифиации кода» как раз и предоставляет такой конкретный пример.
Пффф...
Ты ДЕЙСТВИТЕЛЬНО пытаешься держать коллег за идиотов?
Тебе там с полутыка ответили более одного человека.
Не насторожило разве?
Любой вменяемый коллега и без твоего ломания комедии прекрасно в курсе, о чём речь, тем более, что еще до твоего шоу уже всё написал:
Например, в С++ есть т.н. "бинарная склейка" одинаковых участков кода. Ну вот пусть совершенно разные типы после компиляции создадут идентичный бинарный код некоей ф-ии или метода — такой код будет склеен в единственный экземпляр. Именно это позволяет бороться с распуханием кода после применения шаблонов.
Склеиваемый бинарный код должен быть одинаков. Тчк.
V>>Будь ты студентом и показывай подобные мыслительные возможности преподу, он бы влепил тебе неуд сходу. Q>В данной ситуации скорее ты уподобляешься нерадивому студенту, из которого без наводящих вопросов признания не вытянешь.
Ну, если ты решил побыть в этом месте преподом, то только слепоглухонемым. ))
Заметь, это уже 4-й твой идентичный залёт, когда все нужные ответы были даны задолго до твоих "вопросов".
Поэтому, извини, но неуд.
V>>Потому что ты знанял такую странную позицию из разряда "вот объясните мне, дураку". Q>Я вообще не просил объяснять или обсуждать, почему в данных примерах не сработала оптимизация — я подбирал примеры осознанно и исходил из того, что происходящее понятно. Просто их предъявлял.
Да понятно всё, хосподя.
Только чего потом обижаться, если до этого забавы ради ты решил потыкать в людей палочкой?
Бред, кароч...
Здравствуйте, vdimas, Вы писали:
V>Такая же, какая во время компиляции компилятором.
Во время компиляции компилятором в разных единицах трансляции будут разные версии. Какая из них «такая же»?
V>Например, Resharper C++ смотрит в настройки проекта, т.е. делает ровно то же, что делал бы компилятор С++ с этим исходником.
Версия функции определяется не только настройками проекта. Константы препроцессора могут быть объявлены в любом месте. Например, вне заголовочного файла перед включением этого файла. Глядя только в заголовочный файл с условной компиляцией внутри ты никак не можешь знать, какие ветки будут использоваться компилятором при включении заголовочного файла в разные единицы трансляции. Это могут быть разные ветки в рамках одного проекта.
V>Теперь можешь догадаться.
Похоже, ты просто не читаешь обсуждение в ветке, просто вышел оставить своё исключительно важное мнение.
V>И при этом рядом хватает наглости писать: V>