Здравствуйте, Воронков Василий, Вы писали:
DM>>Спасибо! Занятно, что с полиморфными вариантами компилятор успешно выводит рекурсивный тип, а с обычными вариантами ругается на его рекурсивность.
ВВ>Да, но это ты, видимо, должен пояснить, что там ему не нравится Я все же OCaml слабо знаю.
Заглянул в доку. По умолчанию рекурсивные типы разрешены только с полиморфными вариантами или с объектами. Для других типов рекурсию можно включить ключиком компилятора -rectypes, но это иногда может приводить к сюрпризам.
Recursive types for which there exists a recursive path that does not contain an object or polymorphic variant type constructor are rejected, except when the -rectypes mode is selected.
ВВ>И чем дальше в лес, тем все больше и больше это начинает напоминать Linq
Так и должно быть. Просто здесь состояние передается от вызова к вызову, а не прячется внутри объекта. Пойду еще подумаю, остались ли у меня вопросы.
Здравствуйте, lomeo, Вы писали:
L>Вопрос в другую сторону был поставлен. Почему в Haskell не нужны итераторы. Ответ — потому что ленивость уже решает эти задачи.
Не совсем приемлемый ответ. Все же списки, даже если они будут ленивыми, остаются конкретными структурами данных, а не абстракциями. Итератор шарпа же — это абстракция. Мы можем реализовать итератор поверх любой коллекции или даже без оной (пример — все тот же Range()).
L>Почему нужны в C# — может потому что так удобнее?
+1
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Этот вопрос меня интересует вообще применительно к другому языку, я "перевожу стрелки" на C#, чтобы было проще обсуждать. Т.е. тяжело, неудобно писать — это все понятно. Интересно, дают ли что-либо итераторы, кроме "сахарности"?
Если тебя интересует выражаются ли итераторы шарпа через замыкания (точнее даже будет сказать, через монады) и т.п., то таки да, выражаются. Как и наоборот. Только вот это не говорит, что итераторы шарпа чем-то плохи. Реализация на без ДКА вполне эффективна и проста.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
KO>>Да, итераторы, исключения и любой вид управления control-flow выражается через CPS, вопрос, как всегда в удобстве.
ВВ>Если вопрос *только* в удобстве, почему в C# итераторы присутствуют как отдельная фича,
Да потому что они еще и через ДКА выражаются, и еще несколькими видами. Реализовывать ДКА или CPS вручную — это не очень благодарное занятие. А в виде фичи языка все выглядит просто, императивно (последовательно) и результат получается эффективный.
ВВ>да и компилятор там немало кода генерит?
Компилятор генерирует столько сколько нужно. Реализация получается весьма эффективной. Не хуже чем при использовании CSP.
Кстати, не все такой подход избрали. В F# для аналога генераторов используются Computation Expressions, то есть по сути CPS. В C# 5 появится sync/await. Реализация будет опять же на основе ДКА (точнее даже на основе итераторов). В F# и Nemerle есть аналогичная фича реализованная на базе Computation Expressions. Однако реализация на базе ДКА будет ничем не хуже. Так что возможно в немреле и ее реализуем.
ВВ>Достаточно было бы просто ввести некий сахар "для удобства" и все. Тогда бы у нас была фича, реализованная по классической схеме:
ВВ>- Стандартный паттерн ВВ>- Сахарок сверху, повышающий удобство
Ну, вот Computation Expressions и есть такой подход. Наверно и с итераторами и sync/await можно было так поступить. Но Хейльсберг все в язык тащит.
Но если тогда уж задуматься, то лучшим выходом было бы просто ввести макросы, а уже все подобные детали реализовать на их основе.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Wolverrum, Вы писали:
W>Итератор (курсор) — идиома ООП. W>И вопрос, наверное, следовало бы поставить как: "Почему нужны итераторы" — и вот тут есть довольно резонный ответ — потому что, как правило, ООП-языки не держат функцию за первоклассный объект. Приходится выдумывать в рамках ООП костылёк. Я совершенно не удивлюсь, если мне скажут, что Visitor не нужен, потому что есть map()
А я не удивлюсь если тебе замеят, что шаблон Посетитель и функция map решают разные задачи.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, PoM-PoM 40mm, Вы писали:
PP4>А что такое порядковый номер? Есть масса контейнеров, где он невозможен или бессмысленен. А так можно писать алгоритм, который слабо зависит от контейнера
Это у него такой пунктик. Он весьма странно понимает абстракции. Считает что массив и список это абстракции, а следовательно можно смело пользоваться индексом для выражения порядка элементов списка.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
ВВ>>Т.е. при таком раскладе сама по себе функция-генератор оказывается как бы невостребованной. VD>В указанной ссылке как раз презентация описывающая, что аналог итератора куда лучше чем "хэндл-бэзед ИО".
В презентации описывается реализация паттерна итератор на базе ФВП, о чем я и говорю.
Здравствуйте, VladD2, Вы писали:
L>>Вопрос в другую сторону был поставлен. Почему в Haskell не нужны итераторы. Ответ — потому что ленивость уже решает эти задачи. VD>Не совсем приемлемый ответ. Все же списки, даже если они будут ленивыми, остаются конкретными структурами данных, а не абстракциями. Итератор шарпа же — это абстракция. Мы можем реализовать итератор поверх любой коллекции или даже без оной (пример — все тот же Range()).
Под ленивостью я понимал ленивость, а не ленивые списки. А под итераторами — функции с yield.
Здравствуйте, lomeo, Вы писали:
L>>>Вопрос в другую сторону был поставлен. Почему в Haskell не нужны итераторы. Ответ — потому что ленивость уже решает эти задачи. VD>>Не совсем приемлемый ответ. Все же списки, даже если они будут ленивыми, остаются конкретными структурами данных, а не абстракциями. Итератор шарпа же — это абстракция. Мы можем реализовать итератор поверх любой коллекции или даже без оной (пример — все тот же Range()).
L>Под ленивостью я понимал ленивость, а не ленивые списки.
Ну, и что меняет ленивость в этом плане? Что ты возвращаешь из своих фукнций списки или некие классы типов вроде фолбадб?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
L>>Под ленивостью я понимал ленивость, а не ленивые списки. VD>Ну, и что меняет ленивость в этом плане? Что ты возвращаешь из своих фукнций списки или некие классы типов вроде фолбадб?
Что значит что меняет? Ты сказал вещи, совершенно не относящиеся к моему ответу, т.е. понял мой ответ как-то по своему.
Ленивость в этом плане меняет всё. foreach может замениться, например, на простой вызов функции для обхода ленивой структуры. Специальная конструкция не нужна.
Кстати, а какой будет typeof у результата функции с yield-ами?
Здравствуйте, lomeo, Вы писали:
L>Ленивость в этом плане меняет всё. foreach может замениться, например, на простой вызов функции для обхода ленивой структуры. Специальная конструкция не нужна.
А мне foreach нравится. Как-то недвусмысленнен он. Отлаживат и читать код с foreach легче, чем код с ФВП.
Здравствуйте, hardcase, Вы писали:
L>>Ленивость в этом плане меняет всё. foreach может замениться, например, на простой вызов функции для обхода ленивой структуры. Специальная конструкция не нужна. H>А мне foreach нравится. Как-то недвусмысленнен он. Отлаживат и читать код с foreach легче, чем код с ФВП.
Во-первых, foreach можно очень близко повторить.
class ForEach f where
toEnumerator :: f a -> [a]
foreach :: (ForEach f, Monad m) => f a -> (a -> m ()) -> m ()
foreach = mapM_ . toEnumerator
foreach collection (\item ->
doSomethingWith item
)
Во-вторых, foreach поощряет стиль "берём коллекцию, а работаем с элементом", вместо более высокоуровневого стиля "берём коллекцию и с ней же и работаем" — сравни с LINQ-ом.
В-третьих, да, видимо для большинста код с foreach проще, чем с ФВП. Но выводы из этого можно сделать какие угодно
Здравствуйте, hardcase, Вы писали:
L>>В-третьих, да, видимо для большинста код с foreach проще, чем с ФВП. Но выводы из этого можно сделать какие угодно H>В простых сценариях map/filter да удобны, а вот fold-ы уже наводят тоску при рефакторинге.
fold-ы низкоуровневы, ага. Лучше на них описать более абстрактные функции и с ними уже работать.
А можно пример, чтобы понять о чём речь?
Здравствуйте, lomeo, Вы писали:
L>fold-ы низкоуровневы, ага. Лучше на них описать более абстрактные функции и с ними уже работать. L>А можно пример, чтобы понять о чём речь?
Эт мой немерловый опыт написания и поддержки кода, работающего со списками. Впрочим, foreach в Nemerle это больше чем просто конструкция для итерации.
Здравствуйте, VladD2, Вы писали:
VD>Ну, и что меняет ленивость в этом плане? Что ты возвращаешь из своих фукнций списки или некие классы типов вроде фолбадб?
Ленивость меняет то, что свертка сворачивает контейнер в "итератор" лениво.
toList :: Foldable t => t a -> [a]
toList = foldr (:) []
А в энергичном языке придется делать ленивую свертку, чтобы реализовать аналог Foldable — что сложнее.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Здравствуйте, hardcase, Вы писали:
H>В простых сценариях map/filter да удобны, а вот fold-ы уже наводят тоску при рефакторинге.
Это все изменится с опытом. Дело привычки, и со временем fold-ы будут наводить радость при рефакторинге, потому как такие вещи позволяют рефакторить автоматически и полуавтоматически довольно сложные вещи. Почитайте "Pearls of functional algorithm design" Ричарда Берда.
Здравствуйте, lomeo, Вы писали:
L>А можно пример, чтобы понять о чём речь?
Вот например (красный FoldLeft в строке 83). Автор этого шедевра этой жести — ваш покорный слуга. После 20 минутной медитации над FoldLeft-ом + RevMap-ом переписал на два foreach-а. Код стал понятнее и потом пережил еще пару рефакнторингов — это конвертер switch конструкции C# в match Nemerle. Иммутабельность это хорошо, когда без фанатизма.
Здравствуйте, Klapaucius, Вы писали:
K>Здравствуйте, hardcase, Вы писали:
H>>В простых сценариях map/filter да удобны, а вот fold-ы уже наводят тоску при рефакторинге.
K>Это все изменится с опытом. Дело привычки, и со временем fold-ы будут наводить радость при рефакторинге, потому как такие вещи позволяют рефакторить автоматически и полуавтоматически довольно сложные вещи.
Покачто мой опыт говорит обратное. Рефакторинг FoldLeft со сложной логикой внутри через некоторое время после его написания способен заставить автора всерьез пересмотреть свое отношение к программированию.