Здравствуйте, GarryIV, Вы писали:
GIV>Как только ключевые игроки рынка (MS, IBM, Oracle и тд и тп) сделают ставку на один из них. GIV>Что означает никогда. GIV>Хотя бы потому что NIH.
F# изобретен в Microsoft Research, и Microsoft уже сделал на него ставку.
Здравствуйте, nikov, Вы писали:
N>F# изобретен в Microsoft Research, и Microsoft уже сделал на него ставку.
Чем больше пишу на F#, тем сильнее уверен, что этот язык намнооого дальше от мейнстрима (ооочень далеко), чем Scala. По началу был просто ад, в основном из-за синтаксиса (сейчас он очень нравится). После продолжительного изучения писать на F# получается очень медленно, к сожалению.
Scala намного более дружественна и можно разрабатывать практически как на java с плюшками. С другой стороны система типов слишком переусложнена для мейнстрима и наверняка кто-нибудь будет этим злоупотреблять (у меня никак не получается въехать в параметрический полиморфизм высших порядков и экзистенциональные типы, а особенно в их юзкейсы).
Мне кажется, что если Scala не будут переусложнять всяким матаном и неявными параметрами, то получиться вполне себе великолепный мейнстрим-язык, замена Java. И мне в .net-стеке будет очень завидно, что в java-стеке есть такой язык
Здравствуйте, Пельмешко, Вы писали:
П>Мне кажется, что если Scala не будут переусложнять всяким матаном и неявными параметрами, то получиться вполне себе великолепный мейнстрим-язык, замена Java. И мне в .net-стеке будет очень завидно, что в java-стеке есть такой язык
Здравствуйте, Воронков Василий, Вы писали:
ВВ>А на CLR они забили разве? Он же был и под CLR.
Вроде бы несколько последних версий Scala не выпущены под CLR.
Правда, есть workaround, позволяющий скомпилировать Scala под JVM, а потом запустить JVM под CLR с помощью IKVM.
Здравствуйте, nikov, Вы писали:
N>Вроде бы несколько последних версий Scala не выпущены под CLR. N>Правда, есть workaround, позволяющий скомпилировать Scala под JVM, а потом запустить JVM под CLR с помощью IKVM.
Интересно, у них что, были совершенно отдельные компиляторы под эти бекэнды? Казалось бы логичный путь делать компилятор в свой байт-код, а потом уже трансляторы в целевой байт-код. При таком подходе можно в общем случае менять язык, при этом вообще не внося изменений в компиляторы под целевые платформы.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Интересно, у них что, были совершенно отдельные компиляторы под эти бекэнды? Казалось бы логичный путь делать компилятор в свой байт-код, а потом уже трансляторы в целевой байт-код. При таком подходе можно в общем случае менять язык, при этом вообще не внося изменений в компиляторы под целевые платформы.
Там есть существенное различие в компиляции дженериков: под JVM используется erasure, под CLR — не используется. Но CLR не поддерживает higher-kinded generics, поэтому, видимо, для их компиляции тоже придется использовать частичное erasure. Это одна из основных проблем, стоящих на пути компиляции последних версий Scala под CLR.
По рынку труда пока что полная задница. Есть отдельные фирмы которые применяют немерл (и других) на свой страх и риск, но назвать это рынком язык не поднимается.
Думаю, что ситуация будет меняться, но на это может уйти 10 и более лет. Возможно, что (опять же в течении десятилетия или более) созреют архитекторы развивающие уже популярные языки, так что имеющиеся технологии могут попасть в эти языки. Но пока что на этом фронте все совсем глухо.
В несколько привилегированном положении находится F#, так как его формально поддержал MS. Но что-то мне кажется, что перспективы у этого языка даже хуже чем у Скалы и Немерла.
С другой стороны эта ситуация играет на руку тем кто готов рискнуть, так как они могут снять сливки. Ведь когда на данные технологии начнут переходить массы, то получить выгоду от них уже будет крайне не просто (конкретная будет большая).
Так что я бы советовал не дожидаться когда серые массы начнут переползать на новые технологии, а думать своими мозгами. Если вы видите что язык может дать вам конкретные преимущества, то смело пробуйте его в деле.
С программистами проблем не будет (по крайней мере для немерла, так как любой талантливый C#-программист может быть в течении месяца переучен на немерл). Скажу даже больше. Сейчас перечисленными языками занимаются в основном очень одаренные люди. Это точно не балласт (офисный планктон), а люди влюбленные в свою профессию, и при том люди очень талантливые.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Пельмешко, Вы писали:
П>Scala намного более дружественна и можно разрабатывать практически как на java с плюшками.
Видимо потому, что ты с Явы перепрыгивал. Да?
П>(у меня никак не получается въехать в параметрический полиморфизм высших порядков и экзистенциональные типы, а особенно в их юзкейсы).
Ты случаем F# и Haskell не перепутал? Перечисленные фичи есть только в расширениях (если не ошибаюсь пока что нестандартных) Haskell-я. В F# используется система типов адаптированная для дотнета.
П>Мне кажется, что если Scala не будут переусложнять всяким матаном и неявными параметрами, то получиться вполне себе великолепный мейнстрим-язык, замена Java.
Да он уже получился. Что ждать то?
П> И мне в .net-стеке будет очень завидно, что в java-стеке есть такой язык
Немерл ничем не уступает Скале. Более того он как раз удовлетворяет твоим критериям — он очень простой.
Ну, а макросы делают его на порядок мощнее Скалы и F# вместе взятых.
Так что просто пора прекратить ждать от моря погоды и попробовать.
ЗЫ
В прочем, вопрос темы был совсем не о том. Вы как всегда увели тему в сторону.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
П>>Мне кажется, что если Scala не будут переусложнять всяким матаном и неявными параметрами, то получиться вполне себе великолепный мейнстрим-язык, замена Java. И мне в .net-стеке будет очень завидно, что в java-стеке есть такой язык
ВВ>А на CLR они забили разве? Он же был и под CLR.
Он там всегда был не родным. Как минимум не совместима система типов. Скала рассчитана на медленные, но гибкие дженерики явы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, nikov, Вы писали:
N>Но CLR не поддерживает higher-kinded generics, поэтому, видимо, для их компиляции тоже придется использовать частичное erasure.
А такое вообще возможно?
И бывают ли в природе reified higher-kinded generics?
Здравствуйте, nikov, Вы писали:
N>Там есть существенное различие в компиляции дженериков: под JVM используется erasure, под CLR — не используется. Но CLR не поддерживает higher-kinded generics, поэтому, видимо, для их компиляции тоже придется использовать частичное erasure. Это одна из основных проблем, стоящих на пути компиляции последних версий Scala под CLR.
Не очень понял, в чем проблема с генериками В Джава, мне казалось, реализация генериков должна быть сильно проще, т.к. частью системы типов являются только референс-типы вроде Integer, которые уже обворачивают примитивы. Проще говоря, генерики должны быть просто сахаром к обычным полиморфным коллекциям, работающим через Object. Казалось бы — какие проблемы перенести это на .NET или даже сделать лучше.
Здравствуйте, VladD2, Вы писали:
П>>(у меня никак не получается въехать в параметрический полиморфизм высших порядков и экзистенциональные типы, а особенно в их юзкейсы).
VD>Ты случаем F# и Haskell не перепутал? Перечисленные фичи есть только в расширениях (если не ошибаюсь пока что нестандартных) Haskell-я. В F# используется система типов адаптированная для дотнета.
П>>(у меня никак не получается въехать в параметрический полиморфизм высших порядков и экзистенциональные типы, а особенно в их юзкейсы).
VD>Ты случаем F# и Haskell не перепутал? Перечисленные фичи есть только в расширениях (если не ошибаюсь пока что нестандартных) Haskell-я. В F# используется система типов адаптированная для дотнета.
Здравствуйте, Mystic, Вы писали:
M>Имхо, для них нужны программисты.
Их больше чем может показаться. Причем их качество в разы выше среднего уровня.
M>Лично мне тяжело перестраиваться под такой стиль, как по минному полю идешь.
Можно примеры? Точнее обще, объяснить о каком минном поле идет речь?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
M>>Имхо, для них нужны программисты.
VD>Их больше чем может показаться. Причем их качество в разы выше среднего уровня.
Здравствуйте, nikov, Вы писали:
VD>>Ты случаем F# и Haskell не перепутал? Перечисленные фичи есть только в расширениях (если не ошибаюсь пока что нестандартных) Haskell-я. В F# используется система типов адаптированная для дотнета.
N>Как я понял, речь идет о Scala.
Странно. Вроде бы ход мыли изначальный был про F#.
А откуда в Скале "экзистенциональные типы" и на фиг они там нужны?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, nikov, Вы писали:
VD>>Их больше чем может показаться. Причем их качество в разы выше среднего уровня. N>А цена?
Многократно окупается качеством.
Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Главным образом, их туда вводили для интероперабельности с джавовскими wildcards (которые тоже являются урезанной разновидностью экзистенциальных типов).
Ну и, вообще, это сильный инструмент для абстракции.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Пельмешко, Вы писали:
П>>Scala намного более дружественна и можно разрабатывать практически как на java с плюшками.
VD>Видимо потому, что ты с Явы перепрыгивал. Да?
Нет, никогда на Java ничего не писал, лишь интересовался некоторыми особенностями generic'ов. Я просто слышал распространённое мнение, что можно на Scala можно писать очень java-like, у меня сложилось точно такое же впечатление.
П>>(у меня никак не получается въехать в параметрический полиморфизм высших порядков и экзистенциональные типы, а особенно в их юзкейсы).
VD>Ты случаем F# и Haskell не перепутал? Перечисленные фичи есть только в расширениях (если не ошибаюсь пока что нестандартных) Haskell-я. В F# используется система типов адаптированная для дотнета.
Я про Scala говорил же, внимательнее
П>>Мне кажется, что если Scala не будут переусложнять всяким матаном и неявными параметрами, то получиться вполне себе великолепный мейнстрим-язык, замена Java.
VD>Да он уже получился. Что ждать то?
Мне кажется можно вполне очень легко разрабатывать, практически игнорируя матан, который там есть сейчас — но это сугубо ИМХО. Всякими IDE скрыть implicit-параметры, сигнатурки попроще станут и т.п...
П>> И мне в .net-стеке будет очень завидно, что в java-стеке есть такой язык
VD>Немерл ничем не уступает Скале. Более того он как раз удовлетворяет твоим критериям — он очень простой. VD>Ну, а макросы делают его на порядок мощнее Скалы и F# вместе взятых.
Мне очень хочется познакомиться с макросами лиспа/немерле, но это лишь из любознательности. "Задела на будущее" не вижу никакого, к сожалению.
И ещё, честно говоря, не представляю как у вас там в Немерлях дебажится код, пропущенный через десяток макросов.
Здравствуйте, WolfHound, Вы писали:
VD>>>Их больше чем может показаться. Причем их качество в разы выше среднего уровня. N>>А цена? WH>Многократно окупается качеством. WH>Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать.
Вот и получается такая ниша: проекты с большим количеством алгоритмически сложных вещей и немаленьким бюджетом, например, финансовая сфера. Как я вижу, ее уверенно занимает F#.
Здравствуйте, VladD2, Вы писали:
M>>Лично мне тяжело перестраиваться под такой стиль, как по минному полю идешь. VD>Можно примеры? Точнее обще, объяснить о каком минном поле идет речь?
Очень просто, берешь простую задачу, пытаешься ее решить и буксуешь, не в состоянии найти решение. Или борясь с непонятными ошибками. Да, на Nemerle можно писать в императивном ключе, но... смысл? Просто использовать другой синтаксис? Если брать книгу Душкина по Haskell, то там надо кучу интеллектуального труда только для того, чтобы разобраться в том, как вся работа со списками выражается через три общие функции. Такой высокий полет сознания мне недоступен. Если брать макросы Nemerle, то после того, как я понял, что адский синтаксис на нем реализовать нельзя, то немного охладел к ним. По крайней мере, я не знаю, как их написать.
Вторая проблема в том, что мне наиболее близка императивная форма. Когда я вижу что-то декларативное, которое вроде бы делает то, что мне надо, но я в этом не уверен на все 100%, я начинаю нервничать. И пока все не переведу в императивный вид, не успокоюсь. Соответственно лишняя работа, падение скорости разработки.
Здравствуйте, WolfHound, Вы писали:
VD>>>Их больше чем может показаться. Причем их качество в разы выше среднего уровня. N>>А цена? WH>Многократно окупается качеством. WH>Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать.
А много ли их, сложных вещей, в мейнстриме?
Здравствуйте, vmpire, Вы писали:
V>Здравствуйте, WolfHound, Вы писали:
VD>>>>Их больше чем может показаться. Причем их качество в разы выше среднего уровня. N>>>А цена? WH>>Многократно окупается качеством. WH>>Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать. V>А много ли их, сложных вещей, в мейнстриме?
мало. Но иногда бывает. ИМХО сила Nemerle или Scala в том, что на них мона писать так же как в C#/Java, но при случае — заюзать макросы или этот параметрический полиморфизм высших порядков... В рамках одного языка. Ну и конечно всякие приятные "мелочи" типа АТД и патерн мачинга.. Это то мона вобоще в любом проэкте заюзать с пользой..
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, nikov, Вы писали:
WH>Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать.
Их пишу на чистом C Что-то не видно много сильных шахматных программ на всяких функциональных языках. Алгоритмическая сложность часто завязана на производительность...
Здравствуйте, Mystic, Вы писали:
M>Вторая проблема в том, что мне наиболее близка императивная форма. Когда я вижу что-то декларативное, которое вроде бы делает то, что мне надо, но я в этом не уверен на все 100%, я начинаю нервничать. И пока все не переведу в императивный вид, не успокоюсь. Соответственно лишняя работа, падение скорости разработки.
Для этого обычно разобраться лишь в том, что там под капотом. Всё переписывать совсем не обязательно.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Для этого обычно разобраться лишь в том, что там под капотом. Всё переписывать совсем не обязательно.
Разобраться мало, надо научиться этим пользоваться. Читаешь Душкина, вроде все понятно. Доходишь до упражнений, и сразу: "Э-э-э-э... Как??!! Дайте мне переменные и циклы!!!" Вторая проблема в том, чтобы набраться терпения и довести что-то до конца. Мучаешься, мучаешься, потом забиваешь и делаешь на чем-то более понятном. Или просто забиваешь
Здравствуйте, nikov, Вы писали:
N>F# изобретен в Microsoft Research, и Microsoft уже сделал на него ставку.
Когда начали продвигать F# в иНете появились заметки из серии "F# and WPF". Однако, как потом оказалось, в F# нет public static readonly полей. А без этого в WPF никуда. Это я о том, как всякие мелочи мешают задействовать этот язык даже при желании.
Здравствуйте, Mystic, Вы писали:
WH>>Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать. M>Их пишу на чистом C Что-то не видно много сильных шахматных программ на всяких функциональных языках. Алгоритмическая сложность часто завязана на производительность...
На производительность завязана вообще-то ресурсоёмкость алгоритмов, а не их алгоритмическая сложность. Сложность там как раз появляется в попытке решить одновременно в одном месте как саму основную задачу, так и алгоритм её оптимизации. Отсюда якобы сложность завязана на производительность. На самом деле всё совсем наоборот — в погоне за производительностью мы усложняем задачу.
Основным же инструментом для решения алгоритмически сложных задач в перечисленных языках является паттерн-матчинг, который позволяет десяток запутанных if-ов заменить одним простым и понятным паттерном. Плюс конечно же множество других плюшек и полезняшек, которые в итоге сильно повышают выразительность конкретного языка как инструмента разработки.
Ко всему прочему в Немерле мы ещё имеем макросы. Как известно, сложность разрабатываемого продукта не может превышать на порядок сложности инструмента, на котором этот продукт разрабатывается. Так вот макросы Немерле позволяют самостоятельно разрабатывать такие инструменты и получать уже два порядка, а не один.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Jack128, Вы писали:
WH>>>Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать. V>>А много ли их, сложных вещей, в мейнстриме?
J>мало. Но иногда бывает. ИМХО сила Nemerle или Scala в том, что на них мона писать так же как в C#/Java, но при случае — заюзать макросы или этот параметрический полиморфизм высших порядков... В рамках одного языка. Ну и конечно всякие приятные "мелочи" типа АТД и патерн мачинга.. Это то мона вобоще в любом проэкте заюзать с пользой..
Это в теоретической реальности. А в реальной — 80% ищущих работу на .NET и C# толком не знают.
А макросы или прочие "мелочи" — так это вообще высший пилотаж. Там же надо, страшно подумать, документацию читать!
С другой стороны — для мейнстрима нужна критическая масса заказчиков, которые согласятся вложить свои собственные деньги в проект на языке, поддерживаемом никому особо не известной французской университетской группой LAMP Group (Scala) или другими студентами, только из Польши (Nemerle), а не одним из лидеров отрасли (MS или Sun).
Здравствуйте, Mystic, Вы писали:
WH>>Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать.
M>Их пишу на чистом C Что-то не видно много сильных шахматных программ на всяких функциональных языках. Алгоритмическая сложность часто завязана на производительность...
Перебирать варианты это сложный алгоритм? Хотя, может хорошая шахматная программа и сложная, но написать любую программу можно и на асемблере, особенно когда все процессорное время занимает маленький кусок кода.
На ФП все-таки многие алгоритмы компактнее, а оптимизацией программ должен заниматься компьютер а не человек, если эти оптимизации сильно портят код (раздувают и искажают).
Функциональные программы потенциально легче поддаются оптимизации компилятором.
Хотя, пока к сожалению компиляторы MS не очень хотят заниматься оптимизацией.
Вот пример на F#, функция складывающая два числа:
let public TestFunc p1 p2=
let (e1,e2) = match p1 with
|p1 when p1>0 -> (p2,p1)
| _ -> (p1,p2)
e1+e2
Это после компиляции в release с оптимизацией. Такое показывает рефлектор.
Сложение двух чисел через динамическую память
[CompilationArgumentCounts(new int[] { 1, 1 })]
public static int TestFunc(int p1, int p2)
{
Tuple<int, int> tuple = (p1 <= 0) ? new Tuple<int, int>(p1, p2) : new Tuple<int, int>(p2, p1);
return (tuple.get_Item1() + tuple.get_Item2());
}
Здравствуйте, vmpire, Вы писали:
V>Это в теоретической реальности. А в реальной — 80% ищущих работу на .NET и C# толком не знают. V>А макросы или прочие "мелочи" — так это вообще высший пилотаж. Там же надо, страшно подумать, документацию читать! V>С другой стороны — для мейнстрима нужна критическая масса заказчиков, которые согласятся вложить свои собственные деньги в проект на языке, поддерживаемом никому особо не известной французской университетской группой LAMP Group (Scala) или другими студентами, только из Польши (Nemerle), а не одним из лидеров отрасли (MS или Sun).
Вот интересно, Влад и тебя так же грязью обольет, как и меня, когда я те же самые слова писал с год назад? Или тебя все-таки минет чаша сия?
Здравствуйте, Silver_s, Вы писали:
S_>Здравствуйте, Mystic, Вы писали:
WH>>>Алгоритмически сложные вещи ты на жапошарпах просто озвереешь писать.
M>>Их пишу на чистом C Что-то не видно много сильных шахматных программ на всяких функциональных языках. Алгоритмическая сложность часто завязана на производительность...
S_> Перебирать варианты это сложный алгоритм? Хотя, может хорошая шахматная программа и сложная, но написать любую программу можно и на асемблере, особенно когда все процессорное время занимает маленький кусок кода.
Шахматная программа это не только перебор вариантов при помощи альфа-бета. Это еще и быстрая генерация ходов, завязанная на конкретном представлении позиции (например, magic bitboard), это настройка оценочной функции, это всякие эвристики, управляющие перебором (например, форсированный вариант, ходы-киллеры, нулевой ход, Z-Orbice). Еще надо модифицировать перебор под режим анализа (предлагать несколько линий). Плюс сложность в том, что непонятно, как то или иное новшество повлияет на силу игры. И надо предлагать методы исправления некоторых слабостей программы, чтобы при этом не сильно задеть все остальное. Плюс многопоточность + создание вычислительного кластера.
Сложность задачи характеризует хотя бы тот факт, что программа Deep Blue, которая выполнялась на компьютере, который в несколько раз по производительности обходит персоналки, сейчас по качеству игры проигрывает персоналкам.
Вроде бы, с одной стороны, программирование шахмат как раз отвечает всем преимуществам фунциональных языков, а на практике...
Здравствуйте, nikov, Вы писали:
N>F# изобретен в Microsoft Research, и Microsoft уже сделал на него ставку.
Сам по себе F# достаточно приятный и фичи и синтаксис и интеграция с .Net
Но. Мейнстрим как я понимаю это большие проекты кучи файлов разбросанных по разным папкам.
В связи с этим философский вопрос. Почему они сделали F# без поддержки заглядывания вперед, forward declarations (или как там оно называется). Все что выше по тексту F# вобще не видит.
Это из-за того что компилятор пока не смогли хороший написать, или в самом языке некоторые фичи принципиально не позволяют это сделать? Считают это за нормальную фичу и не собираются исправлять?
Сделали специальную команду в менюшке, чтобы задавать в каком порядке компилировать файлы проекта.
Сделали header файлы как в C++ чтобы forward declarations задавать. От этой гадости мэйнстрим начал уходить, а тут опять предлагают header файлы.
И непонятно почему F# даже внутри списка параметров функции не может вперед заглянуть. Это временные недостатки компилятора, или так и задуманно?
//ошибка, не может определить тип e, надо писать fun (e:SomeStruct) -> ....
let F (lst:List<SomeStruct>) : List<int> =
List.map (fun e -> e.Fld1 - e.Fld2) lst
//если lst перекинуть вперед то тип определяется
let F (lst:List<SomeStruct>) : List<int> =
lst|> List.map (fun e -> e.Fld1 - e.Fld2)
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Mystic, Вы писали:
IT>На производительность завязана вообще-то ресурсоёмкость алгоритмов, а не их алгоритмическая сложность. Сложность там как раз появляется в попытке решить одновременно в одном месте как саму основную задачу, так и алгоритм её оптимизации. Отсюда якобы сложность завязана на производительность. На самом деле всё совсем наоборот — в погоне за производительностью мы усложняем задачу.
Ну я согласен, что шахматы простая задача: написал генератор ходов + полный перебор да забыл. Должен за конечное время выдать наилучший ход И во многих других случаях если максимально забивать на производительность, то можно найти тривиальные решения, плюс прекрасно работает декомпозиция. Представить сложный алгоритм, для которого производительность не была бы критичной... Мне даже ничего не приходит на ум
Здравствуйте, Lloyd, Вы писали:
V>>Это в теоретической реальности. А в реальной — 80% ищущих работу на .NET и C# толком не знают. V>>А макросы или прочие "мелочи" — так это вообще высший пилотаж. Там же надо, страшно подумать, документацию читать! V>>С другой стороны — для мейнстрима нужна критическая масса заказчиков, которые согласятся вложить свои собственные деньги в проект на языке, поддерживаемом никому особо не известной французской университетской группой LAMP Group (Scala) или другими студентами, только из Польши (Nemerle), а не одним из лидеров отрасли (MS или Sun).
L>Вот интересно, Влад и тебя так же грязью обольет, как и меня, когда я те же самые слова писал с год назад? Или тебя все-таки минет чаша сия?
Перечитал — да, забавная была дискуссия.
Пока что остался при своём мнении.
Здравствуйте, Mystic, Вы писали:
M>Представить сложный алгоритм, для которого производительность не была бы критичной... Мне даже ничего не приходит на ум
Например, алгоритм, результат работы которого сохраняется каким-либо образом и затем многократно используется.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Пельмешко, Вы писали:
П>Мне очень хочется познакомиться с макросами лиспа/немерле, но это лишь из любознательности. "Задела на будущее" не вижу никакого, к сожалению.
Плохо смотришь.
П>И ещё, честно говоря, не представляю как у вас там в Немерлях дебажится код, пропущенный через десяток макросов.
Отладчиком.
Никаких проблем не возникает.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Пельмешко, Вы писали:
П>Чем больше пишу на F#, тем сильнее уверен, что этот язык намнооого дальше от мейнстрима (ооочень далеко), чем Scala. По началу был просто ад, в основном из-за синтаксиса (сейчас он очень нравится). После продолжительного изучения писать на F# получается очень медленно, к сожалению.
Почему-то от прямого предка F# OCaml'а такого впечатления нет. Наоборот он достаточно легко изучается, в пределах нескольких месяцев
и подмножество языка на котором уже можно вполне нормально работать очень простое.
Вот и разработчики XenServer это подтверждают:
And, secondly,
we have found that previous OCaml experience is not a prerequisite
for hiring into OCaml-programming positions.
In fact, of the 12 engineers hired, only 2 had prior experience
of OCaml; the other 10 learnt OCaml after they started work at
XenSource or Citrix. Interestingly, having to learn OCaml did not
make a big difference to the training time of the new engineers:
the 10 engineers that did not know OCaml became productive at
about the same speed as the 2 engineers that did have prior OCaml
experience
Здравствуйте, Mystic, Вы писали:
M>Имхо, для них нужны программисты. Лично мне тяжело перестраиваться под такой стиль, как по минному полю идешь.
Ну те же разработчики Xen пишут:
Despite concerns raised at the start of the XAPI project, the MTT
has had no difficulty in finding and hiring good OCaml programmers,
and has been able to grow at a comparable rate to the other
XenServer teams that used mainstream languages. From October
2006 to April 2010, 12 engineers have been hired into OCamlprogramming
positions (roughly a quarter of all XenServer engineers
hired over the period).
Здравствуйте, nikov, Вы писали:
N>http://www.google.ru/search?q=existential+types+Scala
N>Главным образом, их туда вводили для интероперабельности с джавовскими wildcards (которые тоже являются урезанной разновидностью экзистенциальных типов). Ну и, вообще, это сильный инструмент для абстракции.
Для абстракции в ООЯ нужно применять ООП. Мне кажется, что они уходят не в ту степь. Вместо простого и удобного языка для массового рынка они уходят в нишу "крутых" (читать как переусложненных) языков а-ля Хаскель.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vmpire, Вы писали:
V>С другой стороны — для мейнстрима нужна критическая масса заказчиков, которые согласятся вложить свои собственные деньги в проект на языке, поддерживаемом никому особо не известной французской университетской группой LAMP Group (Scala) или другими студентами, только из Польши (Nemerle), а не одним из лидеров отрасли (MS или Sun).
MS c F# тоже в этом списке.
Также и опять MS + университет Глазго — Haskell.
Ну или вполне известный университет INRIA — OCaml
Здравствуйте, Пельмешко, Вы писали:
П>Нет, никогда на Java ничего не писал, лишь интересовался некоторыми особенностями generic'ов. Я просто слышал распространённое мнение, что можно на Scala можно писать очень java-like, у меня сложилось точно такое же впечатление.
А у меня почему-то сложилось обратное впечатление. Все же Скала — это смесь из ООП и ФП, что накладывает сильный отпечаток на стиль программирования. Кроме того Скала ни сколько не мимикрирует под Яву, что не позволяет людям владеющим навыками ява-программиста быстро начать писать на Скале. Таким свойством, как раз, скорее обладает Немерл. При его разработке задача мимикрии ставилась.
П>Я про Scala говорил же, внимательнее
Ясно. Просто ты как-то не к месту вставил F#, и я так понял что речь о нем.
П>>>Мне кажется, что если Scala не будут переусложнять всяким матаном и неявными параметрами, то получиться вполне себе великолепный мейнстрим-язык, замена Java.
VD>>Да он уже получился. Что ждать то?
П>Мне кажется можно вполне очень легко разрабатывать, практически игнорируя матан, который там есть сейчас — но это сугубо ИМХО. Всякими IDE скрыть implicit-параметры, сигнатурки попроще станут и т.п...
Я так и не понял что тебе конкретно кажется. Скала есть и это вполне сформировавшийся язык который отлично заменяет Яву.
П>Мне очень хочется познакомиться с макросами лиспа/немерле, но это лишь из любознательности. "Задела на будущее" не вижу никакого, к сожалению.
Все же прежде чем говорить о "Задела на будущее" неплохо было бы сначала познакомиться с предметом обсуждения. Я так как раз вижу то самое будущее в сращивании парадигм — ООП, ФП и МП (мета-программирование). Причем МП — это пожалуй самое плохо исследованная парадигм. С ее помощью открываются новые способы решения задач. В качестве примеров могу привести Nemerle on rails и PerGrammar
в составе Nemerle-проектов.
П>И ещё, честно говоря, не представляю как у вас там в Немерлях дебажится код, пропущенный через десяток макросов.
Дык тут нечего представлять. Тут надо скачать и попробовать. Ты будешь очень удевлен, но отладка кода с макросами ничем не отличается от отладки кода который написан на языке в котором похожие фичи встроены в язык. Просто ставишь точки останова в коде и бегаешь по коду смотря переменные.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vmpire, Вы писали:
L>>Вот интересно, Влад и тебя так же грязью обольет, как и меня, когда я те же самые слова писал с год назад? Или тебя все-таки минет чаша сия? V>Перечитал — да, забавная была дискуссия.
Это ты еще не знаешь её продолжения. Но дабы не провоцировать, лучше промолчу.
Здравствуйте, Silver_s, Вы писали:
S_>Но. Мейнстрим как я понимаю это большие проекты кучи файлов разбросанных по разным папкам. S_>В связи с этим философский вопрос. Почему они сделали F# без поддержки заглядывания вперед, forward declarations (или как там оно называется). Все что выше по тексту F# вобще не видит. S_>Это из-за того что компилятор пока не смогли хороший написать, или в самом языке некоторые фичи принципиально не позволяют это сделать? Считают это за нормальную фичу и не собираются исправлять?
Кое какие предекларация у них есть. Подробности лучше у Никова выяснить.
Ну, а последовательность файлов нужна в следствии наличия глобального вывода типов и довольно примитивного алгоритма вывода типов. По тем же причинам нет, например, перегрузки для чего-бы то ни было кроме методов.
S_>Сделали специальную команду в менюшке, чтобы задавать в каком порядке компилировать файлы проекта. S_>Сделали header файлы как в C++ чтобы forward declarations задавать. От этой гадости мэйнстрим начал уходить, а тут опять предлагают header файлы.
Это уши ОКамла. Язык ведь не новый. Это адаптированный ОКамл.
S_>И непонятно почему F# даже внутри списка параметров функции не может вперед заглянуть. Это временные недостатки компилятора, или так и задуманно?
Требование алгоритма вывода типов.
В Nemerle пошил другим путем. Алгоритм вывода типов существенно усложнили, но ввели ограничение — он может использоваться только внутри функций и членов типов и выводить конкретные (не не обобщенные) типы.
На мой взгляд вывод типов для публичных интерфейсов совершенно не нужен в условиях ООЯ. Даже, пожалуй, вреден.
Немерловый алгоритм вывода типов, в отличии от ФШарповского делает не один проход по АСТ, а столько сколько нужно для вывода типов. Плюс публичный интерфейс вообще не поддерживает вывод типов. Это позволяет сначала типизировать дерево типов, а потом отдельно типизироваться тела функций, методов, свойство и полей не обращая внимания на их последовательность.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, nikov, Вы писали:
N>Вот и получается такая ниша: проекты с большим количеством алгоритмически сложных вещей и немаленьким бюджетом, например, финансовая сфера. Как я вижу, ее уверенно занимает F#.
На самом деле если забыть о F#, который уж слишком необычен для мэйнстрима, остальные языки (Scala и Nemerle) будут удобнее C# в любой области где применим C#.
Так что нишу можно расширить до — любые задачи сложность которых выше тех что можно решить стадом индусов. А это не так уж и мало.
Те кто на них поставит получат или ускорение решения задач, или возможность решать более сложные задачи.
Не скажу за Скалу, а в Немерле есть убойное средство — разработка DSL-ей для описания (и автоматического решения) задач. Этот подход применим почти в любой области.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vmpire, Вы писали:
V>А много ли их, сложных вещей, в мейнстриме?
Не мало. Просто их принято решать стадом индусов (не по национальности, а по духу).
Все те же задачи можно решать, причем в сотри раз эффективнее, путем применения интеллекта. И тут Скала, Немерл и Фшарп становятся очень кстати.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vmpire, Вы писали:
V>Это в теоретической реальности. А в реальной — 80% ищущих работу на .NET и C# толком не знают. V>А макросы или прочие "мелочи" — так это вообще высший пилотаж. Там же надо, страшно подумать, документацию читать! V>С другой стороны — для мейнстрима нужна критическая масса заказчиков, которые согласятся вложить свои собственные деньги в проект на языке, поддерживаемом никому особо не известной французской университетской группой LAMP Group (Scala) или другими студентами, только из Польши (Nemerle), а не одним из лидеров отрасли (MS или Sun).
Ой. Не могу и согласиться, и не согласиться с этими словами. Они конечно правильные, но еще более они порочные.
Эти слова можно перефразировать так — толпы людей боятся что все вокруг так и будут бояться. В результате вместо того чтобы попробовать более интеллектуальные инструменты эти толпы пытаются решать задачи суммировав интеллект массы посредственных программистов (в народе именуемых индусами).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
IT>На производительность завязана вообще-то ресурсоёмкость алгоритмов, а не их алгоритмическая сложность. Сложность там как раз появляется в попытке решить одновременно в одном месте как саму основную задачу, так и алгоритм её оптимизации. Отсюда якобы сложность завязана на производительность. На самом деле всё совсем наоборот — в погоне за производительностью мы усложняем задачу.
+1
IT>Основным же инструментом для решения алгоритмически сложных задач в перечисленных языках является паттерн-матчинг, который позволяет десяток запутанных if-ов заменить одним простым и понятным паттерном. Плюс конечно же множество других плюшек и полезняшек, которые в итоге сильно повышают выразительность конкретного языка как инструмента разработки.
А вот тут позвольте поспорить!
ПМ — это конечно сильная штука позволяющая упростить решение многих задач связанных с разбором и распознаванием (анализом). Но макры — это не менее мощная вишь. Она позволяет добиться куда больших результатов. Просто ее сложнее оценить.
IT>Ко всему прочему в Немерле мы ещё имеем макросы.
Не ко всему прочему, а В ПЕРВУЮ ОЧЕРЕДЬ!
Просто сами макросы во многом получились из-за того что в языке есть вариантные типы и паттен-матчинг.
IT>Как известно, сложность разрабатываемого продукта не может превышать на порядок сложности инструмента, на котором этот продукт разрабатывается. Так вот макросы Немерле позволяют самостоятельно разрабатывать такие инструменты и получать уже два порядка, а не один.
Вот именно! Более того, само наличие немреле (сделанного такими малыми силами) является доказательством этого утверждения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mystic, Вы писали:
M>Ну я согласен, что шахматы простая задача: написал генератор ходов + полный перебор да забыл. Должен за конечное время выдать наилучший ход И во многих других случаях если максимально забивать на производительность, то можно найти тривиальные решения, плюс прекрасно работает декомпозиция. Представить сложный алгоритм, для которого производительность не была бы критичной... Мне даже ничего не приходит на ум
А ты представь себе простое, декларативное описание своего решения и не очень простой, но все же в пределах понимания обычным человеком, генератор кода который по этому описанию генерирует решение попутно производя тучу оптимизаций и генерируя низкоуровневое, оптимизированное решение в духе старого доброго плоского С.
Вот такое решение можно создать с помощью макросов. Примером такого решения является PegGrammar
— генератор парсеров на основе PEG-грамматики. По вполне простому описанию в виде PEG-грамматики (например, вот грамматика C# 4.0 написанная примерно за неделю человеком который до этого подобных задач не решал). PegGrammar генерирует весьма оптимизированное решение которое по скорости конкурирует с рукописным парсеров. Другие фичи Nemerle — такие как варианты (алгебраические типы данных) и сопоставление с образцом — позволяют сделать процесс оптимизаций прозрачным и простым.
Отделение описания задачи от ее эффективной реализации позволяет удерживать сложность проекта в рамках разумного и позволяет легко развивать проект.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А вот тут позвольте поспорить! VD>ПМ — это конечно сильная штука позволяющая упростить решение многих задач связанных с разбором и распознаванием (анализом). Но макры — это не менее мощная вишь. Она позволяет добиться куда больших результатов. Просто ее сложнее оценить.
Каждый ( и IT в том числе) смотрит с точки зрения своих задач. В рамках BLToolkit (особенно разбор extression tree), глядя на active patterns в F# IT по идее должен ногти до самых плеч себе сгрызть от зависти
Здравствуйте, VladD2, Вы писали:
VD>На мой взгляд вывод типов для публичных интерфейсов совершенно не нужен в условиях ООЯ. Даже, пожалуй, вреден.
Я тоже так считаю, но в F# (а возможно и в окамлах) есть такая интересная штука, как файлы сигнатур, которые явно декларируют типы публичного интерфейса и фиксируют типы для вывода типов. Получается как в плюсах: декларация модуля отделена от реализации, при этом типы указываются только в одном месте. Более того, экспортируемыми (публичными) функциями модуля становятся только функции, перечисленные в сигнатуре модуля — это позволяет не использовать модификаторы доступа для let-биндингов уровня модуля, а лишь сосредоточиться на декларации публичного интерфейса модуля в файле сигнатуры.
Здравствуйте, Mystic, Вы писали:
M>Очень просто, берешь простую задачу, пытаешься ее решить и буксуешь, не в состоянии найти решение. Или борясь с непонятными ошибками.
Можно более конкретный пример?
M>Да, на Nemerle можно писать в императивном ключе, но... смысл?
Смысл в том, что не надо решать всю задачу в незнакомом тебе ключе. Можно изучать новое находясь в практически знакомой среде.
Я вот сам бросил изучать ОКамл в 2003-ем году. А после изучения немерла (которое прошло на ура) я стал читать код на F# и ОКамл.
M>Просто использовать другой синтаксис?
В немерле и без ФП можно получить ряд приятных и полезных улучшений. Постепенно осваивая новые фичи ты сам не заметиешь как втянешься и освоишь весе возможности языка. Ну, а там для тебя откроется новый мир. На решение многих задач ты будешь смотреть совершенно по другому. Даже если потом вообще не придется писать на немерле, ты все равно получишь неоценимый опыт и будешь лучшим C#-, или Ява-программистом нежели был до этого.
M>Если брать книгу Душкина по Haskell, то там надо кучу интеллектуального труда только для того, чтобы разобраться в том, как вся работа со списками выражается через три общие функции.
А не надо брать того от чего крышу ломит.
M>Такой высокий полет сознания мне недоступен. Если брать макросы Nemerle, то после того, как я понял, что адский синтаксис на нем реализовать нельзя, то немного охладел к ним. По крайней мере, я не знаю, как их написать.
Ну, во-первых — обещаю, что в следующей версии немерла ты сможешь не только Адский синтаксис воспроизвести, но и любой другой адстки-крутой.
Во-вторых, уже сейчас есть PegGrammar
с помощью которого можно это сделать.
В-третьих (но не в последнюю очередь, а скорее в первую) суть макросов не в том, чтобы в точности воспроизводить другие языки программирования общего назначения, а в том, чтобы упрощать решение стоящих перед программистом задач. В том числе и методом заработки встроенных DSL-ей, при котором программист описывает простой, декларативный язык и пишет программу (макрос) которая преобразует код на этом языке в исполнимый код. Далее остается только описать на этом языке прикладную задачу и получить качественное и легко поддерживаемое решение.
M>Вторая проблема в том, что мне наиболее близка императивная форма. Когда я вижу что-то декларативное, которое вроде бы делает то, что мне надо, но я в этом не уверен на все 100%, я начинаю нервничать. И пока все не переведу в императивный вид, не успокоюсь. Соответственно лишняя работа, падение скорости разработки.
1. Со временем это проходит.
2. Никто не мешает делать именно так. Немерл не навязывать стиля программирования. Тот же DSL-подход позволяет реализовать полностью декларативное решение которое будет приводить к порождению императивного (и возможно очень эффективного) кода. При этом ты будешь полностью понимать что же происходит под капотом и чувствовать, что за декларативность не надо платить эффективностью.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mystic, Вы писали:
M>Разобраться мало, надо научиться этим пользоваться. Читаешь Душкина, вроде все понятно. Доходишь до упражнений, и сразу: "Э-э-э-э... Как??!! Дайте мне переменные и циклы!!!" Вторая проблема в том, чтобы набраться терпения и довести что-то до конца. Мучаешься, мучаешься, потом забиваешь и делаешь на чем-то более понятном. Или просто забиваешь
Дык циклы никто не отнимал! Это же не Хаскель?
А там поймешь, что, например, паттер-матчинг — это мега-круто, и что его даже в циклах можно использовать. И так потихонечку освоишь все фишки.
Только подход к изучению должен быть не такой. Не надо брать заумные книжки (да еще и по Хаскелю). Надо взять задачку средней сложности и попытаться ее решить. При этом имеет смысл показывать свой код более опытным (в языке) товарищам и просить показать как можно решать данную задачу более красиво. Через месяц все твои вопросы будут сняты. А через 2-3 ты будешь вполне сносно программировать на новом языке.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>Ну те же разработчики Xen пишут:
FR>
FR>Despite concerns raised at the start of the XAPI project, the MTT
FR>has had no difficulty in finding and hiring good OCaml programmers,
FR>and has been able to grow at a comparable rate to the other
FR>XenServer teams that used mainstream languages. From October
FR>2006 to April 2010, 12 engineers have been hired into OCamlprogramming
FR>positions (roughly a quarter of all XenServer engineers
FR>hired over the period).
Ага. А если еще вспомнить, что на Скалу можно довольно легко переучить любого хорошего Ява-программиста, а на Немерл любого хорошего шарписта, то вопрос и вовсе начинает выглядеть надумано.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Jack128, Вы писали:
J>Каждый ( и IT в том числе) смотрит с точки зрения своих задач. В рамках BLToolkit (особенно разбор extression tree), глядя на active patterns в F# IT по идее должен ногти до самых плеч себе сгрызть от зависти
Сгрыз. Не сомневайся Только глядя на ПМ Немерла. Тем более, что в Немерле вроде нет никаких технических проблем доработать компилятор, чтобы он позволял делать описания для внешних типов таким образом, чтобы они воспринимались компилятором как алгебраические типы. Тогда разбор стандартного ET вообще стал бы сплошным удовольствием, а не как сейчас — гемором.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, Пельмешко, Вы писали:
П>>Чем больше пишу на F#, тем сильнее уверен, что этот язык намнооого дальше от мейнстрима (ооочень далеко), чем Scala. По началу был просто ад, в основном из-за синтаксиса (сейчас он очень нравится). После продолжительного изучения писать на F# получается очень медленно, к сожалению.
FR>Почему-то от прямого предка F# OCaml'а такого впечатления нет. Наоборот он достаточно легко изучается, в пределах нескольких месяцев FR>и подмножество языка на котором уже можно вполне нормально работать очень простое.
Я больше скажу, F# сам по себе достаточно прост, к indentation-based syntax не сразу, но быстро привыкаешь и начинаешь переться, если первый изучаемый expression-based язык — то вообще кайф, а вот синтаксис определений классов надо курить долго и серьёзно, к поведению вывода типов и иногда невнятным ошибкам тайп-чекера по началу тяжело привыкнуть...
Лично у меня сложность скорее составляет применение на нём существующих .NET-библиотек так, чтобы потом не было очень грустно.
Иногда на F# очень тяжело получить какой-либо выигрыш по сравнению с кодом на C#, по сути нужна туча "функциональных обёрток" над ООП-шными API...
ИМХО F# без .NET представляет гораздо меньший интерес.
FR>И тут тоже http://www.slideshare.net/j2a/ss-4625844
Если мне не изменяет память, то Лев там упоминает от двух до шести месяцев.
Здравствуйте, Пельмешко, Вы писали:
П>Здравствуйте, VladD2, Вы писали:
VD>>На мой взгляд вывод типов для публичных интерфейсов совершенно не нужен в условиях ООЯ. Даже, пожалуй, вреден.
П>Я тоже так считаю, но в F# (а возможно и в окамлах) есть такая интересная штука, как файлы сигнатур, которые явно декларируют типы публичного интерфейса и фиксируют типы для вывода типов. Получается как в плюсах: декларация модуля отделена от реализации, при этом типы указываются только в одном месте. Более того, экспортируемыми (публичными) функциями модуля становятся только функции, перечисленные в сигнатуре модуля — это позволяет не использовать модификаторы доступа для let-биндингов уровня модуля, а лишь сосредоточиться на декларации публичного интерфейса модуля в файле сигнатуры.
Ага. Это и есть те самые подробности. Сенкс.
Вот только сам видишь как народу нравится такой подход. Любой кто написал мало-мальски серьезный проект скажет тебе, что отсутствие папок в проекте и необходимость упорядочивания файлов в проекте — это просто смешно и не приемлемо.
Ну, а предварительная декларация — это фактически отказ от глобального типа. По сути Немерл просто последователен. Он полностью отказывается от вывода типов публичных интерфейсов, зато предоставляет намного более гибкий и интуитивно понятный вывод типов на уровне тел функций и членов.
Что до отказа от модификаторов доступа, то в F# с этим вообще беда. Все поля по умолчанию становятся internal! И это в ООЯ?! Указать модификаторы доступа явно тоже проблематично.
В общем, у ОКамла торчат уж очень сильно. А ведь ОКамл — это в первую очередь Камл + опциональный ООП, в то время как F# — это полноценный гибридный язык. Да и как может быть по другому для языка спроектированного для дотнета — объектно-ориентированного рантайма?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Пельмешко, Вы писали:
П>Я больше скажу, F# сам по себе достаточно прост, к indentation-based syntax не сразу, но быстро привыкаешь и начинаешь переться, если первый изучаемый expression-based язык — то вообще кайф, а вот синтаксис определений классов надо курить долго и серьёзно, к поведению вывода типов и иногда невнятным ошибкам тайп-чекера по началу тяжело привыкнуть...
П>Лично у меня сложность скорее составляет применение на нём существующих .NET-библиотек так, чтобы потом не было очень грустно. П>Иногда на F# очень тяжело получить какой-либо выигрыш по сравнению с кодом на C#, по сути нужна туча "функциональных обёрток" над ООП-шными API... П>ИМХО F# без .NET представляет гораздо меньший интерес.
Ты меня конечно извини, но почему тогда просто не взять Nemerle? Все описанные тобой проблемы в нем решены или не существуют: синтаксис определения типов привычен C#-программисту и интуитивно понятен, тайп-чекер очень вменяемый, вывод типов можно вообще не курить, нет библиотеки применяются без единой обертки (легко и естественно), выигрыш по сравнению с шарпом виден почти сразу.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
IT>Сгрыз. Не сомневайся Только глядя на ПМ Немерла. Тем более, что в Немерле вроде нет никаких технических проблем доработать компилятор, чтобы он позволял делать описания для внешних типов таким образом, чтобы они воспринимались компилятором как алгебраические типы. Тогда разбор стандартного ET вообще стал бы сплошным удовольствием, а не как сейчас — гемором.
Я тебе уже сто раз говорил, что это возможно уже сейчас. ПМ по обычным классам работает на ура.
Единственно что — синтаксис немного более громоздкий нежели для ПМ по вариантам, так как для вариантов можно использовать паттерн конструктор, а для экземпляров классов нужно использовать паттерн "запись" которая несколько менее компакта.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Пельмешко, Вы писали:
П>Здравствуйте, VladD2, Вы писали:
VD>>На мой взгляд вывод типов для публичных интерфейсов совершенно не нужен в условиях ООЯ. Даже, пожалуй, вреден.
П>Я тоже так считаю, но в F# (а возможно и в окамлах) есть такая интересная штука, как файлы сигнатур, которые явно декларируют типы публичного интерфейса и фиксируют типы для вывода типов.
В F# это дела сильно урезали.
В OCaml (и SML) сигнатуры (не только файлы но и сигнатуры модулей) типы не обязательно фиксируют, чаще наоборот их используют для обобщенного программирования.
Здравствуйте, VladD2, Вы писали:
VD>Единственно что — синтаксис немного более громоздкий нежели для ПМ по вариантам, так как для вариантов можно использовать паттерн конструктор, а для экземпляров классов нужно использовать паттерн "запись" которая несколько менее компакта.
Именно это и не может вынести моё обострённое чувство совершенства. Нет гармонии в этом мире. Одни подпорки.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, VladD2, Вы писали:
VD>Ты меня конечно извини, но почему тогда просто не взять Nemerle? Все описанные тобой проблемы в нем решены или не существуют: синтаксис определения типов привычен C#-программисту и интуитивно понятен, тайп-чекер очень вменяемый, вывод типов можно вообще не курить, нет библиотеки применяются без единой обертки (легко и естественно), выигрыш по сравнению с шарпом виден почти сразу.
Это очень круто все, но мне бы на C# научиться программировать. Так, чтобы на покушать хватало
Остальное — чистый энтузиазм, сегодня интересно познакомиться с ML-семейством, завтра с чем-нибудь ещё Никто мне не позволит на работе F# юзать даже для тулз, Немерле — тем более, а с триалкой решарпера и C# я решу задачу за конечное время и мой код смогут поддерживать... суровая реальность
Здравствуйте, Пельмешко, Вы писали:
П>Я больше скажу, F# сам по себе достаточно прост, к indentation-based syntax не сразу, но быстро привыкаешь и начинаешь переться, если первый изучаемый expression-based язык — то вообще кайф, а вот синтаксис определений классов надо курить долго и серьёзно, к поведению вывода типов и иногда невнятным ошибкам тайп-чекера по началу тяжело привыкнуть...
П>Лично у меня сложность скорее составляет применение на нём существующих .NET-библиотек так, чтобы потом не было очень грустно. П>Иногда на F# очень тяжело получить какой-либо выигрыш по сравнению с кодом на C#, по сути нужна туча "функциональных обёрток" над ООП-шными API... П>ИМХО F# без .NET представляет гораздо меньший интерес.
Понятно, похоже скрещивание OCaml c NET прошло не так гладко.
В OCaml родное ОО таких проблем не представляет, наоборот очень гладко вписана в язык, например та же структурная типизация
одинакова что в записях что в объектах. Ну и в результате получившееся ОО похоже никак ни стыковалось с нетовской, и
разработчикам F# пришлось разрабатывать свой вариант.
FR>>И тут тоже http://www.slideshare.net/j2a/ss-4625844
П>Если мне не изменяет память, то Лев там упоминает от двух до шести месяцев.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Mystic, Вы писали:
VD>А ты представь себе простое, декларативное описание своего решения и не очень простой, но все же в пределах понимания обычным человеком, генератор кода который по этому описанию генерирует решение попутно производя тучу оптимизаций и генерируя низкоуровневое, оптимизированное решение в духе старого доброго плоского С.
Вот, представил. Есть битовая маска 19х19. В ней могут встречаться с учетом поворотов и отраений разнообразные фигуры, список которых известен заранее. Необходимо максимально быстро по этой битовой маске сгенерировать другую битовую маску, в которой будут установлены некоторое подмножество битов.
Вот для этой цели я создаю декларативный язык программирования, который принимает на вход примерно такие данные:
— генератор парсеров на основе PEG-грамматики. По вполне простому описанию в виде PEG-грамматики (например, вот грамматика C# 4.0 написанная примерно за неделю человеком который до этого подобных задач не решал). PegGrammar генерирует весьма оптимизированное решение которое по скорости конкурирует с рукописным парсеров. Другие фичи Nemerle — такие как варианты (алгебраические типы данных) и сопоставление с образцом — позволяют сделать процесс оптимизаций прозрачным и простым.
Это я понимаю, только C# меня не впечатляет. А вот адский синтаксис я уже воссоздать не сумел. Например, такое
Block_Name:
declare
X: Integer;
begin
X := Random(10);
exit Block_Name when X = 0;
Some_Method();
exeption
-- обработчики исключений
end Block_Name;
VD>Отделение описания задачи от ее эффективной реализации позволяет удерживать сложность проекта в рамках разумного и позволяет легко развивать проект.
Я с этим и не спорю, но сейчас намного проще мне для генерации кода написать отдельную тулзу. И результат получается намного более гибкий, потому что я никак не скован какими-либо ограничениями.
Здравствуйте, Пельмешко, Вы писали:
П>Остальное — чистый энтузиазм, сегодня интересно познакомиться с ML-семейством, завтра с чем-нибудь ещё Никто мне не позволит на работе F# юзать даже для тулз, Немерле — тем более, а с триалкой решарпера и C# я решу задачу за конечное время и мой код смогут поддерживать... суровая реальность
Я тебе гарантирую, что освоив F#/Nemerle ты сможешь решать те же задачи на C# в двое быстрее. Правда будешь при этом кусать ногти
Здравствуйте, VladD2, Вы писали:
VD>Дык циклы никто не отнимал! Это же не Хаскель?
Тогда вторым шагом будет: где моя память и где указатели? Большая часть моего кода такая, так что я конченый человек
template <Color attacker, Color defender>
void TsumeSolver<attacker, defender>::KillNode(Node* node)
{
// Вначале надо разобраться с детьмиif (node->answers) // если они есть
{
if (node->nextEqual != node)
{
// Есть клон, который готов взять заботу о детях
// Вначале надо рассказать, кто их папа
Node* child = node->answers;
do {
child->parent = node->nextEqual;
child = child->next;
} while (child != node->answers);
// А потом папе рассказать о его детях
node->nextEqual->answers = node->answers;
node->answers = 0;
}
else {
// Беспризорники нам не нужны, из соображений гуманности детей надо убить :)while(node->answers)
KillNode(node->answers);
}
}
RemoveFromFamily(node);
RemoveFromInterest(node);
// Финальный аккорд!
hashtable.Free(node);
}
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Пельмешко, Вы писали:
П>>Остальное — чистый энтузиазм, сегодня интересно познакомиться с ML-семейством, завтра с чем-нибудь ещё Никто мне не позволит на работе F# юзать даже для тулз, Немерле — тем более, а с триалкой решарпера и C# я решу задачу за конечное время и мой код смогут поддерживать... суровая реальность
VD>Я тебе гарантирую, что освоив F#/Nemerle ты сможешь решать те же задачи на C# в двое быстрее. Правда будешь при этом кусать ногти
от того, что мог бы решать их и в 10 раз быстрее если бы тебе позволили использовать F#/Nemerle.
Я вот только не пойму с чего ты решил, что я недостаточно освоил F# чтобы различать когда в C#-коде встречаются те, или иные задачи, которые прекрасно "ложатся" на функциональные языки
Здравствуйте, FR, Вы писали:
V>>С другой стороны — для мейнстрима нужна критическая масса заказчиков, которые согласятся вложить свои собственные деньги в проект на языке, поддерживаемом никому особо не известной французской университетской группой LAMP Group (Scala) или другими студентами, только из Польши (Nemerle), а не одним из лидеров отрасли (MS или Sun).
FR>MS c F# тоже в этом списке. FR>Также и опять MS + университет Глазго — Haskell. FR>Ну или вполне известный университет INRIA — OCaml
А для тех, кто с MS действует пункт первый
И потом, повторюсь, очень мало в мейнстриме задач где эти языки реально упрощают жизнь. В нишевых задачах — да, но не в мейнстриме.
Как мне кажется, мы наблюдаем (и будем продолжать наблюдать) не переход этих языков в мейнстрим, а переход наиболее применимых в вещей оттуда в мейнстримовые языки.
M>>Да, на Nemerle можно писать в императивном ключе, но... смысл? VD>Смысл в том, что не надо решать всю задачу в незнакомом тебе ключе. Можно изучать новое находясь в практически знакомой среде.
C# и .NET для меня не знакомая среда. Знакомая среда это байты, биты, указатели
M>>Просто использовать другой синтаксис?
VD>В-третьих (но не в последнюю очередь, а скорее в первую) суть макросов не в том, чтобы в точности воспроизводить другие языки программирования общего назначения, а в том, чтобы упрощать решение стоящих перед программистом задач. В том числе и методом заработки встроенных DSL-ей, при котором программист описывает простой, декларативный язык и пишет программу (макрос) которая преобразует код на этом языке в исполнимый код. Далее остается только описать на этом языке прикладную задачу и получить качественное и легко поддерживаемое решение.
Это я понимаю, но это было просто упражнение, чтобы пощупать руками, что за зверь.
Здравствуйте, VladD2, Вы писали:
VD>Единственно что — синтаксис немного более громоздкий нежели для ПМ по вариантам, так как для вариантов можно использовать паттерн конструктор, а для экземпляров классов нужно использовать паттерн "запись" которая несколько менее компакта.
Всетки активные паттерны это очень мощьная штука.
И ее обязательно нужно будет сделать.
Правда несколько в ином виде чем в F#.
И тогда ET можно будет матчить прямо как варианты.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Mystic, Вы писали:
M>Я с этим и не спорю, но сейчас намного проще мне для генерации кода написать отдельную тулзу. И результат получается намного более гибкий, потому что я никак не скован какими-либо ограничениями.
Отдельная тулза — это намного больше труда и таки не мало ограничений. В макре ты можешь воспользоваться проверкой типов и самими типами. Это зачастую дает иной уровень диагностики и возможностей.
Плюс интерактивность. Тебе не надо налаживать процесс кодогенерации или запускать его. Ты просто меняешь данные и уже в IDE видишь результат. Опять же приведу в пример PegGremmar. Ошибка сделанная в грамматике почти сразу же становится видна в IDE:
Или возможность навигации по правилам DSL-я:
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Mystic, Вы писали:
M>>Я с этим и не спорю, но сейчас намного проще мне для генерации кода написать отдельную тулзу. И результат получается намного более гибкий, потому что я никак не скован какими-либо ограничениями. VD>Отдельная тулза — это намного больше труда и таки не мало ограничений. В макре ты можешь воспользоваться проверкой типов и самими типами. Это зачастую дает иной уровень диагностики и возможностей.
А если предметный язык не описывается контекстно свободной грамматикой? Как, например, в моем случае
Здравствуйте, vmpire, Вы писали:
V>И потом, повторюсь, очень мало в мейнстриме задач где эти языки реально упрощают жизнь. В нишевых задачах — да, но не в мейнстриме.
Одна из таких задач в итоге вылилась во встроенный DSL одного из мэйнстрим языков. Не всё там на 100% так как хотелось бы, при наличии того же МП можно было это дело допилить под себя, но спасибо MS и за то, что они уже сделали.
V>Как мне кажется, мы наблюдаем (и будем продолжать наблюдать) не переход этих языков в мейнстрим, а переход наиболее применимых в вещей оттуда в мейнстримовые языки.
Когда уже наконец в мейнстрим перейдёт ПМ?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, VladD2, Вы писали:
V>>А много ли их, сложных вещей, в мейнстриме?
VD>Не мало. Просто их принято решать стадом индусов (не по национальности, а по духу). VD>Все те же задачи можно решать, причем в сотри раз эффективнее, путем применения интеллекта. И тут Скала, Немерл и Фшарп становятся очень кстати.
Моё "много ли" и Ваше "не мало" одинаково бездоказательны ибо опыт у каждого свой. Следовательно, бездоказательны и выводы из этих утверждений.
Насчёт стада индусов — не согласен. Если нужно, скажем,написать компилятор с языка сложностью как C++, то без определённого уровня подготовки количество индусов роли не играет: всё равно не напишут.
Что есть в этих языках такого, чтобы сократить затраты на разработку софта на порядок, не повышая во столько же раз стоимость сопровождения?
Макросы, которые продвигаются как основная фича Nemerle, на мой взгляд, вещь, конечно, приятная, но не убойная.
Для чего часто нужна автоматическая генерация кода? Дополнительный статический контроль типов, сокращение количества кода при реализации некоторых вещей... на этом лично моя фантазия останавливается (да да. тут можно вспомнить блаба). Разве что вот парсинг всякого рода текста с заданной грамматикой пишется легко. Но для этого в мейнстримовых языках уже есть библиотеки.
Здравствуйте, vmpire, Вы писали:
V>Для чего часто нужна автоматическая генерация кода?
Например, для создания повторно используемых библиотек паттернов. В WPF введено такое понятие как dependency property. Штука полезная и вроде архитектурно правильная, но крайне неудобная в использовании. С помощью МП эти неудобства нивелируются полностью и сводятся в ноль. Если бы в C# был МП, то один из первых небольших велосипедов, которые я бы смастерил было бы nameof и infoof, ибо уже задолбало. Если бы в C# был МП и он позволял разширять стандартный синтаксис, то среди моих расширений незамедлительно появились бы такие дополнения к linq как top, skip, distinct, to list и to array.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, VladD2, Вы писали:
V>>Это в теоретической реальности. А в реальной — 80% ищущих работу на .NET и C# толком не знают. V>>А макросы или прочие "мелочи" — так это вообще высший пилотаж. Там же надо, страшно подумать, документацию читать! V>>С другой стороны — для мейнстрима нужна критическая масса заказчиков, которые согласятся вложить свои собственные деньги в проект на языке, поддерживаемом никому особо не известной французской университетской группой LAMP Group (Scala) или другими студентами, только из Польши (Nemerle), а не одним из лидеров отрасли (MS или Sun).
VD>Ой. Не могу и согласиться, и не согласиться с этими словами. Они конечно правильные, но еще более они порочные.
Мир порочен, увы...
VD>Эти слова можно перефразировать так — толпы людей боятся что все вокруг так и будут бояться. VD>В результате вместо того чтобы попробовать более интеллектуальные инструменты эти толпы пытаются решать задачи суммировав интеллект массы посредственных программистов (в народе именуемых индусами).
Да, примерно так. Но не совсем. Скорее, толпы людей боятся что эти студенты разбегутся и некому будет всё это поддерживать (вот, например, перестанет им нравится функциональное программирование и увлекутся они логическим. Или в армию заберут. Всех.). Вероятность, что разбежится MS всё-таки меньше. Как никак для VS есть официальные сроки поддержки, чего у студентов нет и в помине.
Тем более, что не видно, чего можно достигнуть, если перестать бояться. На Аляску рвались за золотом, а зачем рваться в новые языки рискуя своими деньгами? (Если захотите ответить на этот конкретный вопрос, то лучше тут: http://www.rsdn.ru/forum/philosophy/4003165.1.aspx
Кстати, про индусов, это, вообще, очень по русски: нанять для разгрузки вагона 10 таджиков за 500 рублей вместо погрузчика с оператором за 4000.
Все в разной степени этим больны, не только программисты.
Как я уже предполагал чуть раньше, эти языки мир не завоюют. Но то, что в них есть реально полезного, будет постепенно мигрировать в другие языки.
Вот, например, сделает MS в C# макросы в стиле Nemerle и кому тогда Nemerle будет нужен? А что бы им и не сделать, Text Templates уже вот есть...
VD>Ну, во-первых — обещаю, что в следующей версии немерла ты сможешь не только Адский синтаксис воспроизвести, но и любой другой адстки-крутой.
Адский синтаксис хорошо бы для лямб в функциональные языки внедрить
Например как в Mathematica, там так можно для лямбды с двумя параметрами #1 + #2 &
Вместо C#
c.Select((e,i)=> i + e.Fld1 + e.Fld2.Sum( e2 => e2.fld3))
Или вместо F# (лень такое писать)
c|>List.mapi (fun i e-> i + e.Fld1 + ( e.Fld2 |> List.SumBy (fun e2-> e2.fld3))
Было бы
c.Select(#2 + #1.fld1 + #1.fld2.Sum(##.fld3))
Когда один параметр в лямбде решетку можно без номера: c.Sum(#.fld1)
Для вложенных можно две решетки.
Можно конечно в среде VS, пользовать текстовый макрос на VisualBasic который превращает выражение с решетками в какое надо, при нажатии на шорткат. Раз языки себе такой синтаксис позволить не могут.
Здравствуйте, Пельмешко, Вы писали:
П>Я вот только не пойму с чего ты решил, что я недостаточно освоил F# чтобы различать когда в C#-коде встречаются те, или иные задачи, которые прекрасно "ложатся" на функциональные языки
Из твоих слов. Извини, если это не так.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>В F# это дела сильно урезали. FR>В OCaml (и SML) сигнатуры (не только файлы но и сигнатуры модулей) типы не обязательно фиксируют, чаще наоборот их используют для обобщенного программирования.
Но тогда не остается никакой возможности уйти от обязательного расположения файлов в определенном порядке. Да?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
V>Да, примерно так. Но не совсем. Скорее, толпы людей боятся что эти студенты разбегутся и некому будет всё это поддерживать (вот, например, перестанет им нравится функциональное программирование и увлекутся они логическим. Или в армию заберут. Всех.). Вероятность, что разбежится MS всё-таки меньше. Как никак для VS есть официальные сроки поддержки, чего у студентов нет и в помине.
Ключевое слово здесь — боится. Страхи эти совершенно надуманные. В том же С++ почему-то специалистов хватает, не смотря на некоторую сложность в вопросе шаблонов и т.п.
V>Тем более, что не видно, чего можно достигнуть, если перестать бояться. На Аляску рвались за золотом, а зачем рваться в новые языки рискуя своими деньгами? (Если захотите ответить на этот конкретный вопрос, то лучше тут: http://www.rsdn.ru/forum/philosophy/4003165.1.aspx
Да там (еще перед этим сообщением) как раз ответ и дается. Вот только на все слова навешивается язык "бездоказательно" и они успешно игнорируются.
V>Кстати, про индусов, это, вообще, очень по русски: нанять для разгрузки вагона 10 таджиков за 500 рублей вместо погрузчика с оператором за 4000.
С одной лишь оговоркой. Аналогия не верна. Разгрузка вагонов никак не соотносится с созданием сложного ПО. Да что уж "сложного"? Она и с разработкой простого не соотносится. Тут скорее верна другая аналогия, с рождением ребенка. 9 баб не родят ребенка за один месяц.
V>Все в разной степени этим больны, не только программисты.
Ни скажи! В разработке ПО — эта дурь встречается чаще.
V>Как я уже предполагал чуть раньше, эти языки мир не завоюют.
Вот это как раз бездоказательно!
V>Но то, что в них есть реально полезного, будет постепенно мигрировать в другие языки.
А это тоже можно рассматривать как завоевание мира теми языками.
Но, к сожалению, прогресса в этой области в ближайшие 10 лет, похоже, не предвидится. И я не уверен, что мы будем в здравой памяти когда это случится.
V>Вот, например, сделает MS в C# макросы в стиле Nemerle и кому тогда Nemerle будет нужен? А что бы им и не сделать, Text Templates уже вот есть...
Если бы была хотя бы малейшая надежда, что в Немерле сделают макросы и ПМ (а одно без другого нежизнеспособно), то я бы ни в жизнь не стал заниматься немерлом. Но, увы, надежды таяли на глазах и на сегодня растаяли вовсе. Пока у руля Шарпа будет Хейльсберг, нам вряд ли увидеть в Шарпе эти фичи.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vmpire, Вы писали:
V>Моё "много ли" и Ваше "не мало" одинаково бездоказательны ибо опыт у каждого свой. Следовательно, бездоказательны и выводы из этих утверждений.
Тут доказательства бесполезны. Это надо просто попробовать. После втягивания доказательства будут не нужны, а сам вопрос будет казаться смешным.
V>Насчёт стада индусов — не согласен. Если нужно, скажем,написать компилятор с языка сложностью как C++, то без определённого уровня подготовки количество индусов роли не играет: всё равно не напишут.
Вот если говорить о компиляторе, то кроме уровня, в этом деле, очень важны инструменты! И перечисленные Scala / F# / Nemerle (плюс другие клоны ML) являются идеальными инструментами для разработки компиляторов. Причем Nemerle тут вообще вне конкуренции. Короче, погляди по внимательнее PegGrammar
Конечно же наличие такого инструмента не отменяет необходимости знаний и умений, но оно упрощает задачу просто радикально. Если без них написать С++-компилятор смогут только отдельные (можно сказать гениальные) личности, то с ним это сможет сделать любой смертрый и в совершенно реальные сроки (от месяца, до полугода, если не касаться вопросов оптимизации и кодогенерации взяв некий бэкэнд компилятора).
V>Что есть в этих языках такого, чтобы сократить затраты на разработку софта на порядок, не повышая во столько же раз стоимость сопровождения?
В них есть паттер-матчинг и алгебраические типы. Плюс великолепная поддержка ФП отлично интегрированная с ООП. Плюс в Немерле есть мека-фича — макросы!
V>Макросы, которые продвигаются как основная фича Nemerle, на мой взгляд, вещь, конечно, приятная, но не убойная.
Это исключительно потому, что вы не умеет их готовить. Еще раз предлагаю поглядеть на Nemerle on rails, PegGrammar
или хотя бы на XML-литералы.
V>Для чего часто нужна автоматическая генерация кода? Дополнительный статический контроль типов, сокращение количества кода при реализации некоторых вещей... на этом лично моя фантазия останавливается (да да. тут можно вспомнить блаба).
Заметь, не я это сказал.
Лично мне тяжело представить для чего нельзя использовать макросы.
Так что я лучше скажу о приципе их использования. Чтобы увидеть где можно использовать макросы в своих программах, нужно просто попробовать представить как бы твоя программа выглядела, если бы ты не имел ограничений, т.е. представить некое идеальное решение задачи. Далее остается только придумать DSL для этого идеального описания и воплотить его в виде макросов (тут конечно нужен опыт работы с макрами).
V>Разве что вот парсинг всякого рода текста с заданной грамматикой пишется легко. Но для этого в мейнстримовых языках уже есть библиотеки.
Да любая сложная задача может быть решена очень красиво с помощью введения DSL-я. Надо только научиться рассматривать решение задач в этом контексте.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
IT>Например, для создания повторно используемых библиотек паттернов. В WPF введено такое понятие как dependency property. Штука полезная и вроде архитектурно правильная, но крайне неудобная в использовании. С помощью МП эти неудобства нивелируются полностью и сводятся в ноль.
Собственно, вот эта поддержка.
IT>Если бы в C# был МП, то один из первых небольших велосипедов, которые я бы смастерил было бы nameof и infoof, ибо уже задолбало.
А при наличии макросов (и осознании их крутости) ты бы еще понял, что эти инструкции ненужны. Точнее они конечно нужны, но в основном внутри макросов, где они выглядят не как конструкции языка, а как элементы типизированного AST. Кстати, вот и они. Я их использовал при реализации макросов поддержки LINQ.
IT>Если бы в C# был МП и он позволял разширять стандартный синтаксис, то среди моих расширений незамедлительно появились бы такие дополнения к linq как top, skip, distinct, to list и to array.
А скорее всего ты бы просто вместо LINQ создал бы свой DSL-SQL который позволил бы тебе без приседаний описывать запросы к СУБД.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
V>>Для чего часто нужна автоматическая генерация кода?
IT>Например, для создания повторно используемых библиотек паттернов. В WPF введено такое понятие как dependency property. Штука полезная и вроде архитектурно правильная, но крайне неудобная в использовании. С помощью МП эти неудобства нивелируются полностью и сводятся в ноль. Если бы в C# был МП, то один из первых небольших велосипедов, которые я бы смастерил было бы nameof и infoof, ибо уже задолбало.
Это можно (чуть менее красиво, конечно), написать на существующих text templates. Достаточно ли небольшого сокращения в записи кода для обоснования перехода на новый язык?
IT>Если бы в C# был МП и он позволял разширять стандартный синтаксис, то среди моих расширений незамедлительно появились бы такие дополнения к linq как top, skip, distinct, to list и to array.
Я что-то торможу: а разве в LINQ там этого нет?
Здравствуйте, Mystic, Вы писали:
M>А если предметный язык не описывается контекстно свободной грамматикой? Как, например, в моем случае
Да без разницы! Ни языку (немерлу), ни его IDE нет никакого дела до того, что за DSL ты разработал и используешь. Лишь бы DSL был удобным для тебя и качественно реализованным.
Пойми, никто специально не затачивал ни макросы, ни сам язык для поддержки именно грамматик или парсинга. Просто нам самим нужен был именно этот DSL, вот мы себе его и сделали.
Точно так же я сделал для себя DSL XML-литералов, кто-то другой DSL Computation Expressions (аналог фичи из F# которая в этот язык прибита гвоздями), ну, а кто-то сделал себе аналог Ruby on rails — Nemerle on Rails (и это не на скрипте, а на статически-типизированно языке производительность которого близка к С-коду).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, WolfHound, Вы писали:
WH>Всетки активные паттерны это очень мощьная штука.
Это очень медленная штука. Как я понимаю, они там создают копии объектов.
WH>И ее обязательно нужно будет сделать. WH>Правда несколько в ином виде чем в F#.
У меня на этот вопрос есть свое мнение. Можно просто описывать так называемый виртуальный (не существующий в реалии) конструктор который будет сообщать компилятору какие поля или свойства использовать для эмуляции конструктора. Тогда можно будет любой объект любого класса "можно будет матчить прямо как варианты".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
V>>Тем более, что не видно, чего можно достигнуть, если перестать бояться. На Аляску рвались за золотом, а зачем рваться в новые языки рискуя своими деньгами? (Если захотите ответить на этот конкретный вопрос, то лучше тут: http://www.rsdn.ru/forum/philosophy/4003165.1.aspx
). VD>Да там (еще перед этим сообщением) как раз ответ и дается. Вот только на все слова навешивается язык "бездоказательно" и они успешно игнорируются.
Ну естественно. Вы говорите, таких задач "много", я говорю "мало". Пруфлинков ни у кого нет, поэтому я и предлагаю эти аргументы выкинуть.
V>>Кстати, про индусов, это, вообще, очень по русски: нанять для разгрузки вагона 10 таджиков за 500 рублей вместо погрузчика с оператором за 4000. VD>С одной лишь оговоркой. Аналогия не верна. Разгрузка вагонов никак не соотносится с созданием сложного ПО. Да что уж "сложного"? Она и с разработкой простого не соотносится. Тут скорее верна другая аналогия, с рождением ребенка. 9 баб не родят ребенка за один месяц.
Ну... можно вместо макросов посадить 100 индусов вставлять вовсюда одинаковый код. И ещё 100 индусов проверять.
Впрочем, я не настаиваю на верности аналогии.
V>>Как я уже предполагал чуть раньше, эти языки мир не завоюют. VD>Вот это как раз бездоказательно!
Абсолютно бездоказательно. Это личное предположение, а не утверждение.
VD>Но, к сожалению, прогресса в этой области в ближайшие 10 лет, похоже, не предвидится. И я не уверен, что мы будем в здравой памяти когда это случится.
Ну, лямбды-то проросли вместе с функциями высшего порядка. Глядишь, ещё чего переймут.
V>>Вот, например, сделает MS в C# макросы в стиле Nemerle и кому тогда Nemerle будет нужен? А что бы им и не сделать, Text Templates уже вот есть... VD>Если бы была хотя бы малейшая надежда, что в Немерле сделают макросы и ПМ (а одно без другого нежизнеспособно), то я бы ни в жизнь не стал заниматься немерлом. Но, увы, надежды таяли на глазах и на сегодня растаяли вовсе. Пока у руля Шарпа будет Хейльсберг, нам вряд ли увидеть в Шарпе эти фичи.
Хейльсберг не вечен. C# тоже. Вечен только C
Тут всё упирается в деньги. Есть платежеспособный спрос — напишут.
Здравствуйте, vmpire, Вы писали:
V>Ну естественно. Вы говорите, таких задач "много", я говорю "мало". Пруфлинков ни у кого нет, поэтому я и предлагаю эти аргументы выкинуть.
Моими пруфлинками тут вся тема забита.
V>Ну, лямбды-то проросли вместе с функциями высшего порядка. Глядишь, ещё чего переймут.
Лямбды протащили под видом фич необходимых для реализации LINQ-а. А вот против алгебраических типов и МП у Хейльсберга "зуб" имеется.
V>Хейльсберг не вечен. C# тоже. Вечен только C
Это да. Но тут есть еще одна загвоздка. Мы тоже не вечны. И не факт, что мы переживем Хейльсберга.
V>Тут всё упирается в деньги. Есть платежеспособный спрос — напишут.
Все с точностью до наоборот. Сегодня деньги формируют спрос. Если МС захочет и даст денег на тот же Nemerle, то через пару лет о C# будут вспоминать как о тупиковой ветви эволюции С.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Silver_s, Вы писали:
S_> Адский синтаксис хорошо бы для лямб в функциональные языки внедрить S_>Например как в Mathematica, там так можно для лямбды с двумя параметрами #1 + #2 & S_>Вместо C# S_>c.Select((e,i)=> i + e.Fld1 + e.Fld2.Sum( e2 => e2.fld3)) S_>Или вместо F# (лень такое писать) S_>c|>List.mapi (fun i e-> i + e.Fld1 + ( e.Fld2 |> List.SumBy (fun e2-> e2.fld3)) S_>Было бы S_>c.Select(#2 + #1.fld1 + #1.fld2.Sum(##.fld3))
Откровенно говоря C#-вариант мне кажется более понятным и читаемым. Слишком уж невнятно вложенные выражения выглядят.
К тому же это все разговоры по поводу сахара и вкуса. Дополнительной мощности они языку не придают.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vmpire, Вы писали:
V>Для чего часто нужна автоматическая генерация кода? Дополнительный статический контроль типов, сокращение количества кода при реализации некоторых вещей... на этом лично моя фантазия останавливается (да да. тут можно вспомнить блаба). Разве что вот парсинг всякого рода текста с заданной грамматикой пишется легко. Но для этого в мейнстримовых языках уже есть библиотеки.
Например замутить программирование GPU, без всяких CUDA и прочих. Чтобы не лазить во всякие внешние тулзы, а все не отходя от кассы и с intellisence. Но эадача эта не детская лучше бы они(производители карточек) сами написали.
И наверно что-то полезное написали бы уже, если бы в мейнстриме вертелся широко распространенный,приличный язык с метапрограммированием.
Поскольку их нет, а если и есть, то о них мало кто знает. То только Cuda.Net смогли сделать.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, kkolyan, Вы писали:
K>>такое ощущение , что нахожусь в палате для альтернативно одаренных
VD>И давно Вас туда определили?
со вчерашнего вечера
Здравствуйте, Silver_s, Вы писали:
S_>Например замутить программирование GPU, без всяких CUDA и прочих. Чтобы не лазить во всякие внешние тулзы, а все не отходя от кассы и с intellisence. Но эадача эта не детская лучше бы они(производители карточек) сами написали.
Будете смеяться, но и это у нас есть. Причем в двух экзеплярах:
* <b>NUDA</b>
* NemerleCL
S_> И наверно что-то полезное написали бы уже, если бы в мейнстриме вертелся широко распространенный,приличный язык с метапрограммированием. S_>Поскольку их нет, а если и есть, то о них мало кто знает. То только Cuda.Net смогли сделать.
Так что дело за малым. Осталось чтобы немерл стал мэйнстримом.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vmpire, Вы писали:
IT>>Например, для создания повторно используемых библиотек паттернов. В WPF введено такое понятие как dependency property. Штука полезная и вроде архитектурно правильная, но крайне неудобная в использовании. С помощью МП эти неудобства нивелируются полностью и сводятся в ноль. Если бы в C# был МП, то один из первых небольших велосипедов, которые я бы смастерил было бы nameof и infoof, ибо уже задолбало. V>Это можно (чуть менее красиво, конечно), написать на существующих text templates. Достаточно ли небольшого сокращения в записи кода для обоснования перехода на новый язык?
Я это и без темплейтов использую. Смастерил вот такого уродца:
public class Expressor<T>
{
public static FieldInfo FieldExpressor(Expression<Func<T,object>> func)
{
return (FieldInfo)((MemberExpression)((UnaryExpression)func.Body).Operand).Member;
}
public static MethodInfo PropertyExpressor(Expression<Func<T,object>> func)
{
return ((PropertyInfo)((MemberExpression)func.Body).Member).GetGetMethod();
}
public static MethodInfo MethodExpressor(Expression<Func<T,object>> func)
{
var ex = func.Body;
if (ex is UnaryExpression)
ex = ((UnaryExpression)ex).Operand;
return ((MethodCallExpression)ex).Method;
}
}
и использую:
public class DataReader : Expressor<IDataReader>
{
public static MethodInfo GetValue = MethodExpressor(rd => rd.GetValue(0));
public static MethodInfo IsDBNull = MethodExpressor(rd => rd.IsDBNull(0));
}
Но, во первых, это кастыль, во-вторых, это медленно. Но всё же лучше, чем GetType().GetMethod("StringIdentifier", куча непонятных параметров);
IT>>Если бы в C# был МП и он позволял разширять стандартный синтаксис, то среди моих расширений незамедлительно появились бы такие дополнения к linq как top, skip, distinct, to list и to array. V>Я что-то торможу: а разве в LINQ там этого нет?
В синтаксическом расширении нет. В результате приходится писать:
var q =
from x in y
...
select z;
var list = q.ToList();
А хотелось бы
var list =
from x in y
...
select z
to list;
Вроде мелочь. Но вот с таких мелочей грязь в коде и начинается.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, VladD2, Вы писали:
VD>Вот если говорить о компиляторе, то кроме уровня, в этом деле, очень важны инструменты! И перечисленные Scala / F# / Nemerle (плюс другие клоны ML) являются идеальными инструментами для разработки компиляторов. Причем Nemerle тут вообще вне конкуренции. Короче, погляди по внимательнее PegGrammar
и все вопросы отпадут сами собой.
Я, вроде как, не только с этим не спорил, а как раз наоборот, приводил парсинг языков как сильную сторону Nemerle.
V>>Что есть в этих языках такого, чтобы сократить затраты на разработку софта на порядок, не повышая во столько же раз стоимость сопровождения? VD>В них есть паттер-матчинг и алгебраические типы. Плюс великолепная поддержка ФП отлично интегрированная с ООП. Плюс в Немерле есть мека-фича — макросы!
ну, если я скажу,что в мейнстриме (бухгалтерия, финансы) это не нужно, то это будет опять-таки бездоказательно. Скажу только, что я лично в этом потребности не испытывал. А вот в DSL — испытывал.
V>>Макросы, которые продвигаются как основная фича Nemerle, на мой взгляд, вещь, конечно, приятная, но не убойная. VD>Это исключительно потому, что вы не умеет их готовить. Еще раз предлагаю поглядеть на Nemerle on rails, PegGrammar
или хотя бы на XML-литералы.
Я это видел. Могу на это сказать, что согласен с тем, что построение DSL в Nemerle тоже удобно. И это как раз та фича, которая имеет наибольший, наверное, шанс войти в mainstream. Но — в виде расширения C# или Java.
V>>Для чего часто нужна автоматическая генерация кода? Дополнительный статический контроль типов, сокращение количества кода при реализации некоторых вещей... на этом лично моя фантазия останавливается (да да. тут можно вспомнить блаба). VD>Заметь, не я это сказал.
Ну, так я же знаю, с какой стороны какоо языка я нахожусь. Также обращаю внимание, что я не критикую Nemerle и вообще что-либо, а только отвечаю на вопрос, почему они не идут в мейнстрим.
VD>Лично мне тяжело представить для чего нельзя использовать макросы. VD>Так что я лучше скажу о приципе их использования. Чтобы увидеть где можно использовать макросы в своих программах, нужно просто попробовать представить как бы твоя программа выглядела, если бы ты не имел ограничений, т.е. представить некое идеальное решение задачи. Далее остается только придумать DSL для этого идеального описания и воплотить его в виде макросов (тут конечно нужен опыт работы с макрами).
Это из серии "лучше день потерять..." Чаще быстрее написать набор функций для тех же целей. С синтаксисом, конечно, не размахнёшься, но потом саппорту не надо рассказывать, что это за язык такой.
V>>Разве что вот парсинг всякого рода текста с заданной грамматикой пишется легко. Но для этого в мейнстримовых языках уже есть библиотеки. VD>Да любая сложная задача может быть решена очень красиво с помощью введения DSL-я. Надо только научиться рассматривать решение задач в этом контексте.
В эту фразу вместо DSL можно подставить вообще всё, что угодно
Здравствуйте, VladD2, Вы писали:
V>>Ну естественно. Вы говорите, таких задач "много", я говорю "мало". Пруфлинков ни у кого нет, поэтому я и предлагаю эти аргументы выкинуть. VD>Моими пруфлинками тут вся тема забита.
Ссылкт на свои проекты и проекты пары энтузиастов. Это не мейнстрим.
Мейнстрим — это финансы, системы учёта и контроля, офисный софт...
Но, повторюсь, количественных оценок у меня нет.
V>>Тут всё упирается в деньги. Есть платежеспособный спрос — напишут. VD>Все с точностью до наоборот. Сегодня деньги формируют спрос. Если МС захочет и даст денег на тот же Nemerle, то через пару лет о C# будут вспоминать как о тупиковой ветви эволюции С.
Вот это точно философия — что первично, дух или материя
Здравствуйте, VladD2, Вы писали:
VD>Когда вы перестанете молиться на MS, Oracle (Sun) или IBM, и начнете использовать перечисленные выше языки.
Да, мы молимся
Если серьёзно — далеко не всегда (в мейнстриме) есть сама возможность выбора.
Только, пожалуй, если заказчик — индивидуал или стартап.
Здравствуйте, vmpire, Вы писали:
V>Это из серии "лучше день потерять..." Чаще быстрее написать набор функций для тех же целей. С синтаксисом, конечно, не размахнёшься, но потом саппорту не надо рассказывать, что это за язык такой.
Типичное заблуждение основанное на грубых логических ошибках. "набор функций" — это такой же язык как и полноценынй язык. Разница только в том, что — это уродливый язык на котором очень трудно писать, и который еще труднее читать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vmpire, Вы писали:
V>Я это видел. Могу на это сказать, что согласен с тем, что построение DSL в Nemerle тоже удобно. И это как раз та фича, которая имеет наибольший, наверное, шанс войти в mainstream. Но — в виде расширения C# или Java.
Уже было одно расширение. Если не ошибаюсь называлось XC#. Захотело стать платным и безвременно почило в лету.
На самом деле не все фичи могут вот так взять и войти. Для некоторых требуется менять дизайн языка, что для мэйстрим языка, учитывая backward compatibility, это невозможно даже теоретически.
V>Это из серии "лучше день потерять..." Чаще быстрее написать набор функций для тех же целей. С синтаксисом, конечно, не размахнёшься, но потом саппорту не надо рассказывать, что это за язык такой.
А саппорту нужно рассказывать что такое лямбды и linq query comprehension?
Иногда просто удивительно, почему одни умные люди без всяких веских причин и основываясь на собственных домыслах считают других умных людей полными дебилами. Надеюсь этот аргумент был вызван лишь желанием привести аргумент, а не суровой действительностью. Или у вашего саппорта действительно серьёзные проблемы с лямбдами?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, vmpire, Вы писали:
V>Ссылкт на свои проекты и проекты пары энтузиастов. Это не мейнстрим. V>Мейнстрим — это финансы, системы учёта и контроля, офисный софт...
Предположим завтра где-то в финансах или системах учёта кто начал применять сабж. После этого сабж автоматчиски станет мэйнстримом?
VD>>Все с точностью до наоборот. Сегодня деньги формируют спрос. Если МС захочет и даст денег на тот же Nemerle, то через пару лет о C# будут вспоминать как о тупиковой ветви эволюции С. V>Вот это точно философия — что первично, дух или материя
Влад, конечно же, утрирует. Вспоминать начнут через 4 года.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, nikov, Вы писали:
N>Вот и получается такая ниша: проекты с большим количеством алгоритмически сложных вещей и немаленьким бюджетом, например, финансовая сфера.
Здравствуйте, VladD2, Вы писали:
FR>>В F# это дела сильно урезали. FR>>В OCaml (и SML) сигнатуры (не только файлы но и сигнатуры модулей) типы не обязательно фиксируют, чаще наоборот их используют для обобщенного программирования.
VD>Но тогда не остается никакой возможности уйти от обязательного расположения файлов в определенном порядке. Да?
Не совсем.
Да в том смысле что OCaml (и F#) .ml файл принимают за модуль а mli файл за сигнатуру модуля.
Поэтому для этих файлов может быть важен порядок линковки. Но в OCaml модуль != файлу в одном файле могут содержатся несколько
модулей в том числе и вложенных друг в друга (как namespace в C++), с ними уже попроще, можно тусовать.
Здравствуйте, vmpire, Вы писали:
V>Ссылкт на свои проекты и проекты пары энтузиастов. Это не мейнстрим. V>Мейнстрим — это финансы, системы учёта и контроля, офисный софт...
Здравствуйте, nikov, Вы писали:
GIV>>Как только ключевые игроки рынка (MS, IBM, Oracle и тд и тп) сделают ставку на один из них. GIV>>Что означает никогда. GIV>>Хотя бы потому что NIH.
N>F# изобретен в Microsoft Research, и Microsoft уже сделал на него ставку.
Здравствуйте, VladD2, Вы писали:
V>>Ссылкт на свои проекты и проекты пары энтузиастов. Это не мейнстрим. VD>А, да. Забыл. "Миллионы мух не могут ошибаться." — Железная логика!
Миллионы мух в данный момент летают в другом районе и менять дислокацию не собираются.
Ошибаются они или нет — я не знаю.
V>>Но, повторюсь, количественных оценок у меня нет. VD>У тебя их вообще нет. А при приведении примеров (которые ты просил) сразу пошла апелляция к миллионам мух.
Да, их нет, о чём я прямо и сказал. Впрочем, у Вас я их тоже не видел. Есть ссылки на некоторые проекты, наверняка нужные и полезные, но количественный состав мейнстрима нигде не приведён.
У меня есть только личный опыт и опыт знакомых, коллег и заказчиков. Специального исследования не проводил, так как в данный момент статистика не интересна.
Ещё раз обращаю внимание, что я отвечал на вопрос "есть ли шанс у других языков стать мейнстримом и почему", а не "почему Nemerle такой плохой".
Вы же, видимо, пытаетесь в этомтреде добиться ответа на совсем другой вопрос: "Почему никто не пишет на Nemerle, ведь он такой хороший".
Здравствуйте, IT, Вы писали:
V>>Ссылкт на свои проекты и проекты пары энтузиастов. Это не мейнстрим. V>>Мейнстрим — это финансы, системы учёта и контроля, офисный софт... IT>Предположим завтра где-то в финансах или системах учёта кто начал применять сабж. После этого сабж автоматчиски станет мэйнстримом?
Если массово — то да. А отдельные проекты и сейчас есть.
Здравствуйте, FR, Вы писали:
V>>Ссылкт на свои проекты и проекты пары энтузиастов. Это не мейнстрим. V>>Мейнстрим — это финансы, системы учёта и контроля, офисный софт...
FR>Функциональщина в финансах применяется например: FR>http://www.janestreet.com/technology/ocaml.php FR>http://www.lexifi.com/
Да кто бы спорил. Но ведь это отдельные островки в море императивщины.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, IT, Вы писали:
IT>>Мне тоже понравилось Да у Немерле у самого название ещё то
AVK>Давно бы уже переименовали.
Здравствуйте, AndrewVK, Вы писали:
AVK>В JVM дженерики вроде как есть только на уровне метаданных, что в CLR легко обеспечивается атрибутами.
Это уж совсем маразм — игнорировать настоящие дженерики и эмулировать их. В этом случае Скала все равно будет выглядеть ненатурально. С одной стороны не будте совместимости с другими языками. С другой код написанный на ней будет существенно медленее аналогичного написанного на родных языках.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Это уж совсем маразм — игнорировать настоящие дженерики и эмулировать их. В этом случае Скала все равно будет выглядеть ненатурально. С одной стороны не будте совместимости с другими языками. С другой код написанный на ней будет существенно медленее аналогичного написанного на родных языках.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Но она хотя бы *будет*.
Просто наличие некой вещи имеет значение только при некоторых условиях. Например, мне пофигу на то что есть Бугати Веерон просто потому, что я не могу им воспользоваться. Та же фигня и со скалой. Невозможность воспользоваться дотнет-дженериками и низкая производительность делает для меня этот язык неприменимым.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
AVK>Если мы хотим поддерживать JVM, то другого варианта нет.
Ну, почему же? Есть! Не поддерживать .NET, что они в общем-то и делают. Реальность такова, что даже когда создатели Скалы предоставляли вариант совместимый с .NET, все равно его никто не использвал.
Потом под .NET-ом есть аналогичыные языки — F# и Nemerle (который во многом его превосходит). Так что особого смысла нет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ну, почему же? Есть! Не поддерживать .NET, что они в общем-то и делают.
Производительность скаловских дженериков от этого лучше не становится. Да и вообще — Скала не промышленный язык даже близко, это скорее полномасштабный эксперимент. Будет ли кто то на базе Скалы делать мейнстримовый компилятор — большой вопрос.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, VladD2, Вы писали:
VD>Просто наличие некой вещи имеет значение только при некоторых условиях. Например, мне пофигу на то что есть Бугати Веерон просто потому, что я не могу им воспользоваться. Та же фигня и со скалой. Невозможность воспользоваться дотнет-дженериками и низкая производительность делает для меня этот язык неприменимым.
Ну тут я не согласен.
Во-первых, чем больше ФЯ под CLR, тем лучше. У людей будет формироваться интерес к ФЯ как таковым. К тому же Скала язык все же достаточно известный.
Во-вторых, не вижу, почему Scala@CLR должна быть медленее, чем Scala@JVM
Ну и наконец, как я понимаю, производительность будет проседать все же во вполне конкретных сценариях, и не всегда это будет заметно.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Ну и наконец, как я понимаю, производительность будет проседать все же во вполне конкретных сценариях, и не всегда это будет заметно.
Проблема только в том, что сценариев с использованием дженериков становится все больше. По сути, их массово нет только в UI, но там и функциональщина не особо нужна.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, AndrewVK, Вы писали:
ВВ>>Ну и наконец, как я понимаю, производительность будет проседать все же во вполне конкретных сценариях, и не всегда это будет заметно. AVK>Проблема только в том, что сценариев с использованием дженериков становится все больше. По сути, их массово нет только в UI, но там и функциональщина не особо нужна.
Проблема с "ненастоящими" генериками, как я понимаю, прежде всего в упаковке. Там где упаковка не требуется, т.е. для референс-типов, и CLR не генерит отдельные типы. Т.е. даже генерики будут медленнее далеко не всегда, а лишь в ряде конкретных случаев.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Проблема с "ненастоящими" генериками, как я понимаю, прежде всего в упаковке.
Не только. Постоянный кастинг в полиморфных коллекциях тоже не бесплатен, особенно для интерфейсов.
ВВ> Там где упаковка не требуется, т.е. для референс-типов, и CLR не генерит отдельные типы.
Но устраняет кастинг.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, FR, Вы писали:
AVK>>Вопрос в том, какую. Люк в свое время говорил, что текущее видение на F# — экспериментальный язык для гиков.
FR>Так не пойдет это место уже давно Хаскелем занято.
Пойдет. Хаскель далеко не идеален. И для дотнета он код генерить не умеет.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, AndrewVK, Вы писали:
ВВ>>Проблема с "ненастоящими" генериками, как я понимаю, прежде всего в упаковке. AVK>Не только. Постоянный кастинг в полиморфных коллекциях тоже не бесплатен, особенно для интерфейсов.
А в JVM кастинг есть?
ВВ>> Там где упаковка не требуется, т.е. для референс-типов, и CLR не генерит отдельные типы. AVK>Но устраняет кастинг.
А тут можно по-подробнее? Каким образом устраняется кастинг?
Здравствуйте, Воронков Василий, Вы писали:
AVK>>Не только. Постоянный кастинг в полиморфных коллекциях тоже не бесплатен, особенно для интерфейсов.
ВВ>А в JVM кастинг есть?
Скорее всего.
AVK>>Но устраняет кастинг.
ВВ>А тут можно по-подробнее? Каким образом устраняется кастинг?
В CLR есть гарантия, что несовместимые типы в дженерик не придут. Следовательно, джиту нет необходимости делать проверки. А вот в случае джавовских дженериков туда приходит object и при вызове специфичного метода нужно сделать проверку.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, AndrewVK, Вы писали:
FR>>Так не пойдет это место уже давно Хаскелем занято.
AVK>Пойдет. Хаскель далеко не идеален. И для дотнета он код генерить не умеет.
Для гиков F# слабоват, вообще это надо умудрится взять самый практичный функциональный язык (OCaml) и
пытаться из него делать язык для гиков.
Здравствуйте, FR, Вы писали:
AVK>>Пойдет. Хаскель далеко не идеален. И для дотнета он код генерить не умеет.
FR>Для гиков F# слабоват, вообще это надо умудрится взять самый практичный функциональный язык (OCaml) и FR>пытаться из него делать язык для гиков.
Да, мужики! Вам бы только по спорить, а о чем уже не важно.
Неужели тебе не ясно что имели в виду те люди из МС которые сказали фразу про гиков?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
N>>Главным образом, их туда вводили для интероперабельности с джавовскими wildcards (которые тоже являются урезанной разновидностью экзистенциальных типов). Ну и, вообще, это сильный инструмент для абстракции.
VD>Для абстракции в ООЯ нужно применять ООП. Мне кажется, что они уходят не в ту степь. Вместо простого и удобного языка для массового рынка они уходят в нишу "крутых" (читать как переусложненных) языков а-ля Хаскель.
Я напарываюсь постоянно, когда в фреймворке надо работать с коллекциями объектов, по разному параметризованных. Грубо говоря:
// framework:
class FormField[AppData]
class Form {
lazy val fieldsByName: Map[String, FormField[_]] = { /* получаем через рефлексию */ }
}
// app:
class MyForm extends Form {
val email = new FormField[String] (...)
val age = new FormField[Int] (...)
}
Здравствуйте, dimgel, Вы писали:
D>Я напарываюсь постоянно, когда в фреймворке надо работать с коллекциями объектов, по разному параметризованных. Грубо говоря:
D>
D>// framework:
D>class FormField[AppData]
D>class Form {
D> lazy val fieldsByName: Map[String, FormField[_]] = { /* получаем через рефлексию */ }
D>}
D>// app:
D>class MyForm extends Form {
D> val email = new FormField[String] (...)
D> val age = new FormField[Int] (...)
D>}
D>
D>Как это сделать без wildcards?
Опиши исходную задачу. То что я вижу из приведенного кода — это какая-то попытка реализовать динамику в статически типизированном языке. Есть огромная вероятность того, что сама необходимость вызвана некоторыми ограничениями в зыке, или попросту неверным дизайнерским выбором.
Сам факт использования рефлексии зачастую является признаком проблем.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Опиши исходную задачу. То что я вижу из приведенного кода — это какая-то попытка реализовать динамику в статически типизированном языке. Есть огромная вероятность того, что сама необходимость вызвана некоторыми ограничениями в зыке, или попросту неверным дизайнерским выбором.
Дык задача была простая: удобный модуль форм, без необходимости пользователю фреймворка писать кучу boilerplate-кода. В частности, значения атрибута name для <input/> берутся через рефлексию из имён полей класса. Т.е. в шаблоне формы юзер пишет
где значение поля берётся из одноимённого поля переданного в форму DTO (вот эту работу с состоянием я возможно сделаю явной, добавляя геттеры/сеттеры в объявление поля, хотя букв в пользовательском коде сразу станет намного больше).
VD>Сам факт использования рефлексии зачастую является признаком проблем.
Во всех известных мне java-фреймворках рефлексия используется чуть более, чем всегда.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, VladD2, Вы писали:
VD>>Опиши исходную задачу. То что я вижу из приведенного кода — это какая-то попытка реализовать динамику в статически типизированном языке. Есть огромная вероятность того, что сама необходимость вызвана некоторыми ограничениями в зыке, или попросту неверным дизайнерским выбором.
D>Дык задача была простая: удобный модуль форм, без необходимости пользователю фреймворка писать кучу boilerplate-кода. В частности, значения атрибута name для <input/> берутся через рефлексию из имён полей класса. Т.е. в шаблоне формы юзер пишет D>
где значение поля берётся из одноимённого поля переданного в форму DTO (вот эту работу с состоянием я возможно сделаю явной, добавляя геттеры/сеттеры в объявление поля, хотя букв в пользовательском коде сразу станет намного больше).
Для ASP.NET MVC можно писать так:
<td>@Html.EditorFor(m => m.Email)</td>
Выделенное — код на C#, который будет проверяться при компиляции.
Там конечно внутри будет рефлексия работать.
Уверен что на nemelre можно не хуже шаблонизатор сделать, который еще на валидность разметку проверять будет.
VD>>Сам факт использования рефлексии зачастую является признаком проблем. D>Во всех известных мне java-фреймворках рефлексия используется чуть более, чем всегда.
Потому что java — очень слабый язык.
Здесь m — это что?
G>Там конечно внутри будет рефлексия работать.
Во-во, при реализации фреймворка без рефлексии никуда.
D>>Во всех известных мне java-фреймворках рефлексия используется чуть более, чем всегда. G>Потому что java — очень слабый язык.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, gandjustas, Вы писали:
G>>
G>><td>@Html.EditorFor(m => m.Email)</td>
G>>
D>Здесь m — это что?
Параметр лямбды, тип задается во View.
G>>Там конечно внутри будет рефлексия работать. D>Во-во, при реализации фреймворка без рефлексии никуда.
Нет, суть в том что программист может написать код на родном языке, в этом самом шаблонизаторе и этот код будет проверяться при компиляции.
На nemerle можно сделать шаблонизтор, который не будет внутри использовать рефлексию, правда шаблоны будут статичны.
Хотя имея compiler-as-service разница не большая.
D>>>Во всех известных мне java-фреймворках рефлексия используется чуть более, чем всегда. G>>Потому что java — очень слабый язык. D>См. выше.
В Java даже так не выйдет.
В принципе текстовый шаблонизатор, проверяемый при компиляции, на Nemerle сейчас есть. А в asp.net mvc нужно еще доставать атрибуты и тому подобное, это делается только рефлексией в .NET.
D>>Здесь m — это что? G>Параметр лямбды, тип задается во View.
— Где мы находимся? — На воздушном шаре! Я имел в виду — DTO или что ещё. Я к сожалению ASP.NET не знаю, поэтому первый вопрос, который у меня возникает при взгляде на этот пример: а как этот EditorFor определяет имя input, тип (text или password) и как туда можно прикрутить прочие атрибуты типа onchange?
G>В принципе текстовый шаблонизатор, проверяемый при компиляции, на Nemerle сейчас есть. А в asp.net mvc нужно еще доставать атрибуты и тому подобное, это делается только рефлексией в .NET.
Если я правильно понял, то ты агитируешь на счёт того, что на правильных языках при правильном подходе мне не потребуется даже во фреймворке рефлексию использовать. Честно говоря, не верится. Я напишу упрошённо, как у меня сейчас выглядит пользовательский код, использующий lib.web forms, и укажу, где она используется у меня сейчас:
class LoginDTO (
var login: String, // mutable fields; immutable DTO планируются,
var password: String // но пока не прикидывал
)
object LoginForm extends Form[LoginDTO] {
val login = Field(WText, VRequiredTrim & VRegexp("^\w+$"), CString)
val password = FPassword(VRequired)
protected def htmlImpl = <table>...{login.w}...{password.w}...</table>
protected def validate = {
val result = super.validate
if (!result.ok) return result
if (!BL.isValidUser(result.dto.login, result.dto.password))
return /*новый объект с сообщением об ошибке*/
return result
}
}
// Рендеринг:
LoginForm.html(dto)
Здесь рефлексия используется в следующих местах:
1) Form.html(dto) с распихивает поля dto в thread-local переменные одноимённых полей формы (dto.login -> LoginForm.login._tempData, ...) и вызывает htmlImp(). В результате внутри htmlImp(), Widget.w() может вызываться вообще без параметров и брать необходимые ему данные из этого thread-local _tempData.
2) Form.validate() проходится по сгенерированному рефлексией списку fieldsByName и для каждого поля вызывает его валидатор:
for ((name, field) <- fieldsByName) ...request.params(name)(field.validator).
Запись успешно свалидированного параметра в поле DTO также выполняется через рефлексию. Кросс-проверки, включающие одновременно несколько полей, реализуются пока что только в пользовательском коде, как показано в примере (вызов BL.isValidUser()).
Ясно, что из-за обилия рефлексии тут у меня всё на соплях: если тип поля DTO не соответствует типу поля формы, компилятор не отловит. Как бы не пришлось учиться писать плагинчик к компилятору, чтобы проверял это дело. Потому что я не вижу, где здесь можно избавиться от рефлексии, не увеличивая объём пользовательского кода. Пробовал например так (чем-то смахивает на твой пример с анонимной функцией):
val login = FText(VRequiredTrim & ..., _.login, {_.login = _})
Т.е. с явными геттером и сеттером вместо копирования через рефлексию. Если бы оно работало, то рефлексия осталась бы ровно в одном месте — формирование fieldsByName (но всё равно осталась бы). Но во-первых, при длинных идентификаторах букв в коде становится дофига, а во-вторых на реальных примерах выясняется, что вывод типов в scala далеко не так хорош, как мечталось, не хавает он такие краткие записи. Вот доберусь как-нибудь, сделаю минимальный пример и запощу им в качестве issue.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, gandjustas, Вы писали:
G>>>>
G>>>><td>@Html.EditorFor(m => m.Email)</td>
G>>>>
D>>>Здесь m — это что? G>>Параметр лямбды, тип задается во View.
D>- Где мы находимся? — На воздушном шаре! Я имел в виду — DTO или что ещё.
Вообще говоря любой тип.
D>Я к сожалению ASP.NET не знаю, поэтому первый вопрос, который у меня возникает при взгляде на этот пример: а как этот EditorFor определяет имя input, тип (text или password) и как туда можно прикрутить прочие атрибуты типа onchange?
Он подставляет другой шаблон в соответствии с типом (можно указать бизнес-тип для строк, чисел и дат). Дополнительные параметры, такие как обязательность, диапазон значений итп задаются метаданными.
Стандартный провайдер метаданных берет их из атрибутов класса или buddy-metadata класса.
G>>В принципе текстовый шаблонизатор, проверяемый при компиляции, на Nemerle сейчас есть. А в asp.net mvc нужно еще доставать атрибуты и тому подобное, это делается только рефлексией в .NET.
D>Если я правильно понял, то ты агитируешь на счёт того, что на правильных языках при правильном подходе мне не потребуется даже во фреймворке рефлексию использовать.
Скорее всего тебе не придется руками писать код, который использует рефлексию. Как например работают expression trees в C#.
D>Честно говоря, не верится.
А зря, некоторые вещи и сейчас так работают. А с мощными инструментами метапрограммирования, как в nemerle, можно вообще отказаться от рефлексии в рантайме.
D>Я напишу упрошённо, как у меня сейчас выглядит пользовательский код, использующий lib.web forms, и укажу, где она используется у меня сейчас:
D>
D>class LoginDTO (
D> var login: String, // mutable fields; immutable DTO планируются,
D> var password: String // но пока не прикидывал
D>)
D>object LoginForm extends Form[LoginDTO] {
D> val login = Field(WText, VRequiredTrim & VRegexp("^\w+$"), CString)
D> val password = FPassword(VRequired)
D> protected def htmlImpl = <table>...{login.w}...{password.w}...</table>
D> protected def validate = {
D> val result = super.validate
D> if (!result.ok) return result
D> if (!BL.isValidUser(result.dto.login, result.dto.password))
D> return /*новый объект с сообщением об ошибке*/
D> return result
D> }
D>}
D>// Рендеринг:
D>LoginForm.html(dto)
D>
D>Здесь рефлексия используется в следующих местах:
D>1) Form.html(dto) с распихивает поля dto в thread-local переменные одноимённых полей формы (dto.login -> LoginForm.login._tempData, ...) и вызывает htmlImp(). В результате внутри htmlImp(), Widget.w() может вызываться вообще без параметров и брать необходимые ему данные из этого thread-local _tempData.
D>2) Form.validate() проходится по сгенерированному рефлексией списку fieldsByName и для каждого поля вызывает его валидатор: D>for ((name, field) <- fieldsByName) ...request.params(name)(field.validator). D>Запись успешно свалидированного параметра в поле DTO также выполняется через рефлексию. Кросс-проверки, включающие одновременно несколько полей, реализуются пока что только в пользовательском коде, как показано в примере (вызов BL.isValidUser()).
D>Ясно, что из-за обилия рефлексии тут у меня всё на соплях: если тип поля DTO не соответствует типу поля формы, компилятор не отловит. Как бы не пришлось учиться писать плагинчик к компилятору, чтобы проверял это дело. Потому что я не вижу, где здесь можно избавиться от рефлексии, не увеличивая объём пользовательского кода. Пробовал например так (чем-то смахивает на твой пример с анонимной функцией):
D>
D>Т.е. с явными геттером и сеттером вместо копирования через рефлексию. Если бы оно работало, то рефлексия осталась бы ровно в одном месте — формирование fieldsByName (но всё равно осталась бы). Но во-первых, при длинных идентификаторах букв в коде становится дофига, а во-вторых на реальных примерах выясняется, что вывод типов в scala далеко не так хорош, как мечталось, не хавает он такие краткие записи. Вот доберусь как-нибудь, сделаю минимальный пример и запощу им в качестве issue.
Кажется проблема тут в неправильной архитектуре.
Но я не очень понял как это все работает и scala я вообще не не знаю.
На первый взгляд две проблемы:
1)stateful форма, которая пытается имитировать десктопную форму (в ASP.NET это проходили — плохой путь)
2)Сам html шаблон не является типизированным, то есть не является объектом какого-то типа (может я неправ)
Здравствуйте, gandjustas, Вы писали:
G>Кажется проблема тут в неправильной архитектуре.
Гы, эта проблема перманентная. Но я пока не вижу, в какую сторону ползти. Что ты написал про атрибуты — это, как я понимаю, те же аннотации в java/scala, получаемые через рефлексию. На немерле примерчик бы, посмотреть как люди живут.
G>На первый взгляд две проблемы: G>1)stateful форма, которая пытается имитировать десктопную форму (в ASP.NET это проходили — плохой путь)
Ну stateful она только внутри контекста метода html(). При выходе из html() thread-local state очищается. Хак ради краткости записи {field.w} без аргументов (а также для возможности подстановки непрошедшего валидацию значения поля из засабмиченных данных вместо значения поля DTO).
G>2)Сам html шаблон не является типизированным, то есть не является объектом какого-то типа (может я неправ)
Шаблон поля формы — это экземпляр Widget[WidgetData]. Шаблон формы как отдельная сущность отсутствует. Но есть подозрение, что ты имеешь в виду нечто более толковое. Кинь в меня, пожалуйста, какой-нить ссылочкой на ASP.NET на объяснение, что это за "типизированный html шаблон" и какая от него польза.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, gandjustas, Вы писали:
G>>Кажется проблема тут в неправильной архитектуре.
D>Гы, эта проблема перманентная. Но я пока не вижу, в какую сторону ползти. Что ты написал про атрибуты — это, как я понимаю, те же аннотации в java/scala, получаемые через рефлексию.
Вроде того.
D>На немерле примерчик бы, посмотреть как люди живут.
На Nemerle пока такого не сделано.
G>>На первый взгляд две проблемы: G>>1)stateful форма, которая пытается имитировать десктопную форму (в ASP.NET это проходили — плохой путь)
D>Ну stateful она только внутри контекста метода html(). При выходе из html() thread-local state очищается. Хак ради краткости записи {field.w} без аргументов (а также для возможности подстановки непрошедшего валидацию значения поля из засабмиченных данных вместо значения поля DTO).
Суть в том что лучше разным кодом обрабатывать GET и POST, у них общего совсем мало. Объединяя все вместе нарушаешь SRP.
G>>2)Сам html шаблон не является типизированным, то есть не является объектом какого-то типа (может я неправ)
D>Шаблон поля формы — это экземпляр Widget[WidgetData]. Шаблон формы как отдельная сущность отсутствует. Но есть подозрение, что ты имеешь в виду нечто более толковое.
Ну собственно его и имею ввиду. А почему шаблон формы не может задаваться экземпляром такого же Widget?
У тебя получится на входе для GET: Widget[T] и T data. Внутри Widget может использовать рефлексию для вытаскивания полей из T. А еще лучше использоваться compile-time кодогенерацию по шаблону, которая будет проверять по типу T правильность всех выражений внутри шаблона для T.
Для POST: на входе текстовый запрос, он будет парсится некоторым кодом, будет вызываться формирование T data и валидация его. Лучше всего чтобы была также compile-time генерация года для этого дела, но и рефлексия тоже сойдет.
Весь прикол в том что всю compile-time генерацию можно в nemerle с помощью макросов описать.
D>Кинь в меня, пожалуйста, какой-нить ссылочкой на ASP.NET на объяснение, что это за "типизированный html шаблон" и какая от него польза.
Здравствуйте, gandjustas, Вы писали:
D>>Ну stateful она только внутри контекста метода html(). При выходе из html() thread-local state очищается. Хак ради краткости записи {field.w} без аргументов (а также для возможности подстановки непрошедшего валидацию значения поля из засабмиченных данных вместо значения поля DTO). G>Суть в том что лучше разным кодом обрабатывать GET и POST, у них общего совсем мало. Объединяя все вместе нарушаешь SRP.
Оно и обрабатывается разным. Виджет у меня — вообще пассивная вещь, что ему подсунули, то и рисует. Во, щас скажу: у меня каждое поле формы по сути параметризовано тремя типами: [AppData, WidgetData, PostedData]. Последний из них — либо строка, либо (для check box group) массив строк. Widget на вход получает только WidgetData. Преобразования между тремя типами выполняет Converter (в моём длинном примере это CString в поле login; возможно, я сделаю его implicit-параметром, чтобы скала сама по типопараметрам нужный находила). При рендеринге значения из поля DTO выполняется преобразование AppData -> WidgetData; при рендеринге засабмиченного значения, не прошедшего валидацию (т.е. когда AppData не существует), — преобразование PostedData -> WidgetData. Может оно и тяжеловато, но с SRP всё нормально — на уровне отдельных полей формы.
G>Ну собственно его и имею ввиду. А почему шаблон формы не может задаваться экземпляром такого же Widget?
Гы. Мне советовали также и про валидатор формы как отдельный объект, наподобие отдельных валидаторов полей формы. Я себе зарубку сделал, как дозрею до очередного марафона — буду ковыряться в этом направлении.
G>А еще лучше использоваться compile-time кодогенерацию по шаблону, которая будет проверять по типу T правильность всех выражений внутри шаблона для T. G>Весь прикол в том что всю compile-time генерацию можно в nemerle с помощью макросов описать.
Азы про макросы я из Владовых статей уяснил (довычитывать черновик последней так и не добрался — Влад, сорри), но как конкретно эта задача может выглядеть на практике — не вижу.
G>http://www.asp.net/mvc G>там правда много заботать придется чтобы разобраться. Но сейчас это ИМХО самый адекватный веб-фреймворк на статически типизированном языке.
Может ли кто из здесь присутствующих сравнить его с Wicket — в самых общих словах в плане удобства и богатства возможностей? Я Wicket только-только начал изучать. Немного поработав с Tapestry 5, я понял, что мои lib.web forms — это некая недоделка на пути к универсальной компонентной модели, но в целом от T5 я не в восторге. Сейчас у меня главный приоритет — прочувствовать основу Wicket и попытаться набросать архитектуру для stateless component. (Wicket — stateful, но как говорится "know your enemy".) Собсна главный вызов здесь — это само словосочетание "stateless component" (натуральный оксюморон), отсюда и всякие метания на тему геттеров/сеттеров/thread-local. Не вижу пока, как оно в итоге может быть, но чувствую, что определяющими окажутся ограничения языка.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, gandjustas, Вы писали:
G>>http://www.asp.net/mvc G>>там правда много заботать придется чтобы разобраться. Но сейчас это ИМХО самый адекватный веб-фреймворк на статически типизированном языке.
D>Может ли кто из здесь присутствующих сравнить его с Wicket — в самых общих словах в плане удобства и богатства возможностей? Я Wicket только-только начал изучать. Немного поработав с Tapestry 5, я понял, что мои lib.web forms — это некая недоделка на пути к универсальной компонентной модели, но в целом от T5 я не в восторге. Сейчас у меня главный приоритет — прочувствовать основу Wicket и попытаться набросать архитектуру для stateless component. (Wicket — stateful, но как говорится "know your enemy".) Собсна главный вызов здесь — это само словосочетание "stateless component" (натуральный оксюморон), отсюда и всякие метания на тему геттеров/сеттеров/thread-local. Не вижу пока, как оно в итоге может быть, но чувствую, что определяющими окажутся ограничения языка.
Любой component framemork для веба на практике абсолютно неюзабелен. Как только используешь какой-либо более-менее сложный компонент ты фактически теряешь контроль над генерируемым HTML кодом, кроме того обрекаешь себя на вечную борьбу с механизмами сохранения состояния.
Очень мало случаев когда описанные выше проблемы не мешают, в остальных "компонентные" фреймворки использовать нельзя.
Здравствуйте, gandjustas, Вы писали:
G>Любой component framemork для веба на практике абсолютно неюзабелен. Как только используешь какой-либо более-менее сложный компонент ты фактически теряешь контроль над генерируемым HTML кодом, кроме того обрекаешь себя на вечную борьбу с механизмами сохранения состояния.
G>Очень мало случаев когда описанные выше проблемы не мешают, в остальных "компонентные" фреймворки использовать нельзя.
Тем не менее, Wicket очень многие очень хвалят, а дыма без огня не бывает. Контроль над HTML-кодом я тоже люблю иметь полный, но надеюсь, что смогу если не решить, то хотя бы обойти эту проблему, если не буду увлекаться навороченными компонентами в составе фреймворка, а вместо этого обеспечу простой для пользователей способ добавлять свои. Ведь "компоненты" по большому счёту — это просто способ декомпозиции кода. Есть у меня надежда, что stateless component выйдет в итоге тупо пассивным хранилищем для двух ортогональных вещей: class Component(widget, eventHandler), из которых виджет — тупо функция Data => HTML. В этом случае, для пользователя не будет составлять никаких проблем наклепать нужных ему виджетов, генерирующих в точности нужный ему HTML.
Здравствуйте, dimgel, Вы писали:
D>Тем не менее, Wicket очень многие очень хвалят, а дыма без огня не бывает.
Кстати, авторы фреймворка в книге "Wicket in Action" (введение, дальше пока не ушёл) очень грамотно расписали свои мотивы и общую идею, которая суммируется так: "Wicket bridges the impedance mismatch between the stateless HTTP and stateful server-side programming in Java." Открыто проводили аналогию с ORM, которые тоже "bridge impedance". Так что есть надежда, что при таком формализованном подходе всё действительно сделано по уму.
Здравствуйте, gandjustas, Вы писали:
G>Любой component framemork для веба на практике абсолютно неюзабелен. Как только используешь какой-либо более-менее сложный компонент ты фактически теряешь контроль над генерируемым HTML кодом, кроме того обрекаешь себя на вечную борьбу с механизмами сохранения состояния.
G>Очень мало случаев когда описанные выше проблемы не мешают, в остальных "компонентные" фреймворки использовать нельзя.
Они вообще бяка. Даже для десктопа.
Есть у меня мысль: что для ГУИ рулит реактивный MVVM.
http://www.impredicative.com/ur/
Статически типизирован. Рантайм рефлексия отсутствует за не надобностью.
Правда автор далек от практики и в примерах намешал ViewModel и View в одну кучу. С теоретиками такое часто случается.
Но ничто не мешает писать правильно.
Синтаксис местами нужно допилить напильником.
Жабаскриптовая библиотека.
Примеры написаны правильно.
Плохо то что жабаскрипт динамически типизирован.
Да и синтакс местами хромает.
В принципе на немерле можно сделать все правильно. Но на немерле1 многовато возьни будет. На немерле2 все получится несравнимо проще.
Вообще все идет к тому что немерле2 будет движком для создания и тесной интеграции статически типизированных языков.
Парсер уже почти готов. Принципиальных проблем не видно нужно только дописать.
Для вывода типов я уже придумал весьма циничный алгоритм но пока еще даже не прототипировал. Так что пока не ясно насколько я прав. Но если прав то получится очень быстрый, мощьный и что совсем не обычно расширяемый вывод типов.
Например сейчас в http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/ типизация правил осуществляется ручками. С новым выводом типов можно будет заставить компилятор типизировать пользовательские ДСЛ.
Перекладывание этой работы на основной компилятор не только упростит создание собственных ДСЛ но еще и приведет к тому что в интеграции автоматом появится автокомплит и навигация для данного ДСЛ (навигацию можно прикрутить и сейчас но опять же ручками).
Это конечно если я в своих расчетах нигде не ошибся.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, dimgel, Вы писали:
D>>Тем не менее, Wicket очень многие очень хвалят, а дыма без огня не бывает.
D>Кстати, авторы фреймворка в книге "Wicket in Action" (введение, дальше пока не ушёл) очень грамотно расписали свои мотивы и общую идею, которая суммируется так: "Wicket bridges the impedance mismatch between the stateless HTTP and stateful server-side programming in Java." Открыто проводили аналогию с ORM, которые тоже "bridge impedance". Так что есть надежда, что при таком формализованном подходе всё действительно сделано по уму.
В одной лжи они опираются на другую ложь. Прекрасно.
Если уж на то пошло, то ни один ORM не может победить то что data != objects. Прагматичные разработчики и не пытаются это победить, они упростить доступ к данным учитывая эту специфику.
Аналогично нельзя победить (те окончательно устранить) различия stateless http и stateful bullshit, потому что bullshit не денется никуда, зато появятся куча неочевидных проблем.
Не надо побеждать stateless http неявно прикручивая к нему состояние. Лучше сделать инструмент, который упрощает работу именно со stateless http и текстовым html.
Здравствуйте, gandjustas, Вы писали:
G>Если уж на то пошло, то ни один ORM не может победить то что data != objects. Прагматичные разработчики и не пытаются это победить, они упростить доступ к данным учитывая эту специфику.
Это ты про не-ORM типа LINQ и BLTookit? Я в общем тоже последнее время предпочитаю Squeryl, Scala DSL аналог LINQ. На функциональщину и stateless отлично ложится. Но в отличие от ORM, горя со stateful-фреймворками я ещё хлебнуть не успел, попробовать хочется.
G>Аналогично нельзя победить (те окончательно устранить) различия stateless http и stateful bullshit, потому что bullshit не денется никуда, зато появятся куча неочевидных проблем. G>Не надо побеждать stateless http неявно прикручивая к нему состояние. Лучше сделать инструмент, который упрощает работу именно со stateless http и текстовым html.
Ну, моя либа пока ещё называется "stateless". Просто смущает меня её чрезмерная низкоуровневость. Даже не так: смущает, что собственными формами мне пользоваться неприятно. Вот и ищу идеи для развития. Ищу во вражеском лагере, т.к. интуиция. Из stateless java фреймворков я знаю только Spring MVC, он весь построен на аннотациях, а мне такой подход не нравится — там этой самой рефлексии (с которой собственно и началось обсуждение) больше чем нормального кода, статической типизацией опять же не пахнет. Я собственно пытаюсь сделать вещь, максимально заточенную под (как я постепенно начинаю убеждаться — убогие) возможности скалы, на голом языке с минимумом магии, и какая именно из разыскиваемых мною идей может в итоге наилучшим образом лечь на язык — заранее не знаю. В общем, посмотрим. Спасибо за обсуждение.
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, gandjustas, Вы писали:
G>>Любой component framemork для веба на практике абсолютно неюзабелен. Как только используешь какой-либо более-менее сложный компонент ты фактически теряешь контроль над генерируемым HTML кодом, кроме того обрекаешь себя на вечную борьбу с механизмами сохранения состояния.
G>>Очень мало случаев когда описанные выше проблемы не мешают, в остальных "компонентные" фреймворки использовать нельзя. WH>Они вообще бяка. Даже для десктопа.
Для десктопа ОК, иначе придется дофига всего писать.
WH>Есть у меня мысль: что для ГУИ рулит реактивный MVVM.
MVVM как в WPF далеко не все проблемы решает.
Хотя заложена очень здравая концепция: отделение логики (код) от представления (xaml) и все вместе от состояния (viewmodel). Все это связывается между собой мощным механизмом байндинга.
WH>http://www.impredicative.com/ur/ WH>Статически типизирован. Рантайм рефлексия отсутствует за не надобностью. WH>Правда автор далек от практики и в примерах намешал ViewModel и View в одну кучу. С теоретиками такое часто случается. WH>Но ничто не мешает писать правильно. WH>Синтаксис местами нужно допилить напильником.
Все красиво, но 100% работать не будет. Разметка не должна быть в файлах к кодом. В худшем случае наоборот: вкрапления кода в разметку, причем должна быть возможность править разметку без перекомпиляции.
WH>Knockout
WH>Жабаскриптовая библиотека. WH>Примеры написаны правильно. WH>Плохо то что жабаскрипт динамически типизирован. WH>Да и синтакс местами хромает.
А мне либа совсем не нравится. Создавать ручками viewModel в динамически типизрованном языке, где есть eval — моветон.
Лучше так: http://msdn.microsoft.com/en-us/magazine/ee819084.aspx
С синтаксисом вроде неочень, но ms сейчас такие фичи в jQuery пишет вроде уже можно пощупать: http://weblogs.asp.net/scottgu/archive/2010/05/07/jquery-templates-and-data-linking-and-microsoft-contributing-to-jquery.aspx
WH>В принципе на немерле можно сделать все правильно. Но на немерле1 многовато возьни будет. На немерле2 все получится несравнимо проще. WH>Вообще все идет к тому что немерле2 будет движком для создания и тесной интеграции статически типизированных языков. WH>Парсер уже почти готов. Принципиальных проблем не видно нужно только дописать. WH>Для вывода типов я уже придумал весьма циничный алгоритм но пока еще даже не прототипировал. Так что пока не ясно насколько я прав. Но если прав то получится очень быстрый, мощьный и что совсем не обычно расширяемый вывод типов. WH>Например сейчас в http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser/ типизация правил осуществляется ручками. С новым выводом типов можно будет заставить компилятор типизировать пользовательские ДСЛ. WH>Перекладывание этой работы на основной компилятор не только упростит создание собственных ДСЛ но еще и приведет к тому что в интеграции автоматом появится автокомплит и навигация для данного ДСЛ (навигацию можно прикрутить и сейчас но опять же ручками). WH>Это конечно если я в своих расчетах нигде не ошибся.
Реквестирую killerapp для Nemerle2: ViewEngine для ASP.NET MVC 3 c синтаксисом Razor со всеми плюшками типа автоматической подсветки синтаксиса.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, gandjustas, Вы писали:
G>>Если уж на то пошло, то ни один ORM не может победить то что data != objects. Прагматичные разработчики и не пытаются это победить, они упростить доступ к данным учитывая эту специфику.
D>Это ты про не-ORM типа LINQ и BLTookit?
Это неважно в принципе. В первую очередь не надо пытаться делать вид что у нас в базе "живут" объекты. От этого можно много чего упростить.
D>Я в общем тоже последнее время предпочитаю Squeryl, Scala DSL аналог LINQ. На функциональщину и stateless отлично ложится.
А он какое-нить отношение к монадам имеет или отдельным шкафом?
Ведь прелесть LINQ в том что запросы для коллекций в памяти и к бд одинаково выглядят.
D>Но в отличие от ORM, горя со stateful-фреймворками я ещё хлебнуть не успел, попробовать хочется.
Не стоит.
G>>Аналогично нельзя победить (те окончательно устранить) различия stateless http и stateful bullshit, потому что bullshit не денется никуда, зато появятся куча неочевидных проблем. G>>Не надо побеждать stateless http неявно прикручивая к нему состояние. Лучше сделать инструмент, который упрощает работу именно со stateless http и текстовым html.
D>Ну, моя либа пока ещё называется "stateless". Просто смущает меня её чрезмерная низкоуровневость. Даже не так: смущает, что собственными формами мне пользоваться неприятно. Вот и ищу идеи для развития.
Забей на формы. Это искуственная сущность, которая тебе пространство для маневра ограничивает.
D>Ищу во вражеском лагере, т.к. интуиция. Из stateless java фреймворков я знаю только Spring MVC, он весь построен на аннотациях, а мне такой подход не нравится — там этой самой рефлексии (с которой собственно и началось обсуждение) больше чем нормального кода, статической типизацией опять же не пахнет.
Java как язык слабовата, там по-другому не сделаешь. А вот scala ИМХО побольше интересного умеет, но архитектуру надо в корне менять, а не пытаться тянуть то что в java есть.
D>Я собственно пытаюсь сделать вещь, максимально заточенную под (как я постепенно начинаю убеждаться — убогие) возможности скалы, на голом языке с минимумом магии, и какая именно из разыскиваемых мною идей может в итоге наилучшим образом лечь на язык — заранее не знаю. В общем, посмотрим. Спасибо за обсуждение.
Удачи. не брезгуй внешней кодогененрацией, если язык не умеет. Пиши её прямо на scala, а потом встраивай плагинами в IDE.
Здравствуйте, gandjustas, Вы писали:
G>А он какое-нить отношение к монадам имеет или отдельным шкафом? G>Ведь прелесть LINQ в том что запросы для коллекций в памяти и к бд одинаково выглядят.
Не, это database-only костыль пока что.
G>Забей на формы. Это искуственная сущность, которая тебе пространство для маневра ограничивает.
Эта искуственная сущность имеет уникальное свойство напрочь отравлять жизнь в любом проекте на любом фреймворке. Я вообще весь lib.web начал исключительно в русле размышлений над удобной обработкой форм.
G>Удачи. не брезгуй внешней кодогененрацией, если язык не умеет. Пиши её прямо на scala, а потом встраивай плагинами в IDE.
Спасибо. За внешнюю кодогенерацию — ох не хочется, от уж совсем костыли... Проще уж на немерл перейти, и советчиков больше будет (и все на русском, на родном панимаеш кывте) токмо не готовая я пока ещё.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, gandjustas, Вы писали:
G>>А он какое-нить отношение к монадам имеет или отдельным шкафом? G>>Ведь прелесть LINQ в том что запросы для коллекций в памяти и к бд одинаково выглядят.
D>Не, это database-only костыль пока что.
Жаль.
G>>Забей на формы. Это искуственная сущность, которая тебе пространство для маневра ограничивает. D>Эта искуственная сущность имеет уникальное свойство напрочь отравлять жизнь в любом проекте на любом фреймворке. Я вообще весь lib.web начал исключительно в русле размышлений над удобной обработкой форм.
Глянь как это делается в asp.net mvc, там есть то что ты хочешь.
G>>Удачи. не брезгуй внешней кодогененрацией, если язык не умеет. Пиши её прямо на scala, а потом встраивай плагинами в IDE.
D>Спасибо. За внешнюю кодогенерацию — ох не хочется, от уж совсем костыли... Проще уж на немерл перейти, и советчиков больше будет (и все на русском, на родном панимаеш кывте) токмо не готовая я пока ещё.
N2 еще не готов, а на N1 действительно многовато писанины по признанию разработчиков.
Здравствуйте, gandjustas, Вы писали:
G>Удачи. не брезгуй внешней кодогененрацией, если язык не умеет. Пиши её прямо на scala, а потом встраивай плагинами в IDE.
Кстати, expression trees, конечно в Scala нет, но есть compiler plugins.
Здравствуйте, lomeo, Вы писали:
L>Здравствуйте, gandjustas, Вы писали:
G>>Удачи. не брезгуй внешней кодогененрацией, если язык не умеет. Пиши её прямо на scala, а потом встраивай плагинами в IDE.
L>Кстати, expression trees, конечно в Scala нет, но есть compiler plugins.
Здравствуйте, dimgel, Вы писали:
D>Азы про макросы я из Владовых статей уяснил (довычитывать черновик последней так и не добрался — Влад, сорри), но как конкретно эта задача может выглядеть на практике — не вижу.
Посмотри, как подошел к вопросу создания веб-фреймворка камрад Ziaw в проекте Nemerle on Rails.
Здравствуйте, Пельмешко, Вы писали:
П>у меня никак не получается въехать в параметрический полиморфизм высших порядков и экзистенциональные типы, а особенно в их юзкейсы.
Здравствуйте, dimgel, Вы писали:
D>Если я правильно понял, то ты агитируешь на счёт того, что на правильных языках при правильном подходе мне не потребуется даже во фреймворке рефлексию использовать.
Я тебе больше скажу. Тебе даже само понятие фрэймворк не потрбуется, так как все будет реализовываться тем, что раньше называлось "библиотека". Только это будет библиотека макросов.
Вот пример такой библиотеки заменяющей фрэймворк: Nemerle on rails
А вот пример реализации шаблонрго движка редеренга XML-я реализованного в виде встроенного в язык DSL-я Nemerle.Xml: Пример использования. Исходники макроса.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Откровенно говоря, ни черта не понял — ни что оно делает, ни что из себя представляет.
Однако разглядел "using System.Reflection" в первой строчке. :-P
Здравствуйте, gandjustas, Вы писали:
WH>>Они вообще бяка. Даже для десктопа. G>Для десктопа ОК, иначе придется дофига всего писать.
Что писать?
G>MVVM как в WPF далеко не все проблемы решает. G>Хотя заложена очень здравая концепция: отделение логики (код) от представления (xaml) и все вместе от состояния (viewmodel). Все это связывается между собой мощным механизмом байндинга.
viewmodel должна быть реактивной.
А в WPF это достигается через страшные костыли.
G>Все красиво, но 100% работать не будет. Разметка не должна быть в файлах к кодом.
Осталось выяснить чем разметка не код.
G>В худшем случае наоборот: вкрапления кода в разметку, причем должна быть возможность править разметку без перекомпиляции.
А зачем?
Тем более что без перекомпиляции у нас не будет проверки типов.
G>А мне либа совсем не нравится. Создавать ручками viewModel в динамически типизрованном языке, где есть eval — моветон.
Хочешь eval используй. В чем проблема то?
G>Лучше так: http://msdn.microsoft.com/en-us/magazine/ee819084.aspx G>С синтаксисом вроде неочень, но ms сейчас такие фичи в jQuery пишет вроде уже можно пощупать: G>http://weblogs.asp.net/scottgu/archive/2010/05/07/jquery-templates-and-data-linking-and-microsoft-contributing-to-jquery.aspx
Что-то там все очень неуклюже.
G>Реквестирую killerapp для Nemerle2: ViewEngine для ASP.NET MVC 3 c синтаксисом Razor со всеми плюшками типа автоматической подсветки синтаксиса.
Осталось понять нахрена после этого будет нужен сам ASP.NET?
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Гламурненько. Хотя начиная с "_ =" в строке 50 и всё что ниже не понял, так что смотрю только на "xml <# #>". Я так понимаю, главный пойнт в том, что это именно на макросах, а не встроенная в язык поддержка XML, как в скале. Вопрос, кстати: а эта штука умеет оборачивать в if/unless группу элементов, чтобы в каждом элементе группы не дублировать условие?
В догонку про замечание Влада, что будут библиотеки макросов вместо фреймворков — "фреймворк" и "библиотека" ИМХО тут синонимы. Понятно, что фреймворки на языке с поддержкой МП (ФП,ООП,АБЫВАРЛГ) будут использовать МП (ФП,ООП,АБЫВАРЛГ).
Здравствуйте, dimgel, Вы писали:
VD>>Пример использования.
D>Откровенно говоря, ни черта не понял — ни что оно делает, ни что из себя представляет.
Это наверно потому что я косой . Я не туда ссылку дал.
Так понятнее: AsyncTest.n? (подсветка кода кривая, не обращайте внимание на нее).
D>Однако разглядел "using System.Reflection" в первой строчке. :-P
Это был стандартный файл которые Visual Studio добавляет к любому проекте. В нем описывается метаинформация проекта. Я просто нечаянно ссылкой промазал. Смотреть на этот файл бессмысленно. А System.Reflection там видимо потому, что один из атрибутов описан в этом пространстве имен.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, dimgel, Вы писали:
D>Гламурненько. Хотя начиная с "_ =" в строке 50 и
Немерле выдает предупреждение когда возвращаемое значение игнорируется (обычно это ошибка).
Но когда действительно нужно проигнорировать возвращаемое значения его присваивают универсальной черной дыре которая ест все.
D>всё что ниже не понял, так что смотрю только на "xml <# #>".
А там ничего особо интересного нет.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
В принципе, только на это и надо смотреть. Остальное просто тесты функциональнсоти. Так как цель у них была только проверить возможности, то понять там что либо сложно. Бессмысленные действия они и есть бессмысленные действия .
Но на всякий пожарный распишу что к чему:
// запуск процесса, так как там путь к html-страничке, это приводит к открытию страницы браузером выбранным по умолчанию
50 _ = Diagnostics.Process.Start(path);
51 }
52
// Запуск тестовых функции с передачей в нее "типов" (объектов рефлексии описывающих типы)
// Рефлексия здесь используется только как источник данных.
// Так же стоит обратить внимание на то, что функции являются локальными функциями, т.е. функциями объявленными внутри методов.
53 makeClassInfoPage(typeof(XAttribute));
54 makeClassInfoPage(typeof(TestClass));
55
// Это объявление nullable-объекта, т.е. объекта вэлью-типа (int в данном случае) который таки может принимать значение null. Это специфика дотнета.
56 def z : int? = 42;
// Это описание атрибутов без "сахара" (т.е. без использования макроса), на уровне XML-AST.
57 def a = [XAttribute("LANG", "enu"), XAttribute("xx", "yy")];
// А это описание пустого тега "x" с использованием макроса.
58 def e1 = xml <# <x /> #>;
// Объявление с списка состоящего из двух атрибутов ("w" - описанного по месту без макроса и "x", описанного выше).
59 def elems = [XElement("w"), e1];
// Описание куска XML-я с блэкджеом и шлюхами. Последнее описываю отдельно:
// ns1:a=$z - описание атрибута ns1:a значение которого задается через переменную "z".
// ..$a - генерация сразу нескольких атрибутов на список которых ссылается переменная a. Синтаксис "..$выражение" - означает подставить в данное место значение списка.
// ..$elems - почти тоже самое что и в предыдущем случае, но список содержит элементы и, стало быть, раскрывается в набор элементов.
61 def res1 = xml <# <e a="a" ns1:a=$z ..$a>Text $e1<ns2:a ns2:aa="zz" xmlns:ns2="namespace-2"></ns2:a> abc ..$elems</e> #>;
62 WriteLine(res1); // Преобразование сгенерированного XML-я в текст и его вывод консоль.
63 def name = XName.Get("dyn"); // динамическое формирование имени.
// Генерация еще одного фрагмента ХМЛ-я.
// В данном случае:
// $name - задает (динамически) имя тега.
// $when (z.HasValue) - это встроенный условный оператор. Если условие "z.HasValue" ложно, тег не выводится (т.е. весь тег исчезает).
64 def res2 = xml <# <ns2:Папа xmlns:ns2="namespace-2"><$name $when (z.HasValue) ns1:a="123"/></> #>;
65 WriteLine(res2); // вывод сформированного ХМЛ-я на консоль.
66
67 def ƱƲƳ = 123; // Демонстрация поддержки юникода в немерле. К делу не относится.
68 WriteLine(ƱƲƳ);
D>Я так понимаю, главный пойнт в том, что это именно на макросах, а не встроенная в язык поддержка XML, как в скале.
Именно! Это, кроме всего прочего, позволяет сделать собственные движки с собственным блэкджеком и шлюхами.
D>Вопрос, кстати: а эта штука умеет оборачивать в if/unless группу элементов, чтобы в каждом элементе группы не дублировать условие?
Нет, и сделано это намеренно. if-ы в виде тегов выглядят безобразно, на мой взгляд. Если нужно работать с большим количеством элементов, то нужно просто использоваться ФП и слайсы ($xxx или ..$xxx), внутри которых можно использовать любые конструкции языка (в том числе функции высшего порядка).
Реализовать поддержку "групповых операторов" не сложно, но на мой взгляд — это приведет к замусориванию кода.
D>В догонку про замечание Влада, что будут библиотеки макросов вместо фреймворков — "фреймворк" и "библиотека" ИМХО тут синонимы. Понятно, что фреймворки на языке с поддержкой МП (ФП,ООП,АБЫВАРЛГ) будут использовать МП (ФП,ООП,АБЫВАРЛГ).
Ну, в общем — да, конечно библиотека макросов по мощности аналогичнна фрэймворку. Но все же простота использования и возможность встраивания в основной язык у макросов выше. По этому использование макро-библиотек выглядит как использование библиотек, а не как использование фрэймворков. Я специально акцентировал на этом внимание, так как это дорогого стоит.
Плюс используя макросы мы можем спокойно обходиться без рефлексии и других проявлений динамики. Опять же я не говорю, что динамика вообще ненужна, но как правило она закрывает прорехи в языке или технологии. Мое мнение такое. Динамика вещь очень полезная, но по делу она нужна крайне редко. И надо стараться по возможности обходиться без нее. И только тогда когда динамика дает реальные преимущества не достижимые другими путями (как, например, рантайм-загрузка плагинов), на использовать ее.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, dimgel, Вы писали:
D>Дык задача была простая: удобный модуль форм, без необходимости пользователю фреймворка писать кучу boilerplate-кода. В частности, значения атрибута name для <input/> берутся через рефлексию из имён полей класса. Т.е. в шаблоне формы юзер пишет D>
где значение поля берётся из одноимённого поля переданного в форму DTO (вот эту работу с состоянием я возможно сделаю явной, добавляя геттеры/сеттеры в объявление поля, хотя букв в пользовательском коде сразу станет намного больше).
Что касается решения на динамике, то я бы предпочел иметь лямбды. Ими можно было и астрагироваться от типа свойства, и обеспечить ленивого исполнение.
Но реально красивое решение тут можно было бы сделать если воспользоваться метапрограммированием. Приведу еще одну ссылку на Nemerle on rails. Погляди как там в стадию компиляции переносится не только работа с веб-формами и контроллерами, но и реструктуризация БД.
VD>>Сам факт использования рефлексии зачастую является признаком проблем.
D>Во всех известных мне java-фреймворках рефлексия используется чуть более, чем всегда.
Дык, как тут уже сказали, это проблема Явы.
Я не занимаюсь вебом, но все же за последние время рефлексия мне понадобилась только один раз и то только от лени и потому, что там вообще не важна скорость была.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Это наверно потому что я косой . Я не туда ссылку дал. VD>Так понятнее: AsyncTest.n? (подсветка кода кривая, не обращайте внимание на нее).
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, gandjustas, Вы писали:
WH>>>Они вообще бяка. Даже для десктопа. G>>Для десктопа ОК, иначе придется дофига всего писать. WH>Что писать?
Код для протаскивания состояния между "запросами". Ведь на десктопе все объекты живут в памяти между запросами и ручное таскание выглядит как костыли.
G>>MVVM как в WPF далеко не все проблемы решает. G>>Хотя заложена очень здравая концепция: отделение логики (код) от представления (xaml) и все вместе от состояния (viewmodel). Все это связывается между собой мощным механизмом байндинга. WH>viewmodel должна быть реактивной. WH>А в WPF это достигается через страшные костыли.
Реактивной это как?
G>>Все красиво, но 100% работать не будет. Разметка не должна быть в файлах к кодом. WH>Осталось выяснить чем разметка не код.
Тем что править её могут люди далекие от программирования.
G>>В худшем случае наоборот: вкрапления кода в разметку, причем должна быть возможность править разметку без перекомпиляции. WH>А зачем?
см выше.
WH>Тем более что без перекомпиляции у нас не будет проверки типов.
Эта проблема решена в asp.net
G>>Лучше так: http://msdn.microsoft.com/en-us/magazine/ee819084.aspx G>>С синтаксисом вроде неочень, но ms сейчас такие фичи в jQuery пишет вроде уже можно пощупать: G>>http://weblogs.asp.net/scottgu/archive/2010/05/07/jquery-templates-and-data-linking-and-microsoft-contributing-to-jquery.aspx WH>Что-то там все очень неуклюже.
Да ты че?
jquery покачто самый лаконичный и мощный фреймворк.
G>>Реквестирую killerapp для Nemerle2: ViewEngine для ASP.NET MVC 3 c синтаксисом Razor со всеми плюшками типа автоматической подсветки синтаксиса. WH>Осталось понять нахрена после этого будет нужен сам ASP.NET?
Начинать надо с малого.
Здравствуйте, dimgel, Вы писали:
D>Гы, эта проблема перманентная. Но я пока не вижу, в какую сторону ползти. Что ты написал про атрибуты — это, как я понимаю, те же аннотации в java/scala, получаемые через рефлексию. На немерле примерчик бы, посмотреть как люди живут.
В немерле атрибуты могут быть мета-атрибутами. Выглядят они как обычные атрибуты, но метаданных не порождают. Вместо этого они приводят к вызову некоторого макроса которые во время компиляции может что-то сделать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
D>>На немерле примерчик бы, посмотреть как люди живут. G>На Nemerle пока такого не сделано.
Ну, почему же? Кое-что есть. Я тут уже давал ссылки на Nemerle on rails.
G>http://www.asp.net/mvc
G>там правда много заботать придется чтобы разобраться. Но сейчас это ИМХО самый адекватный веб-фреймворк на статически типизированном языке.
Вот Nemerle on rails — это попытка прикрыть макросами его некрасивости.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
G>Код для протаскивания состояния между "запросами". Ведь на десктопе все объекты живут в памяти между запросами и ручное таскание ыглядит как костыли.
Ничего не понял.
Что и зачем таскать?
WH>>viewmodel должна быть реактивной. WH>>А в WPF это достигается через страшные костыли. G>Реактивной это как?
Примерно вот так: http://knockoutjs.com/documentation/observables.html#mvvm_and_view_models
WH>>Осталось выяснить чем разметка не код. G>Тем что править её могут люди далекие от программирования.
И что? Как это отменяет тот факт что разметка это тоже код?
WH>>Тем более что без перекомпиляции у нас не будет проверки типов. G>Эта проблема решена в asp.net
Она решена компиляцией.
G>Да ты че? G>jquery покачто самый лаконичный и мощный фреймворк.
А как по мне так Knockout лаконичней.
WH>>Осталось понять нахрена после этого будет нужен сам ASP.NET? G>Начинать надо с малого.
Мне всетки интересно зачем ASP.NET?
Рендрер у нас свой.
Маршилинг свой.
Поиск серверных обработчиков свой.
Кешировать кроме автогенеренных жабаскриптов и статики нам нечего.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, dimgel, Вы писали:
D>Собсна главный вызов здесь — это само словосочетание "stateless component" (натуральный оксюморон), отсюда и всякие метания на тему геттеров/сеттеров/thread-local. Не вижу пока, как оно в итоге может быть, но чувствую, что определяющими окажутся ограничения языка.
Дык выкинь из лексикона слово компонент и все встанет на свои места.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>В прочем, в Яве по идее любой класс должен храниться в class-файлах. Так что не ясно как они умудряются делать специализации в таких условиях.
Да способов миллион на самом деле, было бы желание.
В частности, scala компилятор навешивает на класс аннотацию ScalaSignature, которая в value хранит в сжатом виде всё, что нужно. Этот же компилятор читает эту аннотацию.
Здравствуйте, dimgel, Вы писали:
D>Тем не менее, Wicket очень многие очень хвалят, а дыма без огня не бывает.
Уверен, что эти многие дальше явы и С++ не заглядывали. Для веба бейсвительно куда лучше опдходят идеи ФП и MVC.
D>Контроль над HTML-кодом я тоже люблю иметь полный, но надеюсь, что смогу если не решить, то хотя бы обойти эту проблему, если не буду увлекаться навороченными компонентами в составе фреймворка, а вместо этого обеспечу простой для пользователей способ добавлять свои. Ведь "компоненты" по большому счёту — это просто способ декомпозиции кода. Есть у меня надежда, что stateless component выйдет в итоге тупо пассивным хранилищем для двух ортогональных вещей: class Component(widget, eventHandler), из которых виджет — тупо функция Data => HTML. В этом случае, для пользователя не будет составлять никаких проблем наклепать нужных ему виджетов, генерирующих в точности нужный ему HTML.
Мне кажется, что сама идея эмуляции GUI-ёвостей которая здесь просматривается — это не лучшая идея. Она противоречит веб-у. Веб страницы намного разумнее рассматривать как набор трансформаций, а не как какие-то там живущие дольше страницы компоненты.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, gandjustas, Вы писали:
G>>Код для протаскивания состояния между "запросами". Ведь на десктопе все объекты живут в памяти между запросами и ручное таскание ыглядит как костыли. WH>Ничего не понял. WH>Что и зачем таскать?
Ну попробуй написать десктопный UI с изоляцией "запросов" друг от друга.
WH>>>viewmodel должна быть реактивной. WH>>>А в WPF это достигается через страшные костыли. G>>Реактивной это как? WH>Примерно вот так: http://knockoutjs.com/documentation/observables.html#mvvm_and_view_models
То есть ты фактически предлагаешь все сделать через DependencyProperty (в терминах .NET), тогда чем тебя WPF не устраивает?
WH>>>Осталось выяснить чем разметка не код. G>>Тем что править её могут люди далекие от программирования. WH>И что? Как это отменяет тот факт что разметка это тоже код?
Только разметку обычно правят не те люди, которые пишут логику.
WH>>>Тем более что без перекомпиляции у нас не будет проверки типов. G>>Эта проблема решена в asp.net WH>Она решена компиляцией.
только никто мне не мешает поправить view на работающем сайте и при необходимости перекомпилировать его.
G>>Да ты че? G>>jquery покачто самый лаконичный и мощный фреймворк. WH>А как по мне так Knockout лаконичней.
В каком месте?
Ты считаешь задавание dependencyObservable лаконичнне выражения в двух фигурных скобках?
WH>>>Осталось понять нахрена после этого будет нужен сам ASP.NET? G>>Начинать надо с малого. WH>Мне всетки интересно зачем ASP.NET? WH>Рендрер у нас свой. WH>Маршилинг свой. WH>Поиск серверных обработчиков свой. WH>Кешировать кроме автогенеренных жабаскриптов и статики нам нечего.
В этом всем и проблема. Вы резко ограничили learnability вашего решения тем что у вас все свое.
Я уверен что asp.net mvc знают больше народу, чем nemerle, поэтому предпочел бы:
1)Написать контроллеры в asp.net mvc на Nemerle
2)Использовать view с синтаксисом razor на Nemrle
3)Для MetadataProvider и Binder использовать макросы (чтобы рефлексии не было)
4)DI и AOP тоже сделать на макросах
5)Генерить клиентские скрипты из кода на nemerle
Но я абсолютно не хочу изучать новый фреймворк с другой идеологией на nemerle. Аналогично я и F# WebTools не использовал слишком сильно он отличается от того что есть.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
G>>N2 еще не готов, а на N1 действительно многовато писанины по признанию разработчиков.
VD>Это где же такие признания?
Здравствуйте, gandjustas, Вы писали:
G>Реквестирую killerapp для Nemerle2: ViewEngine для ASP.NET MVC 3 c синтаксисом Razor со всеми плюшками типа автоматической подсветки синтаксиса.
Дерьмовый синтаксис у этого Razor. Родной ремерловый намного лучше.
То что в Razor хоршо — это возможность рекурсивного дизайна. Но это мы и без него умеем.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
G>В этом всем и проблема. Вы резко ограничили learnability вашего решения тем что у вас все свое.
G>Я уверен что asp.net mvc знают больше народу, чем nemerle, поэтому предпочел бы: G>1)Написать контроллеры в asp.net mvc на Nemerle G>2)Использовать view с синтаксисом razor на Nemrle G>3)Для MetadataProvider и Binder использовать макросы (чтобы рефлексии не было) G>4)DI и AOP тоже сделать на макросах G>5)Генерить клиентские скрипты из кода на nemerle
G>Но я абсолютно не хочу изучать новый фреймворк с другой идеологией на nemerle. Аналогично я и F# WebTools не использовал слишком сильно он отличается от того что есть.
Боюсь показаться навязчивым, но все же стоит поглядеть Nemerle on rails. Там многое уже сделано и намного лучше чем предлагается в этом списке. Используется даже внешний движок рендеренга (причем съемный). Вот только последнее я бы назвал минусом, так как решение на макрах будут сильно гибче.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>В частности, scala компилятор навешивает на класс аннотацию ScalaSignature, которая в value хранит в сжатом виде всё, что нужно. Этот же компилятор читает эту аннотацию.
Выход конечно. Но решение будет работать только в рамках одного языка.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Jack128, Вы писали:
G>>>N2 еще не готов, а на N1 действительно многовато писанины по признанию разработчиков.
VD>>Это где же такие признания?
J>http://rsdn.ru/forum/philosophy/4010931.1.aspx
Вольфхаунд как всегда мечтает о золотом будущем в котором все будет идеально.
Но это не мешает существовать светлому настоящему в котором, все не идеально, но очень даже не плохо.
Я уже тут 20 раз давал ссылки на Nemerle on rails и на Nemerle.Xml который можно использовать в качестве основы для создания собственного движка ренедерга HTML/XML. Базовые вещи там уже реализованы. Добавить своих фич по вкусе не составит труда. И на реализацию этого дела ушло где-то полторы недели.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
G>>Реквестирую killerapp для Nemerle2: ViewEngine для ASP.NET MVC 3 c синтаксисом Razor со всеми плюшками типа автоматической подсветки синтаксиса.
VD>Дерьмовый синтаксис у этого Razor. Родной ремерловый намного лучше. VD>То что в Razor хоршо — это возможность рекурсивного дизайна. Но это мы и без него умеем.
Твое мнение мягко говоря неадекватно. Когда razor зарелизят то пользователей у него будет гораздо больше (там и asp.net mvc и webmatrix), чем у nemerle.
А с подходом "у нас все круче, но свое", нафиг никому ваш nemerle нужен не будет.
Здравствуйте, gandjustas, Вы писали:
G>Твое мнение мягко говоря неадекватно.
Во как? Прелэсно (с)
G>Когда razor зарелизят то пользователей у него будет гораздо больше (там и asp.net mvc и webmatrix), чем у nemerle.
Я и не сомневаюсь. В ASP.NET Forms и сейчас пользователей выше крыши. Это конечно все доказывает. Ведь миллионы мух не могут ошибаться.
G>А с подходом "у нас все круче, но свое", нафиг никому ваш nemerle нужен не будет.
Не, ну, те исповедуют подход "Лучше хуже, но от MC" все равно Немерл не выберут. Так что тут и обсуждать нечего.
Вот только того факта, что razor — это тот же AST с чуть улучшенным синтаксисом — это не меняет. Улучшенный синтаксис у нас уже есть здесь и сейчас. Зачем ждать у моря погоды?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
G>>Когда razor зарелизят то пользователей у него будет гораздо больше (там и asp.net mvc и webmatrix), чем у nemerle.
VD>Я и не сомневаюсь. В ASP.NET Forms и сейчас пользователей выше крыши. Это конечно все доказывает. Ведь миллионы мух не могут ошибаться.
Где только можно он вытесняется MVC.
G>>А с подходом "у нас все круче, но свое", нафиг никому ваш nemerle нужен не будет.
VD>Не, ну, те исповедуют подход "Лучше хуже, но от MC" все равно Немерл не выберут. Так что тут и обсуждать нечего.
VD>Вот только того факта, что razor — это тот же AST с чуть улучшенным синтаксисом — это не меняет. Улучшенный синтаксис у нас уже есть здесь и сейчас. Зачем ждать у моря погоды?
Программисты на Nemerle из воздуха не появятся, это 99,9% будут программисты на C#, которые захотят получить преимущества nemerle. 90% из них не захотят изучать новые фреймворки.
(встряну, с вашего позволения) Прикольно, но вот здесь:
A view: a visible, interactive UI representing the state of the view model. It displays information from the view model, sends commands to the view model
Здравствуйте, VladD2, Вы писали:
VD>Мне кажется, что сама идея эмуляции GUI-ёвостей которая здесь просматривается — это не лучшая идея. Она противоречит веб-у. Веб страницы намного разумнее рассматривать как набор трансформаций, а не как какие-то там живущие дольше страницы компоненты.
Если последовать твоему совету и выбросить из лексикона слово "компонента", то можно считать, что widget = тупо reusable html snippet.
Здравствуйте, dimgel, Вы писали:
D>Если последовать твоему совету и выбросить из лексикона слово "компонента", то можно считать, что widget = тупо reusable html snippet.
Во:
package ru.dimgel.lib.web
import scala.xml.NodeSeq
package object component {
/**
* Widget is just a stateless function without side effects which generates HTML markup from model.
*
* NOTE. I cannot enforce "no side effects" restriction via Scala type system, but please honour it
* just to keep your widgets maximally reusable. Particularly, don't depend on data not provided by model.
*
* Example from lib.web source code:
*
* case class WText(name: String) extends Widget[String] {
* def apply(model: String) = <input type="text" name={name} value={model}/>
* }
*
* Note that you don't even have to extend Widget type, just function with compatible signature will be OK:
*
* def WErrorMessage(model: Option[String]) =
* if (!model.isEmpty) <div class="error">{model.get}</div>
* else NodeSeq.Empty
*/
type Widget[Model] = Function1[Model, NodeSeq]
}
Здравствуйте, gandjustas, Вы писали:
G>Программисты на Nemerle из воздуха не появятся, это 99,9% будут программисты на C#, которые захотят получить преимущества nemerle. 90% из них не захотят изучать новые фреймворки.
Без новых фреймворков получатся маленькие улучшизмы из-за которых точно никто не перейдет.
Чтобы люди перешни нужен качественный скачек.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, gandjustas, Вы писали:
G>Ну попробуй написать десктопный UI с изоляцией "запросов" друг от друга.
Опять ничего не понял.
G>То есть ты фактически предлагаешь все сделать через DependencyProperty (в терминах .NET), тогда чем тебя WPF не устраивает?
Оооооооооооооооооооочеееееееееееееень много ручной работы.
G>Только разметку обычно правят не те люди, которые пишут логику.
WH>>И что? Как это отменяет тот факт что разметка это тоже код?
G>только никто мне не мешает поправить view на работающем сайте и при необходимости перекомпилировать его.
Это сделать не проблема. Но это вредная фича.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, gandjustas, Вы писали:
G>>Программисты на Nemerle из воздуха не появятся, это 99,9% будут программисты на C#, которые захотят получить преимущества nemerle. 90% из них не захотят изучать новые фреймворки. WH>Без новых фреймворков получатся маленькие улучшизмы из-за которых точно никто не перейдет. WH>Чтобы люди перешни нужен качественный скачек.
При таком позиционировании Nemerle это неверно. Сейчас на каждом углу Vlad трубит что Nemerle это C#, только лучше.
А потом начинается: вот есть проект на C#, как его сделать на nemerle? Оказывается asp.net низзя, надо другой фреймворк, EF\Linq2SQL тоже, Linq работает но через *опу... Какая реакция последует? "да ну вас на**й с вашим Nemerle".
Если хотите качественный скачок, так надо позиционировать по другому. Вон F# напирает на то что там код получается в разы короче и async у него офигенно мощный. Такого при желании на C# не повторишь, да и на nemerle с трудом. А то что в F# с выводом типов проблемы бывают — вообще мало кого волнует. Напишут аннотации где надо и все.
Здравствуйте, WolfHound, Вы писали:
G>>То есть ты фактически предлагаешь все сделать через DependencyProperty (в терминах .NET), тогда чем тебя WPF не устраивает? WH>Оооооооооооооооооооочеееееееееееееень много ручной работы.
И это говорит человек, который пишет макросы на Nemerle по 100 штук в день?
G>>Только разметку обычно правят не те люди, которые пишут логику. WH>
WH>>>И что? Как это отменяет тот факт что разметка это тоже код?
Тут не философский вопрос, а практический. Верстальщик со знанием html\css\js и может php хрен разберется в том что там написано в этом UR. Ему подавай чтонить похожее на этот самый php.
G>>только никто мне не мешает поправить view на работающем сайте и при необходимости перекомпилировать его. WH>Это сделать не проблема.
Так сделай.
WH>Но это вредная фича.
Чем это она вредная? Так много кто работает, а кто не хочет работает без динамической компиляции.
Здравствуйте, gandjustas, Вы писали:
G>И это говорит человек, который пишет макросы на Nemerle по 100 штук в день?
Макросы конечно помогут но чтобы все было хорошо нужна полноценная поддержка реактивного програмирования.
G>Тут не философский вопрос, а практический. Верстальщик со знанием html\css\js и может php хрен разберется в том что там написано в этом UR. Ему подавай чтонить похожее на этот самый php.
Вот скажи чего не понятно вот в таком коде:
View
<table>
<tr $foreach (item in items)>
<td><edit value = item.Name/></td>
<td><edit value = item.Value/></td>
<td><edit value = item.Count/></td>
<td>$item.Total</td>
<td><button text = "Delete" click = items.Remove(item) /></td>
</tr>
</table>
<span>Total: $items.Sum(_.Total)</span>
<button text = "New item." click = items.Add(Item()) />
edit типизированный. Те там где нужен int можно ввести только int.
ViewModel
record Item
{
Name : string!;
Value : int!;
Count : int!;
Total = Value * Count;
}
def items : array![Item];
! признак реактивности.
Теперь если что-то поменяется все что зависит от этого чегото будет пересчитано.
Более компактный и понятный способ делать GUI я не представляю.
G>Чем это она вредная? Так много кто работает, а кто не хочет работает без динамической компиляции.
А чего полезного в том чтобы руками ковыряться в продакшене?
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, gandjustas, Вы писали:
G>При таком позиционировании Nemerle это неверно. Сейчас на каждом углу Vlad трубит что Nemerle это C#, только лучше.
Влад не это кричит.
G>А потом начинается: вот есть проект на C#, как его сделать на nemerle?
А зачем переделывать уже работающий проект?
G>Оказывается asp.net низзя,
Можно но это будет ASP.NET но только чуть лчше.
G>надо другой фреймворк,
Если хочешь получить значительный выигрыш то да.
G>EF\Linq2SQL тоже,
Можно.
G>Linq работает но через *опу...
Linq работает нормально.
Во втором будет лучше чем в C#.
G>Если хотите качественный скачок, так надо позиционировать по другому. Вон F# напирает на то что там код получается в разы короче и async у него офигенно мощный. Такого при желании на C# не повторишь, да и на nemerle с трудом.
На немерле это давно есть.
G>А то что в F# с выводом типов проблемы бывают — вообще мало кого волнует. Напишут аннотации где надо и все.
В F# много с чем проблемы.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, gandjustas, Вы писали:
G>Если хотите качественный скачок, так надо позиционировать по другому. Вон F# напирает на то что там код получается в разы короче и async у него офигенно мощный. Такого при желании на C# не повторишь, да и на nemerle с трудом. А то что в F# с выводом типов проблемы бывают — вообще мало кого волнует. Напишут аннотации где надо и все.
Вообще это уже не первая тема от тебя в стиле "Пастернака не читал, но осуждаю". За развитием Немерле ты следишь, интереса не проявляешь, при этом пытаешься "тыкать пальцем в небо", гадая, что там можно сделать, а что нельзя. В этот раз вообще не попал ни разу. Тебе самому не надоело?
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, gandjustas, Вы писали:
G>>И это говорит человек, который пишет макросы на Nemerle по 100 штук в день? WH>Макросы конечно помогут но чтобы все было хорошо нужна полноценная поддержка реактивного програмирования.
G>>Тут не философский вопрос, а практический. Верстальщик со знанием html\css\js и может php хрен разберется в том что там написано в этом UR. Ему подавай чтонить похожее на этот самый php. WH>Вот скажи чего не понятно вот в таком коде: WH>View WH>
WH><table>
WH> <tr $foreach (item in items)>
WH> <td><edit value = item.Name/></td>
WH> <td><edit value = item.Value/></td>
WH> <td><edit value = item.Count/></td>
WH> <td>$item.Total</td>
WH> <td><button text = "Delete" click = items.Remove(item) /></td>
WH> </tr>
WH></table>
WH><span>Total: $items.Sum(_.Total)</span>
WH><button text = "New item." click = items.Add(Item()) />
WH>
WH>edit типизированный. Те там где нужен int можно ввести только int.
WH>ViewModel WH>
WH>record Item
WH>{
WH> Name : string!;
WH> Value : int!;
WH> Count : int!;
WH> Total = Value * Count;
WH>}
WH>def items : array![Item];
WH>
WH>! признак реактивности.
А это ты зачем привел?
Ты же дал ссылку на Ur, а там все в куче, код и разметка.
Я тебе говорил что как раз разделение надо.
G>>Чем это она вредная? Так много кто работает, а кто не хочет работает без динамической компиляции. WH>А чего полезного в том чтобы руками ковыряться в продакшене?
Полезного — не знаю, а необходимость возникает часто.
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, gandjustas, Вы писали:
G>>При таком позиционировании Nemerle это неверно. Сейчас на каждом углу Vlad трубит что Nemerle это C#, только лучше. WH>Влад не это кричит.
G>>А потом начинается: вот есть проект на C#, как его сделать на nemerle? WH>А зачем переделывать уже работающий проект?
Потому что с нуля вообще никто не будет начинать новый проект на Nemerle, тем более с новыми фреймворками. Слишком большие риски.
G>>Оказывается asp.net низзя, WH>Можно но это будет ASP.NET но только чуть лчше.
Только не asp.net
G>>надо другой фреймворк, WH>Если хочешь получить значительный выигрыш то да.
А мне не нужен "значительный", мне нужно повторить то что есть, может гденить улучшить.
G>>EF\Linq2SQL тоже, WH>Можно.
А недавняя бага интеграции с EF?
G>>Linq работает но через *опу... WH>Linq работает нормально. WH>Во втором будет лучше чем в C#.
В чем например?
G>>Если хотите качественный скачок, так надо позиционировать по другому. Вон F# напирает на то что там код получается в разы короче и async у него офигенно мощный. Такого при желании на C# не повторишь, да и на nemerle с трудом. WH>На немерле это давно есть.
Покажешь? И "давно" это когда?
G>>А то что в F# с выводом типов проблемы бывают — вообще мало кого волнует. Напишут аннотации где надо и все. WH>В F# много с чем проблемы.
Тем не менее он более популярен чем nemerle.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, gandjustas, Вы писали:
G>>Если хотите качественный скачок, так надо позиционировать по другому. Вон F# напирает на то что там код получается в разы короче и async у него офигенно мощный. Такого при желании на C# не повторишь, да и на nemerle с трудом. А то что в F# с выводом типов проблемы бывают — вообще мало кого волнует. Напишут аннотации где надо и все.
ВВ>Вообще это уже не первая тема от тебя в стиле "Пастернака не читал, но осуждаю". За развитием Немерле ты следишь, интереса не проявляешь, при этом пытаешься "тыкать пальцем в небо", гадая, что там можно сделать, а что нельзя. В этот раз вообще не попал ни разу. Тебе самому не надоело?
Для справки: многое пытался сам делать, но очень сильно напрягают моменты когда работает почти как в C#, но не C#.
Здравствуйте, gandjustas, Вы писали:
G>Ты же дал ссылку на Ur, а там все в куче, код и разметка. G>Я тебе говорил что как раз разделение надо.
Ты не читаешь то что я пишу
http://www.impredicative.com/ur/
Статически типизирован. Рантайм рефлексия отсутствует за не надобностью. Правда автор далек от практики и в примерах намешал ViewModel и View в одну кучу. С теоретиками такое часто случается.
Но ничто не мешает писать правильно. Синтаксис местами нужно допилить напильником.
G>Полезного — не знаю, а необходимость возникает часто.
Вот так сразу на продакшене?
Совсем без тестирования?
И что будешь делать если машин больше чем одна?
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, gandjustas, Вы писали:
G>Потому что с нуля вообще никто не будет начинать новый проект на Nemerle, тем более с новыми фреймворками. Слишком большие риски.
При условии что кода будет в разы меньше...
WH>>Если хочешь получить значительный выигрыш то да. G>А мне не нужен "значительный", мне нужно повторить то что есть, может гденить улучшить.
Зачем тебе повторять работающий проект?
G>А недавняя бага интеграции с EF?
Какая бага?
G>В чем например?
Например тем что у C# в синтаксисе linq не хватает функций.
WH>>На немерле это давно есть. G>Покажешь? http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/ComputationExpressions/
G>И "давно" это когда?
Когда комуто оно понадобилось.
WH>>В F# много с чем проблемы. G>Тем не менее он более популярен чем nemerle.
Исключительно из-за того что его продвигает МС.
Если бы не МС то ты бы сам о нем отзывался как о говнопорте окамла на .НЕТ.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
G>>Полезного — не знаю, а необходимость возникает часто. WH>Вот так сразу на продакшене?
Вполне
WH>Совсем без тестирования?
У нас же компилируются страницы
WH>И что будешь делать если машин больше чем одна?
Web Farm Framework
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, gandjustas, Вы писали:
G>>Потому что с нуля вообще никто не будет начинать новый проект на Nemerle, тем более с новыми фреймворками. Слишком большие риски. WH>При условии что кода будет в разы меньше...
А как ты дашь такую оценку если это первый большой проект?
WH>>>Если хочешь получить значительный выигрыш то да. G>>А мне не нужен "значительный", мне нужно повторить то что есть, может гденить улучшить. WH>Зачем тебе повторять работающий проект?
Как раз для изучения.
G>>А недавняя бага интеграции с EF? WH>Какая бага?
G>>В чем например? WH>Например тем что у C# в синтаксисе linq не хватает функций.
WH>>>На немерле это давно есть. G>>Покажешь? WH>http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/ComputationExpressions/
Это я видел. А знаменитый уже пример "time flies like an arrow" на этом всем?
WH>>>В F# много с чем проблемы. G>>Тем не менее он более популярен чем nemerle. WH>Исключительно из-за того что его продвигает МС. WH>Если бы не МС то ты бы сам о нем отзывался как о говнопорте окамла на .НЕТ.
Я на маркетинговый\псевдонаучный\архитектурный булшит не ведусь.
Мне пофиг чего на что там портировали в F#, я своей *опой ощутил уменьшение кода.
А в Nemerle — не ощутил. Вывод типов там слабоват, синтаксис частичного применения не очень и куча других мелочей. А чтобы получить это самое уменьшение надо изучить новый фреймворк (макросы), а у меня на это времени не было и в ближайшем будущем не будет.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, WolfHound, Вы писали:
WH>>Здравствуйте, gandjustas, Вы писали:
WH>>>>Они вообще бяка. Даже для десктопа. G>>>Для десктопа ОК, иначе придется дофига всего писать. WH>>Что писать? G>Код для протаскивания состояния между "запросами". Ведь на десктопе все объекты живут в памяти между запросами и ручное таскание выглядит как костыли.
G>>>MVVM как в WPF далеко не все проблемы решает. G>>>Хотя заложена очень здравая концепция: отделение логики (код) от представления (xaml) и все вместе от состояния (viewmodel). Все это связывается между собой мощным механизмом байндинга. WH>>viewmodel должна быть реактивной. WH>>А в WPF это достигается через страшные костыли. G>Реактивной это как?
Здравствуйте, z00n, Вы писали:
Z>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, WolfHound, Вы писали:
WH>>>Здравствуйте, gandjustas, Вы писали:
WH>>>>>Они вообще бяка. Даже для десктопа. G>>>>Для десктопа ОК, иначе придется дофига всего писать. WH>>>Что писать? G>>Код для протаскивания состояния между "запросами". Ведь на десктопе все объекты живут в памяти между запросами и ручное таскание выглядит как костыли.
G>>>>MVVM как в WPF далеко не все проблемы решает. G>>>>Хотя заложена очень здравая концепция: отделение логики (код) от представления (xaml) и все вместе от состояния (viewmodel). Все это связывается между собой мощным механизмом байндинга. WH>>>viewmodel должна быть реактивной. WH>>>А в WPF это достигается через страшные костыли. G>>Реактивной это как?
Z>Reactive Extensions for .NET (Rx). Z>"Property Реактивизатор".
Здравствуйте, gandjustas, Вы писали:
G>Где только можно он вытесняется MVC.
Это не факт. Да и без разницы. Ведь те кто использовали АСП.НЕТ появились не из воздуха и они не уйдут в никуда. Они же могли оценить неверность подхода и выбрать один из доступных фрэймворков сделанных третьими лицами? Но им важнее шилдик "Сдалано в Майкрософт". А раз так, то плевать они хотели на какие-то там преимущества.
Это серые массы которые созданы для того, чтобы те кто хотя бы на йоту умнее могли выделиться из этой серой массы.
G>Программисты на Nemerle из воздуха не появятся, это 99,9% будут программисты на C#, которые захотят получить преимущества nemerle. 90% из них не захотят изучать новые фреймворки.
Дык нет никаких таких фрэймворков. Все что будет — это библиотеки которые в сто раз проще изучать.
А тот же Nemerle on rails как раз включает в себя кучу фрэймворков так привычных интеллектуальному большинству. Так что предмета с которым ты решил побороться попросту нет в природе .
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, z00n, Вы писали:
Z>>Здравствуйте, gandjustas, Вы писали:
G>>>Здравствуйте, WolfHound, Вы писали:
WH>>>>Здравствуйте, gandjustas, Вы писали:
WH>>>>>>Они вообще бяка. Даже для десктопа. G>>>>>Для десктопа ОК, иначе придется дофига всего писать. WH>>>>Что писать? G>>>Код для протаскивания состояния между "запросами". Ведь на десктопе все объекты живут в памяти между запросами и ручное таскание выглядит как костыли.
G>>>>>MVVM как в WPF далеко не все проблемы решает. G>>>>>Хотя заложена очень здравая концепция: отделение логики (код) от представления (xaml) и все вместе от состояния (viewmodel). Все это связывается между собой мощным механизмом байндинга. WH>>>>viewmodel должна быть реактивной. WH>>>>А в WPF это достигается через страшные костыли. G>>>Реактивной это как?
Z>>Reactive Extensions for .NET (Rx). Z>>"Property Реактивизатор".
G>Круто, пример кода покажешь?
Здравствуйте, gandjustas, Вы писали:
G>При таком позиционировании Nemerle это неверно. Сейчас на каждом углу Vlad трубит что Nemerle это C#, только лучше.
Это не совсем так. Nemerle — это совсем другой язык. Он не просто лучше, а намного лучше. Но он успешно мимикрирует под C# позволяя первое время писать в стиле C#++. Нужно это, главным образом, для плавности вхождения, которая обеспечивает простоту перехода. Но если на этом остановиться, то преимущества и правда будут не очень существенными.
Nemerle — это в первую очередь высококачественное ФП, МП и хорошая совместимость с C# на уровне библиотек и фрэймворков.
G>А потом начинается: вот есть проект на C#, как его сделать на nemerle?
Это просто бессмысленно. Если проект есть, то никакими средствами этот факт не отмерить.
Проект можно развивать на Nemerle, или можно начать новый проект (или подпроект) на Nemerle. Но переписывать — это какой-то мазохизм. Я бы и сам не стал это делать.
G>Оказывается asp.net низзя, надо другой фреймворк, EF\Linq2SQL тоже, Linq работает но через *опу... Какая реакция последует? "да ну вас на**й с вашим Nemerle".
На счет линка не понял. Что с ним не так? А что до веб-проектов, то они к счастью состоят из отдельных страниц. И нет никаких проблем начать делать отдельные из них на новом инструменте. А там, потихонечку, можно будет перейти полностью.
G>Если хотите качественный скачок, так надо позиционировать по другому. Вон F# напирает на то что там код получается в разы короче и async у него офигенно мощный.
Да пусть напирает. Все равно это ему не помогает. Ему даже поддержка МС не помогает. Он как был чужим в дотнете, так и останется.
G>Такого при желании на C# не повторишь, да и на nemerle с трудом.
Слушая тебя я прямо таки узнаю много нового. Ты, кстати, в своем сообщении отвечал челвеку (Вольфхаунду) который повторил их Async на макросах немерла. Получилось чуть более гибче, кстати.
G>А то что в F# с выводом типов проблемы бывают — вообще мало кого волнует. Напишут аннотации где надо и все.
Дык проблема в том, что F# сам по себе мало кого волнует. Его и в МС то считают языком для гиков.
Вообще уговаривать кого-то дело не благодарное.
Мы просто делаем то что считаем нужным. Это доставляет нам удовольствие и позволяет использовать в работе тот инструмент который нам больше нравится, а не тот которые нам предлагают большие дяди. Если кто-то хочет к нам присоединиться (с любыми целями) мы будем только рады. Но затягивать силком или обманом желания нет ни малейшего. Посему популизм в виде выбора более привычных, но менее мощных решений — это не наш путь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
G>Потому что с нуля вообще никто не будет начинать новый проект на Nemerle, тем более с новыми фреймворками. Слишком большие риски.
Да ладно тебе. Начинают же.
WH>>Можно но это будет ASP.NET но только чуть лчше. G>Только не asp.net
Дык ASP.NET же это не самоцель? Или самоцель?
G>>>надо другой фреймворк, WH>>Если хочешь получить значительный выигрыш то да. G>А мне не нужен "значительный", мне нужно повторить то что есть, может гденить улучшить.
А зачем повторять то?
G>>>EF\Linq2SQL тоже, WH>>Можно. G>А недавняя бага интеграции с EF?
Ссылку в студию.
G>>>А то что в F# с выводом типов проблемы бывают — вообще мало кого волнует. Напишут аннотации где надо и все. WH>>В F# много с чем проблемы. G>Тем не менее он более популярен чем nemerle.
Да ладно тебе. Ты сам то в это веришь?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
G>>Если хотите качественный скачок, так надо позиционировать по другому. Вон F# напирает на то что там код получается в разы короче и async у него офигенно мощный. Такого при желании на C# не повторишь, да и на nemerle с трудом. А то что в F# с выводом типов проблемы бывают — вообще мало кого волнует. Напишут аннотации где надо и все.
ВВ>Вообще это уже не первая тема от тебя в стиле "Пастернака не читал, но осуждаю". За развитием Немерле ты следишь, интереса не проявляешь, при этом пытаешься "тыкать пальцем в небо", гадая, что там можно сделать, а что нельзя. В этот раз вообще не попал ни разу. Тебе самому не надоело?
Самое смешное, что gandjustas ведь ни разу не противник немерла. Но домыслы и от него исходят.
Вот это и обидно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
G>Для справки: многое пытался сам делать, но очень сильно напрягают моменты когда работает почти как в C#, но не C#.
Так ты попробуй сделать что-то действительно сложное. Причем если какие-то вопросы, то не стесняйся спрашивай на форуме или через скайп. Уверяю тебя, что через месяц ты любого порвешь в клочья кто будет бросаться утверждениями вроде тех кто ты сейчас сам изрекаешь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, dimgel, Вы писали:
VD>>Мне кажется, что сама идея эмуляции GUI-ёвостей которая здесь просматривается — это не лучшая идея. Она противоречит веб-у. Веб страницы намного разумнее рассматривать как набор трансформаций, а не как какие-то там живущие дольше страницы компоненты.
D>Если последовать твоему совету и выбросить из лексикона слово "компонента", то можно считать, что widget = тупо reusable html snippet.
Дык это и не плохо. Я бы еще выбросил "widget" и оставил "reusable html snippet". Вот последнее, если они конечно удобно "реюзаются" — это очень хорошо и многое дает.
На мой взгляд хороший веб-фрэймворк/библиотека должны облегчать решение основной задачи создателя сайта — генерировать страницы, управлять навигацией между страницами и обрабатывать ввод пользователя. А вот как это достигается совершенно не важно. Из описания задачи ясно, что тут рулит ФП, а не ООП. В прочем, ООП может пригодиться для реализации логики навигации. А вот генерация хтмл-я и обработка ввода пользователя — это задачи сугубо функциональные. И тянуть сюда компоненты и объекты — это ошибка.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
WH>>При условии что кода будет в разы меньше... G>А как ты дашь такую оценку если это первый большой проект?
Так это бедут видно даже на игрушечных примерах.
Вот прикинь во что выльется это
без реактивности и биндинга?
WH>>Зачем тебе повторять работающий проект? G>Как раз для изучения.
Для изучения чего?
Подмножества немерла которое чуть лучше чем C#?
Это не имеет смысла.
Человек должен увидиеть что то что раньше делалось тонной мутного кода стало делаться арой строчек простого и понятного кода.
WH>>http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/ComputationExpressions/ G>Это я видел. А знаменитый уже пример "time flies like an arrow" на этом всем?
Этот код использует другую фичу.
Реализовать ее не проблема.
Добровольцем будешь?
G>Мне пофиг чего на что там портировали в F#, я своей *опой ощутил уменьшение кода.
Сколько кода ты написал на F# и немерле?
G>А в Nemerle — не ощутил.
Странно. Может по тому что ты пытался писать на нем как на C#?
G>Вывод типов там слабоват,
Очень интересное заявление. Но что-то мне подсказывает что вывод типов там самый мощьный из языков которые поддерживают перегрузку и неявные приведения типов.
G>синтаксис частичного применения
А что с ним не так? Особенно учитывая что нужен он довольно редко.
G>не очень и куча других мелочей.
Например?
G>А чтобы получить это самое уменьшение надо изучить новый фреймворк (макросы), а у меня на это времени не было и в ближайшем будущем не будет.
Ну да. Тоже весьма распространенная отмазка: Мне копать надо, а не с экскаватором разбираться.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
2 gandjustas: Кстати, не спеши отказываться. Как показывает практика скептицизм можно устранить только практикой. Саму поддержку ComputationExpressions реализовал скептик похожий на тебя.
У тебя уйдет 1-2 вечера на эту фичу (если что WolfHound подскажет).
А потом сам поделишься впечатлениями.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, WolfHound, Вы писали:
WH>>>Осталось понять нахрена после этого будет нужен сам ASP.NET? G>>Начинать надо с малого. WH>Мне всетки интересно зачем ASP.NET? WH>Рендрер у нас свой. WH>Маршилинг свой. WH>Поиск серверных обработчиков свой. WH>Кешировать кроме автогенеренных жабаскриптов и статики нам нечего.
У ASP.NET довольно объемная инфраструктура внизу. Например воркер-процесс в пуле, управление этими процессами, взаимодействие с IIS. Реализовать все это качественно довольно сложно, да и не нужно никому.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>У ASP.NET довольно объемная инфраструктура внизу. Например воркер-процесс в пуле, управление этими процессами, взаимодействие с IIS. Реализовать все это качественно довольно сложно, да и не нужно никому.
А разве это не через хттп-хэндлеры делается?
Мне кажется тут каждый под ASP.NET понимает свое. Кто-то движок рендеринга, а кто-то всю инфраструктуру работы с IIS-ом.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А разве это не через хттп-хэндлеры делается?
хттп хендлеры это часть ASP.NET.
VD>Мне кажется тут каждый под ASP.NET понимает свое. Кто-то движок рендеринга, а кто-то всю инфраструктуру работы с IIS-ом.
Большинство все таки использует второй вариант. Стандартный движок рендеринга обычно обзывают ASP.NET WebForms.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>хттп хендлеры это часть ASP.NET.
Ну, вот на таком уровне поддержки ASP.NET можно и остановиться. Вот только для большинства — это не будет поддержкой ASP.NET, так как оно вкладывает в ASP.NET совсем другой смысл.
VD>>Мне кажется тут каждый под ASP.NET понимает свое. Кто-то движок рендеринга, а кто-то всю инфраструктуру работы с IIS-ом.
AVK>Большинство все таки использует второй вариант. Стандартный движок рендеринга обычно обзывают ASP.NET WebForms.
Я что-то по жизни наблюдаю обратное. Как раз под ASP.NET подразумевают весь набор решений включая дизайнеры из VS.
Думаю, что WolfHound не будет возражать против использования хттп-хэндлеров и собственной реализации чего-то вроде IHttpAsyncHandler. Он как раз имел в виду то что ты понимаешь под ASP.NET WebForms и ASP.NET MVC.
По сути можно конечно использовать и ASP.NET MVC, но получается, что из всего многообразия кода впихнутого в это понятие будет использоваться очень не много.
ЗЫ
Кстити, интересно, а в Моно реализованы хттп-хэндлеры?
Почти уверен, что будет. А стало быть решение сразу будет кросплатформным. И не придется надеяться на силы Моновцев. Так что один плюс у самопала точно есть.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
VD>>И тянуть сюда компоненты и объекты — это ошибка.
AVK>Однако ж инерция мышления. Знаешь, сколько народ визжал как раз по поводу отсутствия компонентов в ASP.NET MVC?
Могу себе представить. Привычка собирать приложения из компонентов. Конечно же приятно не написав ни одной строчки кода набросать на форму компонетов и получить прототип нужной страницы.
Однако многие продвинутые товарищи по собственной воли уходят в MVC и другие реактивные подходы по собственной воле.
Да что там далеко ходить? Вот gandjustas сам за него ратует.
По сути у них с WolfHound-ом разногласий почти нет. Просто WolfHound несколько больше понимает в том какие возможности есть в немерла, плюс он является максималистом. Вот и не понимают они друг-друга. Но это не системное не понимание.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ну, вот на таком уровне поддержки ASP.NET можно и остановиться.
Можно. МС сам, собственно, такое делает. Например тот же MVC + Razor в перспективе.
VD> Вот только для большинства — это не будет поддержкой ASP.NET, так как оно вкладывает в ASP.NET совсем другой смысл.
Ты, имхо, насчет большинства ошибаешься.
VD>По сути можно конечно использовать и ASP.NET MVC
Я бы сказал нужно. Хотя бы ради совместимости и уменьшения объема поддерживаемого кода. А рендерер можно и свой прикрутить.
VD>Кстити, интересно, а в Моно реализованы хттп-хэндлеры?
Очень давно, с ранних версий. MVC, кстати, в случае Моно вообще входит в состав платформы.
VD>Почти уверен, что будет. А стало быть решение сразу будет кросплатформным. И не придется надеяться на силы Моновцев. Так что один плюс у самопала точно есть.
Нету такого плюча. У Моно 100% покрытие всего ASP.NET функционала.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, AndrewVK, Вы писали:
VD>> Вот только для большинства — это не будет поддержкой ASP.NET, так как оно вкладывает в ASP.NET совсем другой смысл.
AVK>Ты, имхо, насчет большинства ошибаешься.
Да что мне ошибаться то? Вот тебе два типичных представителя. WolfHound скорее всего вообще о наличии хттп-хэндлеров не был в курсе, а gandjustas под ASP.NET явно понимает MVC + Razor, так как о поддержке Razor-а как раз и говорил, а Razor не что иное как сменный движок рендеренга для MVC.
VD>>По сути можно конечно использовать и ASP.NET MVC
AVK>Я бы сказал нужно. Хотя бы ради совместимости и уменьшения объема поддерживаемого кода. А рендерер можно и свой прикрутить.
Ну, в Nemerle on rails так и сделано. Только вот не ясно что осталось от этого MVC? Реально получилось, что товарищ сэкономил на создании собственного рендерера воспользовавшись сменными рендерерами MVC и был вынужден делать делать хак для того чтобы передавать данные View model в статически-типизированном виде. По сути хак заключается в том, что аналог анонимных типов в немерле реализован в виде макросов и его можно (хотя и не очень прямы и честным образом) протащить между сборкой контроллера и сборками представлений (которые в MVC создаются по одной для каждого представления).
VD>>Почти уверен, что будет. А стало быть решение сразу будет кросплатформным. И не придется надеяться на силы Моновцев. Так что один плюс у самопала точно есть.
AVK>Нету такого плюча. У Моно 100% покрытие всего ASP.NET функционала.
Ты его использовал? Я вот как не столкнусь с Моно, так сразу оказывается, что у них все не доделано, а то что доделано зачастую сделано криво и не полностью соответствует реализации от МС.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ну, в Nemerle on rails так и сделано. Только вот не ясно что осталось от этого MVC?
Весь MVC, собственно, и остался.
VD>Ты его использовал?
Да.
VD> Я вот как не столкнусь с Моно, так сразу оказывается, что у них все не доделано, а то что доделано зачастую сделано криво и не полностью соответствует реализации от МС.
Столкнулся ты, видимо, с винформсами?
... << RSDN@Home 1.2.0 alpha 4 rev. 1476 on Windows 7 6.1.7600.0>>
Здравствуйте, VladD2, Вы писали:
VD>Кстити, интересно, а в Моно реализованы хттп-хэндлеры?
Справедливости ради, как-то сложно представить реализацию ASP.NET без http handlers/modules. Там это, собственно, самый базовый механизм. На нем все и построено.
Здравствуйте, AndrewVK, Вы писали:
VD>>Ну, в Nemerle on rails так и сделано. Только вот не ясно что осталось от этого MVC?
AVK>Весь MVC, собственно, и остался.
Можно на пальцах объяснить, что же там такое нужное?
VD>>Ты его использовал?
AVK>Да.
И проблем не возникло?
VD>> Я вот как не столкнусь с Моно, так сразу оказывается, что у них все не доделано, а то что доделано зачастую сделано криво и не полностью соответствует реализации от МС.
AVK>Столкнулся ты, видимо, с винформсами?
Болше с рефлекшоном. Он там (особенно эмит) написан просто чудовищно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Справедливости ради, как-то сложно представить реализацию ASP.NET без http handlers/modules. Там это, собственно, самый базовый механизм. На нем все и построено.
Что там представлять то? Залепили свой аналог, и аля-улю, гони гусей (с).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
ВВ>>Справедливости ради, как-то сложно представить реализацию ASP.NET без http handlers/modules. Там это, собственно, самый базовый механизм. На нем все и построено. VD>Что там представлять то? Залепили свой аналог, и аля-улю, гони гусей (с).
Здравствуйте, VladD2, Вы писали:
G>>Программисты на Nemerle из воздуха не появятся, это 99,9% будут программисты на C#, которые захотят получить преимущества nemerle. 90% из них не захотят изучать новые фреймворки.
VD>Дык нет никаких таких фрэймворков. Все что будет — это библиотеки которые в сто раз проще изучать.
Вообще говоря без разницы.
Насчет проще изучать тоже спорный вопрос. Много ли учебным материалов по макросам Nemerle?
Я нарыл четыре с половиной статьи, но примеры в них или слишком сложные, или нафиг ненужные.
Единственное показалось достойным — скринкасты по применению макросов в каком-то веб-приложении, ссылку к сожалению уже не найду.
Ну собственно и все, ни книг нету, ни в блога о nemerle не пишут и в реальных (необязательно коммерческих) проектах nemerle не найдешь.
Здравствуйте, z00n, Вы писали:
Z>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, z00n, Вы писали:
Z>>>Здравствуйте, gandjustas, Вы писали:
G>>>>Здравствуйте, WolfHound, Вы писали:
WH>>>>>Здравствуйте, gandjustas, Вы писали:
WH>>>>>>>Они вообще бяка. Даже для десктопа. G>>>>>>Для десктопа ОК, иначе придется дофига всего писать. WH>>>>>Что писать? G>>>>Код для протаскивания состояния между "запросами". Ведь на десктопе все объекты живут в памяти между запросами и ручное таскание выглядит как костыли.
G>>>>>>MVVM как в WPF далеко не все проблемы решает. G>>>>>>Хотя заложена очень здравая концепция: отделение логики (код) от представления (xaml) и все вместе от состояния (viewmodel). Все это связывается между собой мощным механизмом байндинга. WH>>>>>viewmodel должна быть реактивной. WH>>>>>А в WPF это достигается через страшные костыли. G>>>>Реактивной это как?
Z>>>Reactive Extensions for .NET (Rx). Z>>>"Property Реактивизатор".
G>>Круто, пример кода покажешь?
Z>Вот тьюториал: DEVHOL202 – Curing the asynchronous blues with the Reactive Extensions for .NET.
Z>Про Rx и MVVC, например, вот: Z>http://secondstanza.com/2010/07/24/mvvm-mef-reactive-data-grid-part-i/
Что такое Rx я прекрасно знаю, а вот где там "реактивная viewmodel"?
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
G>>При таком позиционировании Nemerle это неверно. Сейчас на каждом углу Vlad трубит что Nemerle это C#, только лучше.
VD>Это не совсем так. Nemerle — это совсем другой язык. Он не просто лучше, а намного лучше. Но он успешно мимикрирует под C# позволяя первое время писать в стиле C#++. Нужно это, главным образом, для плавности вхождения, которая обеспечивает простоту перехода. Но если на этом остановиться, то преимущества и правда будут не очень существенными.
VD>Nemerle — это в первую очередь высококачественное ФП, МП и хорошая совместимость с C# на уровне библиотек и фрэймворков.
Буллшит детектед.
"Высококачественное МП" без сахара для монад, карированых функций, first class operators и first class events не кажется уж таким высококачественным.
МП возможно есть, но это большая библиотека, которую надо изучить, понять принципы её применения, а для этого материалов мало.
G>>А потом начинается: вот есть проект на C#, как его сделать на nemerle?
VD>Это просто бессмысленно. Если проект есть, то никакими средствами этот факт не отмерить. VD>Проект можно развивать на Nemerle, или можно начать новый проект (или подпроект) на Nemerle. Но переписывать — это какой-то мазохизм. Я бы и сам не стал это делать.
Крайне несогласен. У меня есть несколько проектов (веб, десктоп, математика, чат-сервер итп) объемом около 1000 строк, я их переписываю с применением новых технологий чтобы почувствовать на себе. Крупные проекты, которые приносят деньги я даже трогать не собираюсь.
G>>Оказывается asp.net низзя, надо другой фреймворк, EF\Linq2SQL тоже, Linq работает но через *опу... Какая реакция последует? "да ну вас на**й с вашим Nemerle".
VD>На счет линка не понял. Что с ним не так?
Синтаксис. Раньше и другие проблемы были, сейчас сложно сказать.
VD>А что до веб-проектов, то они к счастью состоят из отдельных страниц.
То что состоит из отдельных страниц к счастью программирования не требует вообще.
Я вот последнее время использую webmatrix и razor
VD>И нет никаких проблем начать делать отдельные из них на новом инструменте. А там, потихонечку, можно будет перейти полностью.
Ага, только nemerle не умеет razor. C# и VB умеют, а nemerle — нет.
G>>Если хотите качественный скачок, так надо позиционировать по другому. Вон F# напирает на то что там код получается в разы короче и async у него офигенно мощный.
VD>Да пусть напирает. Все равно это ему не помогает. Ему даже поддержка МС не помогает. Он как был чужим в дотнете, так и останется.
Тем не менее он и сейчас популярнее nemerle и как бы его популярность только растет.
G>>Такого при желании на C# не повторишь, да и на nemerle с трудом.
VD>Слушая тебя я прямо таки узнаю много нового. Ты, кстати, в своем сообщении отвечал челвеку (Вольфхаунду) который повторил их Async на макросах немерла. Получилось чуть более гибче, кстати.
Я в курсе что там получилось.
всякие defcomp и callcomp слегка напрягают,почему нельзя было сделать def! и do! ?
Общий вопрос. Почему при "Высококачественном МП" не было монад изначально в языке?
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
G>>Потому что с нуля вообще никто не будет начинать новый проект на Nemerle, тем более с новыми фреймворками. Слишком большие риски. VD>Да ладно тебе. Начинают же.
Где? Кто?
WH>>>Можно но это будет ASP.NET но только чуть лчше. G>>Только не asp.net VD>Дык ASP.NET же это не самоцель? Или самоцель?
Конечно самоцель, потому что офигенная инфраструктура заложена и огромный toolchain.
G>>>>надо другой фреймворк, WH>>>Если хочешь получить значительный выигрыш то да. G>>А мне не нужен "значительный", мне нужно повторить то что есть, может гденить улучшить.
VD>А зачем повторять то?
Для обучения, чтобы преимущества почувствовать.
G>>>>EF\Linq2SQL тоже, WH>>>Можно. G>>А недавняя бага интеграции с EF?
VD>Ссылку в студию. http://www.rsdn.ru/forum/nemerle/3823376.flat.aspx
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Воронков Василий, Вы писали:
ВВ>>Справедливости ради, как-то сложно представить реализацию ASP.NET без http handlers/modules. Там это, собственно, самый базовый механизм. На нем все и построено.
VD>Что там представлять то? Залепили свой аналог, и аля-улю, гони гусей (с).
Хм... а расширение для IIS, которое будет запускать твои аналоги кто писать будет? Или свой веб сервер? А потом поставить его всем хостерам?
Кстати в мире java примерно так и делают, там этих app-серверов как собак нерезаных, а потом подходящий хостинг не найдешь.
На надо создавать инфраструктуру на nemerle, надо создавать приложения. А вот с приложениями у nemerle хреново. Единственный реальный пример крупного проекта на nemerle — компилятор nemerle.
Здравствуйте, AndrewVK, Вы писали:
VD>>Можно на пальцах объяснить, что же там такое нужное?
AVK>Собственно сам фреймворк, что ж еще.
Это не ответ, а уход от ответа. По от фрэймворка ничего и не остается.
AVK>>>Да. VD>>И проблем не возникло? AVK>Серьезных — нет.
Остается поверить в чудо.
В любом случае чем меньше кода (особенно написанного моновцами), тем лучше.
VD>>Болше с рефлекшоном. Он там (особенно эмит) написан просто чудовищно.
AVK>Эмит уже переписали, насколько я знаю.
Ага. Раз 10. С каждым разом все хуже и хуже. В 2.7 он чуть было не заработал, но в 2.8 они устранили эту не доработку и эмит там просто убит.
Мы вот думаем первым шагом на пути создания Nemerle 2.0 перевести его на CCI Metadata, чтобы навсегда забыть про это чудо природы — Reflection.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
VD>>Болше с рефлекшоном. Он там (особенно эмит) написан просто чудовищно. AVK>Эмит уже переписали, насколько я знаю.
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, gandjustas, Вы писали:
WH>>>При условии что кода будет в разы меньше... G>>А как ты дашь такую оценку если это первый большой проект? WH>Так это бедут видно даже на игрушечных примерах. WH>Вот прикинь во что выльется это
без реактивности и биндинга?
Это потому что ты уже знаешь что такое реактивность и binding.
А вот теперь представь что ты не знаешь что такое метапрограммирование, как будешь оценки давать?
WH>>>Зачем тебе повторять работающий проект? G>>Как раз для изучения. WH>Для изучения чего? WH>Подмножества немерла которое чуть лучше чем C#? WH>Это не имеет смысла. WH>Человек должен увидиеть что то что раньше делалось тонной мутного кода стало делаться арой строчек простого и понятного кода.
И где он это должен увидеть?
WH>>>http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/ComputationExpressions/ G>>Это я видел. А знаменитый уже пример "time flies like an arrow" на этом всем? WH>Этот код использует другую фичу. WH>Реализовать ее не проблема. WH>Добровольцем будешь?
Нет, у меня уже список из десятка технологий\языков\библиотек которые надо изучить.
Мне тупо некогда этим заниматься. Если и создателям языка тупо некогда, то можно считать что такой фичи нет.
G>>Мне пофиг чего на что там портировали в F#, я своей *опой ощутил уменьшение кода. WH>Сколько кода ты написал на F# и немерле?
На F# тыщи 3 строк наверное, на nemerle несколько сотен.
G>>А в Nemerle — не ощутил. WH>Странно. Может по тому что ты пытался писать на нем как на C#?
А где бы почитать как надо писать на nemerle с примерами из реальных проектов?
G>>Вывод типов там слабоват, WH>Очень интересное заявление. Но что-то мне подсказывает что вывод типов там самый мощьный из языков которые поддерживают перегрузку и неявные приведения типов.
Тока не глобальный он, а значит для меня, как пользователя он слабоват.
G>>синтаксис частичного применения WH>А что с ним не так? Особенно учитывая что нужен он довольно редко.
Ну конечно, он нужен редко в тех языках, где его нет
G>>не очень и куча других мелочей. WH>Например?
Надоело перечислять, оно ведь или "редко используется", или "можно сделать на макросах".
G>>А чтобы получить это самое уменьшение надо изучить новый фреймворк (макросы), а у меня на это времени не было и в ближайшем будущем не будет. WH>Ну да. Тоже весьма распространенная отмазка: Мне копать надо, а не с экскаватором разбираться.
Я с другими экскаваторами разбираюсь, на ваш, для которого даже мануала нет, времени не хватает.
Здравствуйте, gandjustas, Вы писали:
VD>>Nemerle — это в первую очередь высококачественное ФП, МП и хорошая совместимость с C# на уровне библиотек и фрэймворков. G>Буллшит детектед. G>"Высококачественное МП" без сахара для монад, карированых функций, first class operators и first class events не кажется уж таким высококачественным.
Уважаемый, не позорься. Ты выставляешь себя полнешим клоуном. Как Петрик. Любой кто даже поверхностно знает Nemerle понимает что ты несешь околесицу. Сейчас тебя закидают какашками. Приготовься. Но это будут делать другие. Мне просто в лом в который раз отвечать на столь очевидно беспочвенные утверждения.
G>МП возможно есть, но это большая библиотека, которую надо изучить, понять принципы её применения, а для этого материалов мало.
А ну, да. Старые плесни о главном. Видимо ты и есть некий Стас вот в этом блоге.
VD>>Это просто бессмысленно. Если проект есть, то никакими средствами этот факт не отмерить. VD>>Проект можно развивать на Nemerle, или можно начать новый проект (или подпроект) на Nemerle. Но переписывать — это какой-то мазохизм. Я бы и сам не стал это делать. G>Крайне несогласен. У меня есть несколько проектов (веб, десктоп, математика, чат-сервер итп) объемом около 1000 строк, я их переписываю с применением новых технологий чтобы почувствовать на себе. Крупные проекты, которые приносят деньги я даже трогать не собираюсь.
Значит тебе откровенно не чем заняться. Переписывание готового качественного кода — это пустая трата времени. Всегда можно найти что написать на новом языке и без переписывания работаующего кода.
G>>>Оказывается asp.net низзя, надо другой фреймворк, EF\Linq2SQL тоже, Linq работает но через *опу... Какая реакция последует? "да ну вас на**й с вашим Nemerle". VD>>На счет линка не понял. Что с ним не так? G>Синтаксис. Раньше и другие проблемы были, сейчас сложно сказать.
И что с синтаксисом не так?
VD>>А что до веб-проектов, то они к счастью состоят из отдельных страниц. G>То что состоит из отдельных страниц к счастью программирования не требует вообще. G>Я вот последнее время использую webmatrix и razor
Что же такое webmatrix?
WebMatrix is everything you need to build Web sites using Windows. It includes IIS Developer Express (a development Web server), ASP.NET (a Web framework), and SQL Server Compact (an embedded database).
то есть, практически ничего для того кто хоть раз видел VS.
Да и сказать что "я использую webmatrix" — это все равно что ничего не сказать.
Реально ты видимо используешь ASP.NET MVC с Razor в качестве движка рендеренга. Razor лучшее что смогли сотворить в МС, но вот реализация того же ASP.NET MVC далека от совершенства. Куча приседаний с неявным результатом. Сравнивать это с Nemerle on rails просто смешно. А уж с теми идеями о которых говорит WolfHound и подавно.
Ну, и точно уж нет особых проблем, чтобы завивать ASP.NET MVC сайт на Nemerle on rails или просто использовать Nemerle в рамках такого проекта.
VD>>И нет никаких проблем начать делать отдельные из них на новом инструменте. А там, потихонечку, можно будет перейти полностью. G>Ага, только nemerle не умеет razor. C# и VB умеют, а nemerle — нет.
Ды ты не боись. Сделать поддержку Razor не сложно. Было бы желание. Кстати, тоже не плохая задача для освоения языка.
Ziaw реализовал поддержку Spark-а (тоже не плохого движка рендеренга для MVC). Razor в то время, как я понимаю, еще был суровой бэтой. Но сейчас можно реализовать поддержку Razor, раз уж он стал официально доступен.
Вот только не уверен, что у Razor будут реальные приемущества над Nemerle.Xml. В прочем, каждому свое. Если хочется не гибкости, а мастерпэйджей и прочих радостей псевдо-дизайнера, то можно использовать и MVC-шные движки ренедеренга.
VD>>Да пусть напирает. Все равно это ему не помогает. Ему даже поддержка МС не помогает. Он как был чужим в дотнете, так и останется. G>Тем не менее он и сейчас популярнее nemerle и как бы его популярность только растет.
Да где он популярнее то? Зачем врать самому себе?
G>>>Такого при желании на C# не повторишь, да и на nemerle с трудом.
VD>>Слушая тебя я прямо таки узнаю много нового. Ты, кстати, в своем сообщении отвечал челвеку (Вольфхаунду) который повторил их Async на макросах немерла. Получилось чуть более гибче, кстати. G>Я в курсе что там получилось. G>всякие defcomp и callcomp слегка напрягают,почему нельзя было сделать def! и do! ?
А меня вот напрягало бы использование оператора "not" и ключевого слова из цикла. И что?
Важен сам факт наличия фичи. И если ты уж знаешь, то не стоит тогда принародно говорить не правды про то, что в немерле нет сахара для монад. Или ты не в курсе, что это как раз и есть сахар для монад?
G>Общий вопрос. Почему при "Высококачественном МП" не было монад изначально в языке?
Дык не нужны они никому.
Я тебе более скажу. Вот уже несколко месяцев как у нас есть библиотека ComputationExpressions, но за все это время меня (да и других) не потянуло ее использовать. Как-то многопточностью в последнее время не занимаюсь. А вдругих применениях от ComputationExpressions не так много пользя. Есть ведь и другие не менее удобные решения. К тому же более привычные.
Если же вопрос ставит ударение на "в языке", дык соверешнно очевидно почему. Потому что таким вещам в языке не место. Для подобных вещей как раз и созданы макросы.
Немерл потому и является самым мощьным языком для дотнета, что в отличии от других языков он обладает макрос-системой.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
VD>>А зачем повторять то? G>Для обучения, чтобы преимущества почувствовать.
Чтобы почувствовать приемущества не надо ничего повторять.
Более того если именно что повторять (бездумно копировать) то результатом и будет копия.
G>>>>>EF\Linq2SQL тоже, WH>>>>Можно. G>>>А недавняя бага интеграции с EF?
VD>>Ссылку в студию. G>http://www.rsdn.ru/forum/nemerle/3823376.flat.aspx
Я думал поплуярность языка определяется частотой его использовния в реальных проектах, а не клоичеством вопросов почему в языке криво то или се. К тому же на одном сайте.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
ВВ>>>Справедливости ради, как-то сложно представить реализацию ASP.NET без http handlers/modules. Там это, собственно, самый базовый механизм. На нем все и построено.
VD>>Что там представлять то? Залепили свой аналог, и аля-улю, гони гусей (с).
G>Хм... а расширение для IIS, которое будет запускать твои аналоги кто писать будет?
А причем тут IIS. Моновцы многое через одно место делают.
G>Кстати в мире java примерно так и делают, там этих app-серверов как собак нерезаных, а потом подходящий хостинг не найдешь.
Кстати, не надо путать веб-сервер и сервер приложений. Сам по себе веб-сервер не такой уж сложный продукт. Это только МС монстра из IIS-а сделал.
G>На надо создавать инфраструктуру на nemerle, надо создавать приложения.
Это кому как. Если имеющаяся инфраструктура не обеспечивает подтребнсоти, то посредственные программисты городят тонны однообразного кода руками приговрания — "ничег не поделаешь, такая задача...", а хорошие программисты создают инфраструктуру под себя или дорабатывают имеющуюся.
Так что хочешь получить качественно приложения, незабуть подумать об инфраструктуре.
G>А вот с приложениями у nemerle хреново. Единственный реальный пример крупного проекта на nemerle — компилятор nemerle.
Тут оно как. Одни люди совсем не самостятельны. В стаде (по середке или ближе к концу) плестись могут, но сами что-то оценить и пойти впереди стада или всторону от него не могут. Другие идут впереди и снимают сливки.
Лично мне не надо никаких доказателсьв чтобы оценить язык. Я могу попросу попробовать его и сформирвоать мнение.
Рано или поздно приложения появятся, и возможно, стадо двинется в указанном направлении, но так как в стаде движение происходит с одинаковой скорость, то у цели окажется все стадо. И извлечь выгоду из этого не получится.
Конечно, если язык и правда плох, то движение в стаде защитит от неверного выбора.
Но что если язык все же действительно хорош и те кто его попробовали не врут?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
VD>>>Nemerle — это в первую очередь высококачественное ФП, МП и хорошая совместимость с C# на уровне библиотек и фрэймворков. G>>Буллшит детектед. G>>"Высококачественное МП" без сахара для монад, карированых функций, first class operators и first class events не кажется уж таким высококачественным.
VD>Уважаемый, не позорься. Ты выставляешь себя полнешим клоуном. Как Петрик. Любой кто даже поверхностно знает Nemerle понимает что ты несешь околесицу. Сейчас тебя закидают какашками. Приготовься. Но это будут делать другие. Мне просто в лом в который раз отвечать на столь очевидно беспочвенные утверждения.
Ок, я на nemerle писал что-нить пару месяцев назад, может что изменилось.
Давай конкретнее.
На F#
[|1;2;3;4|]
|> Seq.map
|> Seq.reduce (*)
let f = new Form(Visible = true)
let button = new Button(Text = "Click me")
f.Controls.Add(button)
let cookie =
button.Click
|> Observable.scan (fun x _ -> x+1) 0
|> Observable.subscribe( fun x ->
MessageBox.Show(sprintf "Clicked %d times" x) |> ignore )
Как будет на Nemerle?
VD>>>Это просто бессмысленно. Если проект есть, то никакими средствами этот факт не отмерить. VD>>>Проект можно развивать на Nemerle, или можно начать новый проект (или подпроект) на Nemerle. Но переписывать — это какой-то мазохизм. Я бы и сам не стал это делать. G>>Крайне несогласен. У меня есть несколько проектов (веб, десктоп, математика, чат-сервер итп) объемом около 1000 строк, я их переписываю с применением новых технологий чтобы почувствовать на себе. Крупные проекты, которые приносят деньги я даже трогать не собираюсь.
VD>Значит тебе откровенно не чем заняться.
Мне есть чем заняться.
VD>Переписывание готового качественного кода — это пустая трата времени. Всегда можно найти что написать на новом языке и без переписывания работаующего кода.
А зачем искать если уже есть готовые идеи?
Например Microsoft_овский NerdDinner было бы интересно повторить на Nemerle.
G>>>>Оказывается asp.net низзя, надо другой фреймворк, EF\Linq2SQL тоже, Linq работает но через *опу... Какая реакция последует? "да ну вас на**й с вашим Nemerle". VD>>>На счет линка не понял. Что с ним не так? G>>Синтаксис. Раньше и другие проблемы были, сейчас сложно сказать. VD>И что с синтаксисом не так?
<# #>...
VD>>>А что до веб-проектов, то они к счастью состоят из отдельных страниц. G>>То что состоит из отдельных страниц к счастью программирования не требует вообще. G>>Я вот последнее время использую webmatrix и razor
VD>Что же такое webmatrix? VD>
VD>WebMatrix is everything you need to build Web sites using Windows. It includes IIS Developer Express (a development Web server), ASP.NET (a Web framework), and SQL Server Compact (an embedded database).
VD>то есть, практически ничего для того кто хоть раз видел VS.
Ты видимо сам много раз использовал WebMatrix
VD>Да и сказать что "я использую webmatrix" — это все равно что ничего не сказать.
Да ну?
VD>Реально ты видимо используешь ASP.NET MVC с Razor в качестве движка рендеренга.
И его тоже использую, но это не webmatrix.
VD>Razor лучшее что смогли сотворить в МС, но вот реализация того же ASP.NET MVC далека от совершенства. Куча приседаний с неявным результатом. Сравнивать это с Nemerle on rails просто смешно. А уж с теми идеями о которых говорит WolfHound и подавно.
Ну да, готовый фреймворк сравнивать с идеями, половина из которых только в Nemerle 2 (которого еще нет) могут быть реализованы, действительно смешно.
VD>Ну, и точно уж нет особых проблем, чтобы завивать ASP.NET MVC сайт на Nemerle on rails или просто использовать Nemerle в рамках такого проекта.
Одна проблема: нет razor.
VD>>>И нет никаких проблем начать делать отдельные из них на новом инструменте. А там, потихонечку, можно будет перейти полностью. G>>Ага, только nemerle не умеет razor. C# и VB умеют, а nemerle — нет.
VD>Ды ты не боись. Сделать поддержку Razor не сложно. Было бы желание. Кстати, тоже не плохая задача для освоения языка.
Да вот есть проблема. Язык то я знаю, могу на нем сварганить простенькое приложение, но вот макросы изучать мне некогда, особенно при таком количестве материалов.
VD>Ziaw реализовал поддержку Spark-а (тоже не плохого движка рендеренга для MVC). Razor в то время, как я понимаю, еще был суровой бэтой. Но сейчас можно реализовать поддержку Razor, раз уж он стал официально доступен.
Он и сейчас beta, но уже в двух технологиях используется (mvc и webmatrix).
VD>Вот только не уверен, что у Razor будут реальные приемущества над Nemerle.Xml. В прочем, каждому свое. Если хочется не гибкости, а мастерпэйджей и прочих радостей псевдо-дизайнера, то можно использовать и MVC-шные движки ренедеренга.
Какой смысл писать код на Nemerle и view на C#? С razor я могу писать view на C# или VB — том же языке, что и проект.
G>>>>Такого при желании на C# не повторишь, да и на nemerle с трудом.
VD>Важен сам факт наличия фичи. И если ты уж знаешь, то не стоит тогда принародно говорить не правды про то, что в немерле нет сахара для монад. Или ты не в курсе, что это как раз и есть сахар для монад?
G>>Общий вопрос. Почему при "Высококачественном МП" не было монад изначально в языке? VD>Дык не нужны они никому.
Датыче?
VD>Я тебе более скажу. Вот уже несколко месяцев как у нас есть библиотека ComputationExpressions, но за все это время меня (да и других) не потянуло ее использовать. Как-то многопточностью в последнее время не занимаюсь. А вдругих применениях от ComputationExpressions не так много пользя. Есть ведь и другие не менее удобные решения. К тому же более привычные.
Видимо поэтому и не было.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, gandjustas, Вы писали:
ВВ>>>>Справедливости ради, как-то сложно представить реализацию ASP.NET без http handlers/modules. Там это, собственно, самый базовый механизм. На нем все и построено.
VD>>>Что там представлять то? Залепили свой аналог, и аля-улю, гони гусей (с). G>>Хм... а расширение для IIS, которое будет запускать твои аналоги кто писать будет? VD>А причем тут IIS. Моновцы многое через одно место делают.
Так они 100% повторили asp.net чтобы он запускался на apache.
А ты зачем-то придумываешь свое.
G>>Кстати в мире java примерно так и делают, там этих app-серверов как собак нерезаных, а потом подходящий хостинг не найдешь. VD>Кстати, не надо путать веб-сервер и сервер приложений. Сам по себе веб-сервер не такой уж сложный продукт. Это только МС монстра из IIS-а сделал.
И что?
G>>На надо создавать инфраструктуру на nemerle, надо создавать приложения. VD>Это кому как. Если имеющаяся инфраструктура не обеспечивает подтребнсоти, то посредственные программисты городят тонны однообразного кода руками приговрания — "ничег не поделаешь, такая задача...", а хорошие программисты создают инфраструктуру под себя или дорабатывают имеющуюся.
Это как раз плохие программисты так делают, а хорошие берут готовые решения.
Почти каждая задача хотя бы раз решалась, а ля многих уже написаны библиотеки.
VD>Так что хочешь получить качественно приложения, незабуть подумать об инфраструктуре.
Если хочешь качественное приложение, не думай о создании инфраструктуры, используй готовую.
G>>А вот с приложениями у nemerle хреново. Единственный реальный пример крупного проекта на nemerle — компилятор nemerle. VD>Тут оно как. Одни люди совсем не самостятельны. В стаде (по середке или ближе к концу) плестись могут, но сами что-то оценить и пойти впереди стада или всторону от него не могут. Другие идут впереди и снимают сливки. VD>Лично мне не надо никаких доказателсьв чтобы оценить язык. Я могу попросу попробовать его и сформирвоать мнение.
И как всегда мнение одного мало кого интересует, а массы почему-то имею другое мнение.
VD>Рано или поздно приложения появятся, и возможно, стадо двинется в указанном направлении, но так как в стаде движение происходит с одинаковой скорость, то у цели окажется все стадо. И извлечь выгоду из этого не получится.
Ну таки ушел от обсуждения какие же проекты есть на nemerle?
Хотелось бы посмотреть как там люди реальные задачи решают.
VD>Конечно, если язык и правда плох, то движение в стаде защитит от неверного выбора. VD>Но что если язык все же действительно хорош и те кто его попробовали не врут?
Язык может и хорошо, но кроме качеств язык еще много других проблем есть.
Мне например haskell нравится, но для него тонны библиотек, которые надо долго изучать, также еще полтонны матана надо разобрать, IDE толком нет. Поэтому не могу я его массово использовать, несмотря на все преимущества.
Здесь ошибки нет? Я F# не знаю, но судя по тому, что |> посылает аргумент в функцию, и у него левая ассоциация, мы получим
Seq.reduce (*) (Seq.map [|1;2;3;4|])
что, очевидно, бред.
Я также не знаю и Nemerle, но в любом случае, в языке, в котором есть HOF и placeholder для создания лямбды, это сделать можно со схожей степенью выразительности.
G>
G>let f = new Form(Visible = true)
G>let button = new Button(Text = "Click me")
G>f.Controls.Add(button)
G>let cookie =
G> button.Click
G> |> Observable.scan (fun x _ -> x+1) 0
G> |> Observable.subscribe( fun x ->
G> MessageBox.Show(sprintf "Clicked %d times" x) |> ignore )
G>
G>Как будет на Nemerle?
Аналогично, не понимаю, какие здесь могут быть сложности.
L>Здесь ошибки нет?
Есть, че-то не то скопировал
надо так:
[|1;2;3;|]
|> Seq.map (fun x -> x*x)
|> Seq.reduce (*)
L>Я также не знаю и Nemerle, но в любом случае, в языке, в котором есть HOF и placeholder для создания лямбды, это сделать можно со схожей степенью выразительности.
G>>
G>>let f = new Form(Visible = true)
G>>let button = new Button(Text = "Click me")
G>>f.Controls.Add(button)
G>>let cookie =
G>> button.Click
G>> |> Observable.scan (fun x _ -> x+1) 0
G>> |> Observable.subscribe( fun x ->
G>> MessageBox.Show(sprintf "Clicked %d times" x) |> ignore )
G>>
G>>Как будет на Nemerle?
L>Аналогично, не понимаю, какие здесь могут быть сложности.
Как минимум вы том что nemerle не поддерживает first class events.
Пайпы в Немерле тоже есть, в виде макросов, так что можно записать практически аналогично. Тут товарищ, видимо, намекает на то, что в Немерле функции не являются каррированными, поэтому, если воспроизводить буквально, придется писать как-то так:
[1, 2, 3]
|> Map(fun(x) { x * x }, _)
|> Reduce(_*_, _)
(Причем скорее всего на Немерле это будет реализовано все же через Linq).
Оно, может, и менее красиво, но разница все же ничтожна. А вот разницы между (*) и _*_ я не вижу в упор. Первое товарищ называет "first class operator", второе же упорно игнорирует. Причем все это обсуждалось где-то полгода назад с ровно теми же самыми вопросами.
Здравствуйте, lomeo, Вы писали:
L>>>Аналогично, не понимаю, какие здесь могут быть сложности. G>>Как минимум вы том что nemerle не поддерживает first class events.
L>Что такое first class events?
Ну собственно то и значит, что события можно передавать параметром в функцию и возвращаться из функции.
L>Замыканий недостаточно?
Недостаточно
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Тут товарищ, видимо, намекает на то, что в Немерле функции не являются каррированными
Я поэтому про placeholder и сказал. По сравнению с каррингом у него есть свои преимущества и недостатки. В этом примере преимуществ нет, но и недостатки незначительны.
ВВ>(Причем скорее всего на Немерле это будет реализовано все же через Linq).
+1, но иногда хочется странного. Чтобы легко делать комбинаторы, к сожалению, нужно автоматическое каррирование.
ВВ>Оно, может, и менее красиво, но разница все же ничтожна. А вот разницы между (*) и _*_ я не вижу в упор. Первое товарищ называет "first class operator", второе же упорно игнорирует.
Карринг не сильно поможет написать аналог
"(" + _ + ")"
ВВ>Причем все это обсуждалось где-то полгода назад с ровно теми же самыми вопросами.
Ну ещё пообсуждаем, нам не сложно, тем более я в первый раз выступаю защитником Nemerle
Здравствуйте, gandjustas, Вы писали:
L>>Что такое first class events? G>Ну собственно то и значит, что события можно передавать параметром в функцию и возвращаться из функции.
Хорошо, по другому спрошу — что такое событие?
Событие — это Button.Click, да? Если да, то я вообще не вижу проблему — что мешает реализовать то же самое на Nemerle?
Здравствуйте, lomeo, Вы писали:
ВВ>>Тут товарищ, видимо, намекает на то, что в Немерле функции не являются каррированными L>Я поэтому про placeholder и сказал. По сравнению с каррингом у него есть свои преимущества и недостатки. В этом примере преимуществ нет, но и недостатки незначительны. ВВ>>(Причем скорее всего на Немерле это будет реализовано все же через Linq). L>+1, но иногда хочется странного. Чтобы легко делать комбинаторы, к сожалению, нужно автоматическое каррирование.
Каррирование и placeholder, мне кажется, вещи вообще ортогональные.
То, что в Немерле все функции не являются каррированными, это, конечно, минус. Сами поляки, напротив, зачем-то специально позиционировали, что аргументы всех функций описываются через кортеж, и в языке есть даже "фишки", которые как бы подтверждают это. Например, автоматическая распаковка кортежа, если, скажем, кортеж из трех элементов передается в функцию от трех аргументов.
Что интересно — тут недавно было обсуждение, в процессе которого оказалось, что подобные неявные конверсии людям не очень нравятся.
Влад мне как-то пытался объяснить, почему каррирование в Немерле добавить нельзя. Но я так и не понял, честно говоря. Есть у меня подозрение, что все там можно Можно сделать как в F# — у всех "родных" функций сигнатура уже имеет вид int->int->int вместо (int*int)->int, а мембер-функции всегда имеют сигнатуру (int*int)->int и их нельзя каррировать.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Влад мне как-то пытался объяснить, почему каррирование в Немерле добавить нельзя. Но я так и не понял, честно говоря. Есть у меня подозрение, что все там можно Можно сделать как в F# — у всех "родных" функций сигнатура уже имеет вид int->int->int вместо (int*int)->int, а мембер-функции всегда имеют сигнатуру (int*int)->int и их нельзя каррировать.
Если делать как в F#, то лично мне не нравится, что база получается большая. Вместо того, чтобы делать эта-экспансию, инлайны и выпрямлять цепочку, пишется куча кода, который должен программист знать, когда и что применять. Ну и сам аналогично поддерживать две иерархии функций (или три в зависимости от кол-ва аргументов). Если же автоматом создавать замыкания на месте карринга, тоже ничего хорошего — производительность, неявное создание, нельзя делать перегрузку по кол-ву аргументов.
Здравствуйте, Воронков Василий, Вы писали:
ВВ> Есть у меня подозрение, что все там можно Можно сделать как в F# — у всех "родных" функций сигнатура уже имеет вид int->int->int вместо (int*int)->int, а мембер-функции всегда имеют сигнатуру (int*int)->int и их нельзя каррировать.
Эт, мужики, я вот реально не догоняю зачем нужно это каррирование и какая от него польза.
Здравствуйте, lomeo, Вы писали:
L>Если делать как в F#, то лично мне не нравится, что база получается большая. Вместо того, чтобы делать эта-экспансию, инлайны и выпрямлять цепочку, пишется куча кода, который должен программист знать, когда и что применять. Ну и сам аналогично поддерживать две иерархии функций (или три в зависимости от кол-ва аргументов). Если же автоматом создавать замыкания на месте карринга, тоже ничего хорошего — производительность, неявное создание, нельзя делать перегрузку по кол-ву аргументов. L>IMHO, не надо на Nemerle писать как на F#.
"Как на F#" я имею в виду "все функции каррированные" (кроме нехороших мембер-функций, которые некаррированные). По поводу "выпрямлять цепочку" ты имеешь в виду лифтинг замыканий? Ну тут я просто не в курсе, что оба компилятора делают. Компилятор C#, к примеру, не занимается таким. Перегрузка для локальных функций и сейчас недоступна. Фишка с неявной распаковкой кортежа, которая идеологически противоречит каррированию, вроде как considered harmful.
Т.е. если чисто прагматично подойти к вопросу, то что по-большому счету нужно-то? Нужен сахар. Запись кода так, как если бы функция была каррированой в некоторых случаях лаконичнее и выразительной, чем создание новой функции через placeholder.
Т.е. предположим, что на некоем "более другом" Немерле валидным является код вида:
def sum(x, y) { x + y }
def sum2 = sum(2);
sum2(2);
Этот код может рассахариваться в:
def sum(x, y) { x + y }
def sum2 = sum(_, 2);
sum2(2);
Т.е. таки да — с т.з. производительности это не очень круто, получается двойной вызов. Но ведь не хуже чем сейчас? Ибо другого варианта кроме как 2 сейчас вообще нет.
Здравствуйте, hardcase, Вы писали:
H>Эт, мужики, я вот реально не догоняю зачем нужно это каррирование и какая от него польза.
Удобно писать в комбинаторном стиле, когда мы работаем не с данными, а с их обработчиками. В этом случае код получается очень composable, мы можем легко использовать такую замечательную технику, как equational reasoning.
Вот как код с данными (использующий паттерн матчинг) на Nemerle в Haskell легко преобразуется в более приятный аналог
Здравствуйте, hardcase, Вы писали:
ВВ>> Есть у меня подозрение, что все там можно Можно сделать как в F# — у всех "родных" функций сигнатура уже имеет вид int->int->int вместо (int*int)->int, а мембер-функции всегда имеют сигнатуру (int*int)->int и их нельзя каррировать. H>Эт, мужики, я вот реально не догоняю зачем нужно это каррирование и какая от него польза.
Каррирование нужно для частичного применения. И польза от него соответствующая. По сравнению с использованием оператора "_" запись в некоторых случаях получается более лаконичной, т.е. вместо Sum2(_, 2) будешь писать Sum2(2).
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Т.е. таки да — с т.з. производительности это не очень круто, получается двойной вызов. Но ведь не хуже чем сейчас? Ибо другого варианта кроме как 2 сейчас вообще нет.
Повторю — если оставить отмеченную тобой производительность, то это неявность создания замыкания, которая вступает в конфликт с перегрузкой функции по кол-ву аргументов.
Здравствуйте, lomeo, Вы писали:
L>Повторю — если оставить отмеченную тобой производительность, то это неявность создания замыкания, которая вступает в конфликт с перегрузкой функции по кол-ву аргументов.
Перегрузки для локальных функций нет. И как ты ее себе представляешь?
Здравствуйте, Воронков Василий, Вы писали:
L>>Повторю — если оставить отмеченную тобой производительность, то это неявность создания замыкания, которая вступает в конфликт с перегрузкой функции по кол-ву аргументов. ВВ>Перегрузки для локальных функций нет. И как ты ее себе представляешь?
Представляю как и обычную перегрузку, скажем, методов. В любом случае, извиняюсь, я как то пропустил твоё "Перегрузка для локальных функций и сейчас недоступна".
Поэтому я говорил не только о локальных функциях (это же nested functions — так?). Я говорил о внешних для кода функций (или методов) — каррирование только для локальных функций принесёт очень мало пользы. Я говорю в контексте вообще функций/методов (всего, что принимает аргументы) — их то можно перегружать в Nemerle?
Здравствуйте, lomeo, Вы писали:
L>Поэтому я говорил не только о локальных функциях (это же nested functions — так?). Я говорил о внешних для кода функций (или методов) — каррирование только для локальных функций принесёт очень мало пользы. Я говорю в контексте вообще функций/методов (всего, что принимает аргументы) — их то можно перегружать в Nemerle?
Их поэтому я и говорю "как в F#". Там нет перегрузки для локальных функций, но есть каррирование. Для мембер-функций есть перегрузка, но каррирования нет.
Хотя я сейчас тоже засомневался в полезности каррирования для локальных функций только. В F# они играют как бы большую роль. Все вот эти вот Seq.reduce, Seq.map — это "локальные" функции. Ну т.е. термин "локальная функция" здесь, конечно, неприемлим. В F# есть как бы четкое разделение — .NET функции и "свои" функции. "Свои" функции не поддерживают перегрузку. Т.е. ты не сможешь сделать Seq.reduce с другим списком параметров — поэтому в стандартных модулях много функций типа reduce2, map2 и пр.
В Немерле в принципе это разделение тоже присутствует. Но в Немерле есть нюанс — если F# "отгораживается" от враждебного дотнета своими модулями, то Немерле так по большому счету не делает. Например, для работы с последовательностями там вполне кошерно использовать Линк. А вот с Линком каррирование уже не прокатит точно.
Здравствуйте, lomeo, Вы писали:
L>>>Повторю — если оставить отмеченную тобой производительность, то это неявность создания замыкания, которая вступает в конфликт с перегрузкой функции по кол-ву аргументов. ВВ>>Перегрузки для локальных функций нет. И как ты ее себе представляешь? L>Представляю как и обычную перегрузку, скажем, методов.
Кстати, а как это вообще сочетается с "первоклассностью" функций? Скажем:
def sum(x, y) { x + y }
def sum(x, y, z) { x + y + z}
def f = sum; //Здесь у нас вообще что?
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Хотя я сейчас тоже засомневался в полезности каррирования для локальных функций только. В F# они играют как бы большую роль. Все вот эти вот Seq.reduce, Seq.map — это "локальные" функции. Ну т.е. термин "локальная функция" здесь, конечно, неприемлим. В F# есть как бы четкое разделение — .NET функции и "свои" функции. "Свои" функции не поддерживают перегрузку. Т.е. ты не сможешь сделать Seq.reduce с другим списком параметров — поэтому в стандартных модулях много функций типа reduce2, map2 и пр.
Ага, понял, спасибо. HM-вывод типов не допускает перегрузки, думаю.
ВВ>В Немерле в принципе это разделение тоже присутствует. Но в Немерле есть нюанс — если F# "отгораживается" от враждебного дотнета своими модулями, то Немерле так по большому счету не делает. Например, для работы с последовательностями там вполне кошерно использовать Линк. А вот с Линком каррирование уже не прокатит точно.
ВВ>>def sum(x, y) { x + y }
ВВ>>def sum(x, y, z) { x + y + z}
ВВ>>def f = sum; //Здесь у нас вообще что?
ВВ>>
L>Не знаю. А разве не так надо:
L>
L>def f = sum(_, _)
L>
Здесь ты новую функцию создал. У меня же ничего не создается.
Фишка в том, что так называемые "локальные функции" являются первоклассными объектами, т.е. их запись вида:
def sum(x, y) { x + y }
В некотором смысле аналогична:
def val = 1
Можно сказать, что в первом случае ты объявляешь переменную функционального типа, значением которой является приведенная функция. Это значение можно передавать в другие функции, присваивать другим переменным и пр.
Здравствуйте, lomeo, Вы писали:
ВВ>>Хотя я сейчас тоже засомневался в полезности каррирования для локальных функций только. В F# они играют как бы большую роль. Все вот эти вот Seq.reduce, Seq.map — это "локальные" функции. Ну т.е. термин "локальная функция" здесь, конечно, неприемлим. В F# есть как бы четкое разделение — .NET функции и "свои" функции. "Свои" функции не поддерживают перегрузку. Т.е. ты не сможешь сделать Seq.reduce с другим списком параметров — поэтому в стандартных модулях много функций типа reduce2, map2 и пр. L>Ага, понял, спасибо. HM-вывод типов не допускает перегрузки, думаю.
Мне кажется, его в первую очередь "первоклассность" функций не допускает.
Здравствуйте, lomeo, Вы писали:
L>Удобно писать в комбинаторном стиле, когда мы работаем не с данными, а с их обработчиками. В этом случае код получается очень composable, мы можем легко использовать такую замечательную технику, как equational reasoning.
Спасибо. Идею уловил.
В чистом виде каррирование на Nemerle не взлетит — оно идет вразрез с системой типов .NET, и, как следствие, дизайном языка.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Каррирование нужно для частичного применения. И польза от него соответствующая. По сравнению с использованием оператора "_" запись в некоторых случаях получается более лаконичной, т.е. вместо Sum2(_, 2) будешь писать Sum2(2).
Я уже понял. УК lomeo пару ссылок дал.
Жаль что фича с частичым применением недопиленная — она плохо работает с макросами.
Здравствуйте, hardcase, Вы писали:
H>Спасибо. Идею уловил. H>В чистом виде каррирование на Nemerle не взлетит — оно идет вразрез с системой типов .NET, и, как следствие, дизайном языка.
Следствие тут не вижу, честно говоря. В Немерле многое идет вразрез с системой типов .NET.
Здравствуйте, lomeo, Вы писали:
ВВ>>Причем все это обсуждалось где-то полгода назад с ровно теми же самыми вопросами.
L>Ну ещё пообсуждаем, нам не сложно, тем более я в первый раз выступаю защитником Nemerle
Ага. Я тоже хотел сказать об этом. Вообще показательно, что даже люди Nemerle-ом не занимающиеся и в нем не заинтересованные говорят об неадекватности претензий. Причем, как правильно заметил Воронков, претензии эти в неизменном виде повторяются одним и тем же человеком с завидной периодичностью.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Влад мне как-то пытался объяснить, почему каррирование в Немерле добавить нельзя. Но я так и не понял, честно говоря. Есть у меня подозрение, что все там можно Можно сделать как в F# — у всех "родных" функций сигнатура уже имеет вид int->int->int вместо (int*int)->int, а мембер-функции всегда имеют сигнатуру (int*int)->int и их нельзя каррировать.
Да все можно, если не противоречит законам физики. Вот только деление функций на родные и инородные — это дичайший косяк дизайна языка, на мой взгляд.
Зачем ставить крест на общепринятом С-ишном синтаксисе в угоду ровным счетом ничего не дающей фишки? Частичное применение немерла не менее удобно нежели каринг, и при этом его еще очень легко объяснить (и понять).
В общем, не надо ходить на поводу у тролей. Человеку просто по фигу любые мнения и рассуждения, от тупо повторяет заученный текст в котором нет ни капли здравого смысла.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Здравствуйте, Воронков Василий, Вы писали:
ВВ>>Влад мне как-то пытался объяснить, почему каррирование в Немерле добавить нельзя. Но я так и не понял, честно говоря. Есть у меня подозрение, что все там можно Можно сделать как в F# — у всех "родных" функций сигнатура уже имеет вид int->int->int вместо (int*int)->int, а мембер-функции всегда имеют сигнатуру (int*int)->int и их нельзя каррировать.
L>Если делать как в F#, то лично мне не нравится, что база получается большая.
А зачем делать как в F#? Это самоцель?
L>IMHO, не надо на Nemerle писать как на F#.
Вот именном! У него свой С-подобный стиль. И в этом его преимущество (и конечно же недостаток, в зависимости от пристрастий). К тому же, тех кому сишный стиль ближе неимоверно больше.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, lomeo, Вы писали:
L>>Повторю — если оставить отмеченную тобой производительность, то это неявность создания замыкания, которая вступает в конфликт с перегрузкой функции по кол-ву аргументов.
ВВ>Перегрузки для локальных функций нет. И как ты ее себе представляешь?
Ты уже достал с этими локальными функциями. Кроме них есть все остальные для которых перегрузка есть. А делать разный синтаксис вызова для локльных функций и остальных — это значит вносить в язык глобальный дизайнерский косяк.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ты уже достал с этими локальными функциями. Кроме них есть все остальные для которых перегрузка есть. А делать разный синтаксис вызова для локльных функций и остальных — это значит вносить в язык глобальный дизайнерский косяк.
Так, спокойнее
Можно, я маленький такое вопрос задам? Причем тут вообще синтаксис? Каррирование к синтаксису никакого отношения не имеет.
Здравствуйте, VladD2, Вы писали:
VD>Да все можно, если не противоречит законам физики. Вот только деление функций на родные и инородные — это дичайший косяк дизайна языка, на мой взгляд.
Деление все равно есть. Можешь назвать его как-нибудь иначе. Есть "локальные функции", есть "мембер-функции". От названия тут суть не меняется.
VD>Зачем ставить крест на общепринятом С-ишном синтаксисе в угоду ровным счетом ничего не дающей фишки? Частичное применение немерла не менее удобно нежели каринг, и при этом его еще очень легко объяснить (и понять).
Каррирование и синтаксис ортогональны. Проблем с Си-шным синтаксисом я тут тоже не вижу
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Их поэтому я и говорю "как в F#". Там нет перегрузки для локальных функций, но есть каррирование. Для мембер-функций есть перегрузка, но каррирования нет.
Нем, дорогой товарищ! В F# нет деления на локальные и внешние функции. Там есть деление на ОКамловские и Дотнетовске функции. Другими словами есть внутренний дуализм, что на мой взгляд ни что иное как косяк языка.
Это приводит к куче проблем. Не раз встречал мнение, что в F# приходится городить кучу оберток над дотнетными АПИ. Это прямое следствие такого дуализма.
ВВ>Хотя я сейчас тоже засомневался в полезности каррирования для локальных функций только. В F# они играют как бы большую роль. Все вот эти вот Seq.reduce, Seq.map — это "локальные" функции.
Во-во "локальные" функции из модулей. Самому то не смешно?
ВВ> Ну т.е. термин "локальная функция" здесь, конечно, неприемлим.
+1
ВВ>В F# есть как бы четкое разделение — .NET функции и "свои" функции.
Вот-вот!
ВВ>"Свои" функции не поддерживают перегрузку. Т.е. ты не сможешь сделать Seq.reduce с другим списком параметров — поэтому в стандартных модулях много функций типа reduce2, map2 и пр.
Ну, 2 — это из другой оперы. Я бы их тоже так же назвал.
Главное, что есть два подхода к вызову функций, что само по себе плохо.
ВВ>В Немерле в принципе это разделение тоже присутствует.
Не выдумывай.
ВВ>Но в Немерле есть нюанс — если F# "отгораживается" от враждебного дотнета своими модулями, то Немерле так по большому счету не делает.
Ни по большому, ни по малому. Есть единый подход для всех функций.
ВВ>Например, для работы с последовательностями там вполне кошерно использовать Линк. А вот с Линком каррирование уже не прокатит точно.
Дело не в линке. Дело в способе вызова функций.
Собственно ты сам пришел к правильным выводам. Дизайн немерла не случаен. В отличии от F# при дизайне Немерла не стали пытаться адаптировать ОКамл (или любой другой МЛ) к дотнету. Вместо этого был выбран другой путь — путь дизайна языка в рамках имеющихся в дотнете С++-подобного мира, в котором есть перегрузка.
Как не странно но хорошие черты ML-я удалось органично вписать в рамки этого мира. На мой взгляд получилось очень не плохо. Возможно перебором была игра с автоматическим раскрытием кортежей, так как вреда оказалось больше чем пользы. Но и это, по большому счету мы преодолели. Я лично доработал механизм разрешения перегрузки так чтобы он предпочитал исходные перегрузки тем что получены в результате раскрытия кортежей. В итоге получилось очень даже не плохо.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
L>>Ага, понял, спасибо. HM-вывод типов не допускает перегрузки, думаю.
ВВ>Мне кажется, его в первую очередь "первоклассность" функций не допускает.
Причем тут первоклассность функций?
lomeo прав. Дело именно в перегрузке. Хиндли-Милнер не рассчитан на перегрузку. В Хаскеле для эмуляции перегрузки ввели классы типов. Но они совершенно не совместимы с дотнетой систмой типов, так что в F# просто сделали два вида функций возложив всю функциональщину на традиционные МЛьные функции, и введя картежные функции которые обделены вкусностями.
Если уж на то пошло, то надо было бы обсудить ущербность подхода F#, так как в нем весь сахар (вроде каринга) не доступен для картежный (дотнетных) функций, что является огромным минусом и приводит к необходимости клепания кучи оберточных библиотек.
Кроме того не улучшает качества кода и необходимость постоянно указывать имена модулей при доступе к "родным" функциям.
Поглядите на код аналогичный линковскому. Он просто пестрит разными именами модулей вроде "Seq.".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Круто вы, конечно. Если это "говнопорт", зачем смотреть на этот язык и фишку оттуда перенимать?
Смотрю я на все. Иначе не понять что из себя язык представляет.
А что касается фишек то иногда случаются хорошие фишки посреди груды говна.
ВВ>Где-то у вас несоответствие.
В твоем воображении.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, gandjustas, Вы писали:
G>Это потому что ты уже знаешь что такое реактивность и binding. G>А вот теперь представь что ты не знаешь что такое метапрограммирование, как будешь оценки давать?
1)Какое отношение метапрограммирование имеет к реактивному программированию и биндингу?
2)Чтобы на этом писать не нужно знать про метапрограммирование. Дустаточно знать что ViewModel волшебным образом синхронизируется с View.
Ты бы почитал доки по Knockout там все понятно написано.
G>И где он это должен увидеть?
В примерах кода.
G>Нет, у меня уже список из десятка технологий\языков\библиотек которые надо изучить.
Из-за того что ты не имеешь знаний ты создал у себя в голове кучу мифов.
И на основе этой кучи мифов ты делаешь вывод что технологию не нужно изучать.
Вот такой вот замкнутый круг.
И ладно бы ты сидел и помалкивал. Так нет ты ходишь по форумам и изливаешь тонны феерического бреда по теме в которой ты ничего не понимаешь.
G>Мне тупо некогда этим заниматься. Если и создателям языка тупо некогда, то можно считать что такой фичи нет.
Создателям языка эта фича тупо не нужна.
Немерле тем и хорошь что фичи может делать кто угодно.
G>На F# тыщи 3 строк наверное, на nemerle несколько сотен.
Ту накидал несколько строк в стиле C#++ и кричишь на всех угдах что немерле отстой. Классная позиция.
G>А где бы почитать как надо писать на nemerle с примерами из реальных проектов?
Ну так исходников полно.
Вот например: http://code.google.com/p/nemerle/source/browse/nemerle/trunk/snippets/peg-parser
G>Тока не глобальный он, а значит для меня, как пользователя он слабоват.
А знаешь что самое смешное в этом твоем требовании?
То что в языках где вывод типов глобальный всеравно явно задают типы экспортируемых функций...
Так что не так уж он и нужен если не сказать вреден.
G>Ну конечно, он нужен редко в тех языках, где его нет
Опять ты врешь. Частичное применение есть.
Я порылся в peg parser'е и нашол несколько применений этой фичи.
И что характерно ни одно из них не покрывается каррингом...
_ :> ClassMember.Function
_ is RuleAttribute.Recovery
_.IsSinglChar
hasLeftRecImpl(_, visited)
G>Надоело перечислять, оно ведь или "редко используется", или "можно сделать на макросах".
Ну то есть сказать нечего.
Так и запишем.
G>Я с другими экскаваторами разбираюсь, на ваш, для которого даже мануала нет, времени не хватает.
Влад уже столько статей понаписал что там со всем можно без проблем разобраться.
И те кто хотят без проблем разбираются.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, VladD2, Вы писали:
ВВ>>В Немерле в принципе это разделение тоже присутствует. VD>Не выдумывай.
В Немерле есть разделение на функции-члены и локальные функции. И дуализм присутствует в полном объеме, хоть его и пытались заштукатурить в отличие от F#. От него ты никуда не денешься. Есть функции "с перегрузкой". А есть функции, которые вполне можно сделать каррированными.
ВВ>>Но в Немерле есть нюанс — если F# "отгораживается" от враждебного дотнета своими модулями, то Немерле так по большому счету не делает. VD>Дело не в линке. Дело в способе вызова функций.
А он и так разный. Есть там каррирование, нет там каррирования.
VD>Собственно ты сам пришел к правильным выводам. Дизайн немерла не случаен. В отличии от F# при дизайне Немерла не стали пытаться адаптировать ОКамл (или любой другой МЛ) к дотнету. Вместо этого был выбран другой путь — путь дизайна языка в рамках имеющихся в дотнете С++-подобного мира, в котором есть перегрузка.
Влад, ты меня извини, это все такой же bullshit как "параметры функции описываются через кортеж". Ничем кардинально ситуация в Немерле от F# не отличается. Есть два разных вида функций. Разных. И их два. Я понимаю, что это для тебя видимо больная тема какая-то, но тут "дуализма" никак не избежать. И скрывать, что их на самом деле два — это все равно, что в штанах шило прятать. В F# не пытаются это делать — поэтому там есть каррированные функции и функции "с кортежем". В Немерле есть функции "с кортежем" и функции, про которые зачем-то говорится, что они "с кортежем" (причем ради этого даже баго-фичу целую реализовали) — но при этом на самом деле ни хрена там не кортеж, а абсолютно то же самое, что и в F#.
Вот на немерле оно будет практически также.
Плюс еще можно сделать макру и вместо Observable.FromEvent<EventArgs>(button1, "Click") писать так ToObservable(button1.Click).
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, lomeo, Вы писали:
L>Хорошо, по другому спрошу — что такое событие? L>Событие — это Button.Click, да? Если да, то я вообще не вижу проблему — что мешает реализовать то же самое на Nemerle?
Вера gandjustas'а в то что это сделать нельзя.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Кстати, а как это вообще сочетается с "первоклассностью" функций?
Элементарно!
ВВ>Скажем:
ВВ>
ВВ>def sum(x, y) { x + y }
ВВ>def sum(x, y, z) { x + y + z}
ВВ>def f = sum; //Здесь у нас вообще что?
ВВ>
Здесь у нас перекрытие имен, так как это локальные функции.
Но точно такой же код можно было бы написать и для статических методов (глобальных функций).
Конечно, если код будет именно таким как привел ты, то будет сообщение о неоднозначности. Например:
using System.Console;
module Program
{
Overloaded(_ : int) : void { WriteLine("Overloaded : int -> void") }
Overloaded(_ : string) : void { WriteLine("Overloaded : string -> void") }
Overloaded(_ : int, _ : int) : void { WriteLine("Overloaded : int * int -> void") }
Main() : void
{
def f = Overloaded;
}
}
в этом случае компилятор сообщит об ошибке:
Main.n(12,13):Error: typing fails on ambiguity between overloads:
Main.n(12,13):Warning: hint: Posible overload: method Program.Overloaded(_N_wildcard_2795 : string) : void
Main.n(12,13):Warning: hint: Posible overload: method Program.Overloaded(_N_wildcard_2794 : int) : void
Main.n(12,13):Warning: hint: Posible overload: method Program.Overloaded(_N_wildcard_2796 : int, _N_wildcard_2797 : int) : void
Но ведь это совершенно бессмысленный код! В реальном проекте созданная переменная будет где-то использована. Это даст алгоритму вывода типов (который, кстати сильно сложнее нежели базовый Хиндли-Милнер) возможность вычислить тип.
Вот расширенный пример:
using System.Console;
module Program
{
Overloaded(_ : int) : void { WriteLine("Overloaded : int -> void") }
Overloaded(_ : string) : void { WriteLine("Overloaded : string -> void") }
Overloaded(_ : int, _ : int) : void { WriteLine("Overloaded : int * int -> void") }
Main() : void
{
def f = Overloaded;
f(1);
def f = Overloaded;
f("test");
def f = Overloaded;
f(1, 2);
}
}
Так как Немерл выводит типы и из использования (т.е. ниже по коду), типы выведутся успешно. При запуске этого примера на экран выведется:
Overloaded : int -> void
Overloaded : string -> void
Overloaded : int * int -> void
Такое возможно благодаря отложенному выводу типов. Когда компилятор встречает строку
def f = Overloaded;
Он формирует список перегрузок (три метода описанных выше) и оставляет фрагмент кода недотипизированным. При этом создается так называемый объект отложенной типизации. Его можно представлять себе как некую лямбду ссылка на которую кладется в некий список. Лямбды из этого списка будут дергаться после того как закончится основной проход типизации.
Когда компилятор (на первом проходе, но уже после формирования объекта отложенной типизации) встречает:
f(1);
Он уточняет тип переменной "f" как "int -> ?" (где "?" означает любой тип).
На следующем проходе компилятор пытается достает объект отложенной типизации из списка и дает ему шанс повторно провести типизацию.
На этот раз тип "f" уже уточнен, что приводит к тому, что типизация двух перегрузок (Overloaded : string -> void и Overloaded : int * int -> void) оканчивается неудачей, что приводит к отбрасыванию их. Так как остается только одна перегрузка (Overloaded : int -> void) процедура разрешения перегрузки завершается успехом и генерируется код аналогичный следующему псевдокоду:
def f = Overloaded : int -> void;
f(1);
Конечно, в реальной жизни все намного сложнее, но думаю, что такого объяснения достаточно чтобы понять суть алгоритма, и то что никаких проблем с перегрузкой не будет даже если локальные функции будут ее поддерживать.
С другой стороны если ввести идею карринга (автоматического преобрзования от X * Y -> Z к X -> Y -> Z и ввести поддержку МЛьного синтаксиса (бесскобочного), то с перегрузкой будет полная задница придется заниматься приседаниями аналогичными тем что делает компилятор F#-а.
И все ради чего? По сути ради того чтобы не писать скобки при вызове. Ведь частично применение прекрасно заменяет те возможности которые предоставляет карринг.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>В Немерле есть разделение на функции-члены и локальные функции.
Опять выдумываешь. С точки зрения правил вызова никакого разделения нет.
Единственное что есть — это принцип перекрытия имен введенных с помощью def.
Но это просто калька с МЛ-я. Ничто не мешало ввести перегрузку для локальных функций. Алгоритм вывода типов это спокойно потянул бы.
Короче, суть я описал здесь
.
ВВ>И дуализм присутствует в полном объеме, хоть его и пытались заштукатурить в отличие от F#. От него ты никуда не денешься. Есть функции "с перегрузкой". А есть функции, которые вполне можно сделать каррированными.
Нет никакого дуализма. Ты его выдумал.
ВВ>>>Но в Немерле есть нюанс — если F# "отгораживается" от враждебного дотнета своими модулями, то Немерле так по большому счету не делает. VD>>Дело не в линке. Дело в способе вызова функций.
ВВ>А он и так разный. Есть там каррирование, нет там каррирования.
Синтаксис вызова функций в Немерле один — сишный.
ВВ>Влад, ты меня извини, это все такой же bullshit
Не извиню. Ты мало того что бредишь, так еще и попытку тебе что-то объяснить дерьмом называешь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Можно, я маленький такое вопрос задам? Причем тут вообще синтаксис? Каррирование к синтаксису никакого отношения не имеет.
Подумай и сам поймешь. Карринг со скобочным синтаксисом вызова методов несовместим. Потому в F# он и не поддерживается для методов.
Что мне толку от того, что компилятор будет рассматривать функцию int * int -> bool как int -> int -> bool если я этот факт не смогу никак использовать?
Если я начну вызвать эту функцию так:
f(1)(2)
то куда пойдет перегрузка? У меня ведь может быть и другая функция f которая будет принимать один параметр и возвращать скажем функцию.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, kkolyan, Вы писали:
K>хочешь чтобы люди были заинтересованы в немерле, сделай так чтобы была работа и зп повыше чем у c#( а так просто пуки в лужу)
Ты не боись. Те кто способен освоить немерл и так получают хорошую зарплату. Маленькие зарплаты — это проблема планктона.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Повторю — если оставить отмеченную тобой производительность, то это неявность создания замыкания, которая вступает в конфликт с перегрузкой функции по кол-ву аргументов.
В принципе алгоритм вывода типов который я думаю должен позволить такой финт ушами.
Вопрос лишь в том не приведет ли это решение к проблемам.
Что точно так это будет некоторая потеря производительности из-за того что придется переберать больше вариантов.
Так что тут вопрос скорее политический чем технический.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Klikujiskaaan, Вы писали:
VD>> претензии эти в неизменном виде повторяются одним и тем же человеком с завидной периодичностью. K>А воз и ныне там :-D
Ну да. Фантазией троли не блещут.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, lomeo, Вы писали:
L>Вот как код с данными (использующий паттерн матчинг) на Nemerle в Haskell легко преобразуется в более приятный аналог
L>WolfHound ужимает код в три раза на языке с ПМ
А объединить две функции можно и в немреле. Все операции над функциями в нем доступны.
Это же базовые вещи!
Проблема с твои кода в другом. Не смотря на компактность читать его сильно сложнее. Для его чтения нужно долго и упорно упражняться в том самом комбинировании функций. И если тебе этот код будет понятен, то многим другим прграммистам не очень.
А выиграл ты пару строк.
Собственно от темы мы отделились уже конкретно.
Если принять за аксиому принцип "чудес не бывает", то приходится признать, что карринг идет в разрез с перегрузкой. А раз так, то приходится делать выбор. В F# сделали выбор в пользу дуализма и карринга, в немерле в пользу перегрузки и стройности языка. На мой взгляд последний последний выбор оправдан.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
H>>В чистом виде каррирование на Nemerle не взлетит — оно идет вразрез с системой типов .NET, и, как следствие, дизайном языка.
ВВ>Следствие тут не вижу, честно говоря. В Немерле многое идет вразрез с системой типов .NET.
Примеры в студию. Посчитаем...
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Каррирование нужно для частичного применения. И польза от него соответствующая. По сравнению с использованием оператора "_" запись в некоторых случаях получается более лаконичной, т.е. вместо Sum2(_, 2) будешь писать Sum2(2).
Так как частично применение без проблем работает без карринга и дает отличные результаты, твое утверждение автоматически становится не верным.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Klikujiskaaan, Вы писали:
VD>> претензии эти в неизменном виде повторяются одним и тем же человеком с завидной периодичностью.
K>А воз и ныне там :-D
Какой воз?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, gandjustas, Вы писали:
L>>Что такое first class events? G>Ну собственно то и значит, что события можно передавать параметром в функцию и возвращаться из функции.
Пример, такой передачи в студию.
L>>Замыканий недостаточно? G>Недостаточно
И аргументацию для этого утверждения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
ВВ>>Каррирование нужно для частичного применения. И польза от него соответствующая. По сравнению с использованием оператора "_" запись в некоторых случаях получается более лаконичной, т.е. вместо Sum2(_, 2) будешь писать Sum2(2). VD>Так как частично применение без проблем работает без карринга и дает отличные результаты, твое утверждение автоматически становится не верным.
Здравствуйте, VladD2, Вы писали:
ВВ>>Следствие тут не вижу, честно говоря. В Немерле многое идет вразрез с системой типов .NET. VD>Примеры в студию. Посчитаем...
Здравствуйте, VladD2, Вы писали:
ВВ>>В Немерле есть разделение на функции-члены и локальные функции. VD>Опять выдумываешь. С точки зрения правил вызова никакого разделения нет.
Э, а что за зверь такой — "правила вызова"? Неужели ты опять про скобочки?
В F# тоже кстати можно убрать это разделение — выкинуть из языка каррирование как класс. И тогда можно будет говорить — "разделения нет". Это, видимо, ваш путь.
VD>Единственное что есть — это принцип перекрытия имен введенных с помощью def. VD>Но это просто калька с МЛ-я. Ничто не мешало ввести перегрузку для локальных функций. Алгоритм вывода типов это спокойно потянул бы. VD>Короче, суть я описал здесь
"Ничто не мешало"? Или же все-таки что-то помешало? Ты бы хоть Москаля спросил, почему они перегрузку не сделали. Даю хинт — первоклассная функция это такая, которую можно присвоить переменной.
ВВ>>И дуализм присутствует в полном объеме, хоть его и пытались заштукатурить в отличие от F#. От него ты никуда не денешься. Есть функции "с перегрузкой". А есть функции, которые вполне можно сделать каррированными. VD>Нет никакого дуализма. Ты его выдумал.
Я вообще не любитель в футбол словами играть. Не видишь — ради бога. Он правда от этого никуда не денется.
ВВ>>А он и так разный. Есть там каррирование, нет там каррирования. VD>Синтаксис вызова функций в Немерле один — сишный.
Повторяю в сотый раз — причем тут синтаксис?
ВВ>>Влад, ты меня извини, это все такой же bullshit VD>Не извиню. Ты мало того что бредишь, так еще и попытку тебе что-то объяснить дерьмом называешь.
Что ты мне пытался объяснить? Ты сказал, что не знаешь, что означает, что параметры функции описываются как кортеж. Если не знаешь, я могу тебе сказать. Это ничего не означает. Это просто бред. Который был придуман, чтобы "правила вызова" локальных функций были похожи на "правила вызова" функций-членов. Не надо вестись на это.
Здравствуйте, VladD2, Вы писали:
VD>Подумай и сам поймешь. Карринг со скобочным синтаксисом вызова методов несовместим. Потому в F# он и не поддерживается для методов. VD>Что мне толку от того, что компилятор будет рассматривать функцию int * int -> bool как int -> int -> bool если я этот факт не смогу никак использовать? VD>Если я начну вызвать эту функцию так: VD>
VD>f(1)(2)
VD>
VD>то куда пойдет перегрузка? У меня ведь может быть и другая функция f которая будет принимать один параметр и возвращать скажем функцию.
Какая еще перегрузка? Я тебя спросил про синтаксис. Ты мне про перегрузку.
Разговор о каррировании как всегда начинается с "с Сишным синтаксисом несовместимо". Тебя заклинило что ли на этом синтаксисе?
Здравствуйте, gandjustas, Вы писали:
VD>>Дык нет никаких таких фрэймворков. Все что будет — это библиотеки которые в сто раз проще изучать. G>Вообще говоря без разницы.
Ну, ты тут много утверждений противоречащих действительности сделал. Одним больше, одним меньше.
G>Насчет проще изучать тоже спорный вопрос. Много ли учебным материалов по макросам Nemerle?
Достаточно чтобы изучить все что нужно. Было бы желание.
Причем, материалы есть на Русском. По тому же F# их на русском практически нет.
G>Я нарыл четыре с половиной статьи, но примеры в них или слишком сложные, или нафиг ненужные.
Примеров нужных каждому не пасешься. Примеры демонстрируют принципы. А уж где их применять каждый должен уметь решать сам.
Пока что все кто хотели освоить осваивали без проблем.
А тех кто ищет причины чтобы оправдать свою предвзятость, они всегда найдут то что им нужно. В этом ты не оригинален.
G>Ну собственно и все, ни книг нету, ни в блога о nemerle не пишут и в реальных (необязательно коммерческих) проектах nemerle не найдешь.
Еще раз повторюсь, что материалов для освоения выше крыши. Людей которые освоили немрел так же порядочно. Причем многие освоили его прочитав одну статью или даже поигравшись с ним недельку.
Практика показывает, что те люди которые применяли немерл в течении 1-2 месяцев в реальном проекте становятся его сторонниками.
Так что кончай троллить. Не надо искать причины для оправдания своей лени. Тебя никто не заставляет изучать немерл. Море людей его не знают и в этом нет ничего плохого. Но если уж ты не знаешь язык, то не стоит ходить по форумам и нести полнейшую чушь о нем.
Пожалей свое время и репутацию. Ты же выглядишь в глазах других воинствующим невеждой.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Еще раз повторюсь, что материалов для освоения выше крыши. Людей которые освоили немрел так же порядочно. Причем многие освоили его прочитав одну статью или даже поигравшись с ним недельку.
120 человек выше крыши? f# думаю на порядок больше освоило
Здравствуйте, Воронков Василий, Вы писали:
ВВ>>>Каррирование нужно для частичного применения. И польза от него соответствующая. По сравнению с использованием оператора "_" запись в некоторых случаях получается более лаконичной, т.е. вместо Sum2(_, 2) будешь писать Sum2(2). VD>>Так как частично применение без проблем работает без карринга и дает отличные результаты, твое утверждение автоматически становится не верным.
ВВ>Какое именно из утверждений?
"Каррирование нужно для частичного применения"
Оно не нужно. Оно одна из возможных реализаций.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>>>Следствие тут не вижу, честно говоря. В Немерле многое идет вразрез с системой типов .NET. VD>>Примеры в студию. Посчитаем...
ВВ>Например, функциональный тип.
Раз! Два — это вариантный тип. На этом и обчелся.
И ни то, ни другое никак не противоречит системе типов дотнета, а очень гармонично ее дополняет.
Если ДВА (2) — это много, то конечно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
ВВ>>>>Каррирование нужно для частичного применения. И польза от него соответствующая. По сравнению с использованием оператора "_" запись в некоторых случаях получается более лаконичной, т.е. вместо Sum2(_, 2) будешь писать Sum2(2). VD>>>Так как частично применение без проблем работает без карринга и дает отличные результаты, твое утверждение автоматически становится не верным. ВВ>>Какое именно из утверждений? VD>"Каррирование нужно для частичного применения" VD>Оно не нужно. Оно одна из возможных реализаций.
Ага. Автомобиль нужен для передвижения. Передвигаться можно и пешком. Вывод — утверждение об автомобиле является ложным.
Я понял. При общении с тобой надо переходить на специальный язык. То, что у тебя понятие "синтаксис" означает совсем не синтаксис, я уже начинаю догадываться. Тебе оказывается, что и формальная логика тоже неприменима. Может, тогда просто кусками кода друг в друга швыряться будем?
Здравствуйте, VladD2, Вы писали:
ВВ>>Например, функциональный тип. VD>Раз! Два — это вариантный тип. На этом и обчелся. VD>И ни то, ни другое никак не противоречит системе типов дотнета, а очень гармонично ее дополняет. VD>Если ДВА (2) — это много, то конечно.
Дано — функциональный язык.
Дано — платформа, на которой построен этот функциональный язык.
Дано — в функциональном языке сами функции и алгребраические типы идут вразрез с платформой.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Э, а что за зверь такой — "правила вызова"? Неужели ты опять про скобочки?
Ага. Точнее синтаксис вызова методов. При нем карринг становится бессмысленным.
ВВ>В F# тоже кстати можно убрать это разделение — выкинуть из языка каррирование как класс. И тогда можно будет говорить — "разделения нет". Это, видимо, ваш путь.
В F# и так жопа, так как карринг не применим к методам. Если из него убрать и карринг (не добавив частичного применения), то вообще не ясно что от языка останется.
VD>>Единственное что есть — это принцип перекрытия имен введенных с помощью def. VD>>Но это просто калька с МЛ-я. Ничто не мешало ввести перегрузку для локальных функций. Алгоритм вывода типов это спокойно потянул бы. VD>>Короче, суть я описал здесь
.
ВВ>"Ничто не мешало"? Или же все-таки что-то помешало?
Ничего ровным счетом. Поверь человеку который довел алгоритм разрешение перегрузки до ума.
ВВ>Ты бы хоть Москаля спросил, почему они перегрузку не сделали.
Спроси.
ВВ>Даю хинт — первоклассная функция это такая, которую можно присвоить переменной.
Спасибо, дядя! Ты мне просто таки глаза открыл! Я то раньше был в не ведении!
Ну, раз уж ты открыл нам всем глаза на этот неочевидный факт, то может до кучи объяснишь нам невеждам, как этот факт влияет на наличие или отсутствие "принципа перекрытия имен введенных с помощью def"?
ВВ>Я вообще не любитель в футбол словами играть. Не видишь — ради бога. Он правда от этого никуда не денется.
Это ты ты не любитель? А чем ты тут (и в других форумах) занимаемый то?
Спроси любого и тебе скажут, что Воронков — это такой флудер который влезает во все окружающие споры ради спортивного интереса.
Так что не надо. Ты лучше потрудись обосновывать свои утверждения. А то наклеиваешь ярлыки и потом что-то пытаешься кому-то доказать используя эти ярлыки как аксиомы.
ВВ>>>А он и так разный. Есть там каррирование, нет там каррирования. VD>>Синтаксис вызова функций в Немерле один — сишный.
ВВ>Повторяю в сотый раз — причем тут синтаксис?
Повторю сто раз. Синтаксис влияет на возможность применения перегрузки и карринга. А вот поведение def-а никак и не разу. Будь оно другим, ничего бы не изменилось.
ВВ>>>Влад, ты меня извини, это все такой же bullshit VD>>Не извиню. Ты мало того что бредишь, так еще и попытку тебе что-то объяснить дерьмом называешь.
ВВ>Что ты мне пытался объяснить? Ты сказал, что не знаешь, что означает, что параметры функции описываются как кортеж. Если не знаешь, я могу тебе сказать. Это ничего не означает. Это просто бред. Который был придуман, чтобы "правила вызова" локальных функций были похожи на "правила вызова" функций-членов. Не надо вестись на это.
Я вообще не понял твоих рассуждений о моем незнании. Но я не намерен общаться с теми кто называет мои слова собачим дерьмо.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, WolfHound, Вы писали:
ВВ>>Круто вы, конечно. Если это "говнопорт", зачем смотреть на этот язык и фишку оттуда перенимать? WH>Смотрю я на все. Иначе не понять что из себя язык представляет. WH>А что касается фишек то иногда случаются хорошие фишки посреди груды говна. ВВ>>Где-то у вас несоответствие. WH>В твоем воображении.
Ну да точно. Видимо, мне одному кажется немного странным вытаскивание из F# самых его стремных "экспериментальных" фич на фоне параллельного признания "говнопортом" проверенных решений из языков ML-семейства, которыми действительно пользуются люди. Ну что ж, бывает, показалось. Воображение у меня, наверное, хорошее. Вы главное продолжайте. Что там следующее по списку? Актив паттерны?
ВВ>"Ничто не мешало"? Или же все-таки что-то помешало? Ты бы хоть Москаля спросил, почему они перегрузку не сделали. Даю хинт — первоклассная функция это такая, которую можно присвоить переменной.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Какая еще перегрузка? Я тебя спросил про синтаксис. Ты мне про перегрузку. ВВ>Разговор о каррировании как всегда начинается с "с Сишным синтаксисом несовместимо". Тебя заклинило что ли на этом синтаксисе?
Это тебя заклинило. Не хочешь понимать того что тебе объясняют, не надо. Это твои проблемы. Я не подписывался тебе что-то разжевывать.
Слова lomeo на тебя тоже не возымели действия.
Если кто-то "имеет позиции хрен оспоришь", то объяснить ему что-то физически невозможно.
ЗЫ
Если желание понять у тебя все же есть, то вот пример в тему.
У нас может быть функция A -> (B -> C) и функция (A * B) -> C:
F(a : A) : B -> C
{
...
}
F(a : A, b : B) -> C
{
...
}
Попытайся подумать как, при наличии карринга, рассматривать следующий вызов:
F(A())
?
Это частичное применение? Или это вызов первой перегрузки?
Другими словами как мы можем отличить факт частичного применения от факта вызова?
В F# все очень просто. В нем функции делятся на функции поддерживающие карринг, но не поддерживающие перегрузку. И на функции поддерживающие перегрузку, но не поддерживающие карринг.
В Немерле тоже все очень просто. Есть синтаксис вызова фукнции — применение скобок в условиях отсутствия плэйсхолдеров (символа "_") в параметре. И синтаксис частичного применения при котором в некоторые из параметров передаются плэйсходеры.
А что предлагаешь ты?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
ВВ>>Э, а что за зверь такой — "правила вызова"? Неужели ты опять про скобочки? VD>Ага. Точнее синтаксис вызова методов. При нем карринг становится бессмысленным.
Ты это можешь как-то объяснить? Или это просто догма, которую ты вбил себе в голову? Явное каррирование реализуется на любом языке с замыканиями, хоть на C#. С первоклассным каррированием я тоже проблем не вижу. Показать тебе первоклассное каррирование в языке с Си-подобным синтаксисом?
ВВ>>В F# тоже кстати можно убрать это разделение — выкинуть из языка каррирование как класс. И тогда можно будет говорить — "разделения нет". Это, видимо, ваш путь. VD>В F# и так жопа, так как карринг не применим к методам. Если из него убрать и карринг (не добавив частичного применения), то вообще не ясно что от языка останется.
Останется все остальное. Но вопрос не в том, что останется. Вопрос в том, чего НЕ останется. А не останется как раз того самого "дуализма", о котором ты говоришь.
ВВ>>"Ничто не мешало"? Или же все-таки что-то помешало? VD>Ничего ровным счетом. Поверь человеку который довел алгоритм разрешение перегрузки до ума. ВВ>>Ты бы хоть Москаля спросил, почему они перегрузку не сделали. VD>Спроси. ВВ>>Даю хинт — первоклассная функция это такая, которую можно присвоить переменной. VD>Спасибо, дядя! Ты мне просто таки глаза открыл! Я то раньше был в не ведении!
Так не наводит сей факт ни на какие мысли? Если сделать особую диспетчеризацию вызова для def-объявлений, то они тут же перестанут быть биндингом переменных. Получится та же петрушка, что и с мембер-функциями. А что останется? Останутся первоклассные функции:
def sum = fun(x, y) { x + y }
А теперь внимание. Правила вызова этих самых функций будут отличаться от правил вызова всех других функций. Упс, "дуализм"
VD>Ну, раз уж ты открыл нам всем глаза на этот неочевидный факт, то может до кучи объяснишь нам невеждам, как этот факт влияет на наличие или отсутствие "принципа перекрытия имен введенных с помощью def"? ВВ>>Я вообще не любитель в футбол словами играть. Не видишь — ради бога. Он правда от этого никуда не денется. VD> Это ты ты не любитель? А чем ты тут (и в других форумах) занимаемый то? VD>Спроси любого и тебе скажут, что Воронков — это такой флудер который влезает во все окружающие споры ради спортивного интереса.
Ну и что? Я здесь не так уж и известен. А если спросить "любого", кто такой Влад ака "Розовый слоник" — как думаешь, что они ответят? Сдается мне, что у тебя-то как раз имидж куда более одиозный. При этом повторюсь — ну и что? Я же с тобой не общаюсь в таком ключе. И это никак не отменяет того факта, что в футбол словами я играть не люблю.
ВВ>>Повторяю в сотый раз — причем тут синтаксис? VD>Повторю сто раз. Синтаксис влияет на возможность применения перегрузки и карринга. А вот поведение def-а никак и не разу. Будь оно другим, ничего бы не изменилось.
Давай начнем издалека. Что ты понимаешь под "синтаксисом"?
ВВ>>Что ты мне пытался объяснить? Ты сказал, что не знаешь, что означает, что параметры функции описываются как кортеж. Если не знаешь, я могу тебе сказать. Это ничего не означает. Это просто бред. Который был придуман, чтобы "правила вызова" локальных функций были похожи на "правила вызова" функций-членов. Не надо вестись на это. VD>Я вообще не понял твоих рассуждений о моем незнании. Но я не намерен общаться с теми кто называет мои слова собачим дерьмо.
Во-первых, не собачьим, а коровьим.
Во-вторых, я *твои* слова никаким дерьмом не называл. От тебя я как раз никакого объяснения о "кортежности" функций не услышал. А данный тезис встречается в статьях о Немерле на английском, которые явно писал не ты. Мир?
Здравствуйте, kkolyan, Вы писали:
VD>>Еще раз повторюсь, что материалов для освоения выше крыши. Людей которые освоили немрел так же порядочно. Причем многие освоили его прочитав одну статью или даже поигравшись с ним недельку.
K>120 человек выше крыши? f# думаю на порядок больше освоило
Я не знаю с какого потолка взята цифры, но я точно знаю что нет никакой разницы между цифрой 10 и 1000000 в данном аспекте.
Если есть хотя бы 10 человек легко освоивших язык по имеющимся материалам, то апелляция одного человека к недостаточности материалов для освоения выглядит мягко говоря натянутой.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А что предлагаешь ты?
Влад, я предлагаю называть вещи своими именами.
Есть синтаксис.
Есть перегрузка.
Есть языки с Си-подобным синтаксисом, в которых есть перегрузка.
Есть языки с Си-подобным синтаксисом, в которых НЕТ перегрузки. Синтаксис от этого не перестает быть Си-подобным.
Я не умею читать мысли, я не могу догадаться о том, что ты подразумеваешь, когда говоришь "синтаксис". Когда я начинаю в подобном ключе общаться, меня не понимает вообще никто.
Да, и сейчас по факту для локальных функций перегрузки нет. И я вправе рассматривать запись вида:
def sum(x, y) { x + y }
Как аналогичную:
def sum = fun(x, y) { x + y }
Если ввести перегрузку — они равнозначность потеряют. Но не в этом дело. Сейчас ничто, кроме распаковки кортежей *принципиально* не мешает сделать карринг.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Да, и сейчас по факту для локальных функций перегрузки нет. И я вправе рассматривать запись вида:
ВВ>def sum(x, y) { x + y }
ВВ>Как аналогичную:
ВВ>def sum = fun(x, y) { x + y }
ВВ>Если ввести перегрузку — они равнозначность потеряют.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>>>Какое именно из утверждений? VD>>"Каррирование нужно для частичного применения" VD>>Оно не нужно. Оно одна из возможных реализаций.
ВВ>Ага. Автомобиль нужен для передвижения. Передвигаться можно и пешком. Вывод — утверждение об автомобиле является ложным.
Не поверю, что у тебя столь серьезные проблемы с логическим выводом. Это же за гранью фола. Так что кончай троллить.
Если это так на самом деле, то советую почитать учебники по логике.
Итак. Утверждения "Автомобиль нужен для передвижения." и "Каррирование нужно для частичного применения" ложны так как они слишком широкие.
Автомобиль не нужен для передвижения, так как передвигаться можно и без автомобиля. Автомобиль может применяться для передвижения. Он позволяет ускорить передвижение или увеличить массу передвигаемого груза.
Точно так же карринг не требуется для частичного применения. Для частичного применения есть и другие решения. Но, конечно же, карринг может использоваться в качестве механизма лежащего в основе частичного применения.
Если карринг нам нужен только для реализации частичного примерения, а частичное применение может быть реализовано другими методами, то не трудно сделать простой логический вывод о том, что каррин не является необходимым в языке. Так что для введения карринга нам требуются более весомые предпосылки. Кроме того карринг не может существовать в вакууме. Для его использования нужны синтаксические и семантические решения. Таковые решения принятие в F# конфликтуют с другими решениями которые хочется принять, а именно с перегрузкой и испоьзованием сишного синтаксиса вызова методов.
ВВ>Я понял. При общении с тобой надо переходить на специальный язык.
Не ты не понял. Твое общение со мной постоянно приводит к тому, что у меня появляется ощущение бесцельно потраченного времени. От этого я не нашутку раздражаюсь. Посему нам или нужно перестать общаться (вообще), или все же быть более конструктивными и не применять детский демакогических приемов вроде аналогий с автомобилями.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, WolfHound, Вы писали:
L>>Повторю — если оставить отмеченную тобой производительность, то это неявность создания замыкания, которая вступает в конфликт с перегрузкой функции по кол-ву аргументов. WH>В принципе алгоритм вывода типов который я думаю должен позволить такой финт ушами. WH>Вопрос лишь в том не приведет ли это решение к проблемам. WH>Что точно так это будет некоторая потеря производительности из-за того что придется переберать больше вариантов. WH>Так что тут вопрос скорее политический чем технический.
Да, я понимаю, можем же мы в систему уравнений дописать typeof(sum1) | typeof(sum2) | typeof(sum3) для переменной, которой присваиваем перегруженную функцию. И при использовании переменной с этим типом решить оконачательно какой именно выбираем. Если по завершении вывода тип не выбран — то ошибка с type ambiguity.
С другой стороны как далеко за пределы функции выводить тип? Хотя, если в Nemerle вывод типов только в пределах функции и её локальных функций, то всё должно получиться.
А какие сложности ты видишь, кроме очевидного перебора вариантов?
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Дано — функциональный язык. ВВ>Дано — платформа, на которой построен этот функциональный язык.
Пока все логично.
ВВ>Дано — в функциональном языке сами функции и алгребраические типы идут вразрез с платформой.
А вот это не верный вывод. Все же у тебя и правд не все ОК с логическим выводом.
То что платформа не предоставляет примитивов для представления некоторых фич языке еще не означает, что фичи идут в разрез с платформой.
Скорее это говорит о недоработках в платформе.
Если ты хочешь пофилософствовать по поводу платформы, то могу высказать свои (крамольные для многих) мысли.
Я считаю, что ошибочно было вводить в платформу классы (и особенно их наследование). Достаточно было ввести типы разделив их на ссылочные и значений.
Далее ошибкой было введение делегатов. Вместо этого лучше было бы ввести в платформу ссылку на функцию и понятие замыкания. Это действительно базовые вещи требующие абстрагирования.
ВВ>Вывод — ну подумаешь, фигня, раз-два и обчелся.
А выводы сделанные на неверных предположениях или с ошибками никому не нужны. Это в лучшем случае пустая трата времени, а в худшем — форменное вредительство.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
ВВ>>Ага. Автомобиль нужен для передвижения. Передвигаться можно и пешком. Вывод — утверждение об автомобиле является ложным.
VD>Не поверю, что у тебя столь серьезные проблемы с логическим выводом. Это же за гранью фола. Так что кончай троллить. VD>Если это так на самом деле, то советую почитать учебники по логике.
Тут не в логике дело. Просто вы эту фразу по-разному читате:
Вот твоя трактовка:
- Что нужно для частичного применеия?
— Каррирование.
Очевидно, это неверное утверждение.
А вот что имел в виду твой собеседник:
- Для чего нужно каррирование? Какого его предназначение?
— Для частичного применения.
Здравствуйте, hardcase, Вы писали:
ВВ>>Да, и сейчас по факту для локальных функций перегрузки нет. И я вправе рассматривать запись вида: ВВ>>def sum(x, y) { x + y } ВВ>>Как аналогичную: ВВ>>def sum = fun(x, y) { x + y } ВВ>>Если ввести перегрузку — они равнозначность потеряют. H>Они не равнозначны.
Приведешь пример, из которого будет видна их неравнозначность?
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Ты это можешь как-то объяснить? Или это просто догма, которую ты вбил себе в голову?
Да, конечно. Но при условии, что тот кто слушает объяснение исходит и правильных предпосылок и правильно понимает исходные термины.
ВВ>Явное каррирование реализуется на любом языке с замыканиями, хоть на C#.
Я и раньше подозревал, но теперь окончательно понял, что ты неверно понимаешь термин карриннг. Возможно тебя сбивает с верного хода мыслей дурацкий русский перевод, что ты используешь — "каррирование".
Карринг — это не процесс, а фича.
Если проанализировать цитату выше, то становится очевидно, что это бред.
Итак. Я последний раз даю правильно определение термину карринг (он же каррирование). Карринг это способность представлять функцию типа (A * B) -> C, как функцию A -> (B -> C). Можно (и даже нужно) сказать даже не "представлять", а считать эквивалентными данные представления.
Исходя из этого ни в C#, ни в Nemerle карринг не поддерживается, так как (A * B) -> C в них всегда означает (A * B) -> C и ни что другое.
Как я понял, ты понимаешь под каррингом просто трансформацию одних функций в другие, которые к слову не обязательно делать только лишь с помощью лямбд (хотя с их помощью, конечно, тоже можно делать).
ВВ>С первоклассным каррированием я тоже проблем не вижу. Показать тебе первоклассное каррирование в языке с Си-подобным синтаксисом?
Термин "первоклассное каррирование" — это еще одна твоя выдумка.
Лучше применять намного более простую терминологию.
Можно ввести понятие преобразования функций. Тогда частично применение, карринг и даже замыкания (Заметь! Замыкания, а не лямбды.) можно определить как преобразование функций позволяющие создавать новые функции.
Так вот если заменить твои слова о лямбдах на замыкания, то конечно же верным будет утверждение, что эффект достигаемый как каррингом, так и частичным применением всегда можно добиться с использованием замыканий.
Таким образом карринг и частичное применение немерла есть не что иное как различные синтаксические и/или семантически реализации шорткатов для манипуляции функциями.
Если же принять за верное твое утверждение о том, что карринг — это и есть само преобразование функций, то придется признать, что карринг есть и Немреле, и даже в Шарпе. Что бессмысленно в контексте данного разговора.
Так вот как бы ты не называел карринг "первоклассным каррированием" или еще как-то. Но эта хрень не вписывается в концепции языка поддерживающего перегрузку и сишный способ вызова функций. Конечно в каком-то виде всегда можно прилепить к языку что угодно, но при этом вылезут проблемы в других местах.
Так что таки, ДА, в языках синтаксис и семантика тесно связанны. Семантические решения определяют синтаксические и на оборот. Если бы это было не так, то разницы между языками практически не было бы.
ВВ>
ВВ>def sum = fun(x, y) { x + y }
ВВ>
ВВ>А теперь внимание. Правила вызова этих самых функций будут отличаться от правил вызова всех других функций.
Нет, не отличаются. Правила вызова просты и однозначны. Выражение к которому применены скобки с параметрами является вызовом, если среди параметров нет плэйсхолдеров. Не больше, не меньше.
ВВ>Упс, "дуализм"
Тебе показалось.
VD>>Ну, раз уж ты открыл нам всем глаза на этот неочевидный факт, то может до кучи объяснишь нам невеждам, как этот факт влияет на наличие или отсутствие "принципа перекрытия имен введенных с помощью def"?
Игнорирование данного предложения засчитываю за слив.
ВВ>Во-первых, не собачьим, а коровьим.
Ага. Сейчас я с тобой и по этому поводу поспорю. Это же совершенно меняет дело! Погоди чуть чуть...
ЗЫ
Меня сильно утомило разжевывание свои мыслей до битов и пустая философия которой приходится заниматься. По сему я пожалуй воздержусь от ее развития. Я и так слишком много времени убил на этот бесполезный треп.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Да, и сейчас по факту для локальных функций перегрузки нет. И я вправе рассматривать запись вида:
ВВ>def sum(x, y) { x + y }
ВВ>Как аналогичную:
ВВ>def sum = fun(x, y) { x + y }
ВВ>Если ввести перегрузку — они равнозначность потеряют.
демонстрацию того, что описанных тобой проблем не появляется. Мощный алгоритм вывода типов разрулит эти проблемы.
ВВ>Но не в этом дело. Сейчас ничто, кроме распаковки кортежей *принципиально* не мешает сделать карринг.
Сейчас у нас есть единый механизм интерпретации синтаксиса вызова и единый тип функции — функция.
Если же ввести карринг для локальных функций, то мы утратим эти единые механизмы и получит тот самый дуализм, что сейчас есть в F# и который очень сильно портит этот язык.
Кроме того нужно понять ради чего вводить в язык этот самый карринг? Что мы получим взамен усложнению языка (и его компилятора)? За что мы платим манипуляции функциями? Да она у нас была с самого начала. В немреле есть частичное применение и те самые замыкания которые позволяют добиться всего чего можно добиться с помощью карринга.
Так на хрен нужно портить язык не получая в замен никаких ощутимых преимуществ?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А объединить две функции можно и в немреле. Все операции над функциями в нем доступны.
Я понимаю, что можно. Но, к сожалению, так писать на Nemerle нехорошо — нет элиминации промежуточных структур.
VD>Проблема с твои кода в другом. Не смотря на компактность читать его сильно сложнее. Для его чтения нужно долго и упорно упражняться в том самом комбинировании функций. И если тебе этот код будет понятен, то многим другим прграммистам не очень.
Я знаю и меня это огорчает На самом деле это поразительный факт — код с функциями и данными вперемешку понятнее кода с функциями.
saving = 0
for employee in staff
if employee.isFired
saving += employee.salary
return saving
понятнее чем
(sum . map salary . filter isFired) staff
Но это было бы не так интересно, если бы у комбинаторного кода не было других преимуществ помимо краткости. Но ведь ещё код получается модульным сам собой, в то время как для того, чтобы не сделать код, обрабатывающий данные явно, лапшой необходимо прилагать усилия. Это как одно из условий выразительности. Плюс equational reasoning — очень полезная техника — гораздо проще применять на комбинаторном коде.
Я тут хотел написать пару примеров, но заметил, что уже долго пищу это сообщение, поэтому пока закончу
VD>А выиграл ты пару строк.
Да не в строках дело, хоть я и написал "ужал" — это было пустое бахвальство. И сейчас и тогда я говорил о возможности работать с кусками программы на качественно другом уровне. У WH код монолитен — вся логика размазана по матчингу. Комбинаторный код позволяет чётко выделять подзадачи. Видно что в какой последовательности делается. Следовательно, мы можем брать эти куски и работать с ними, что я и демонстрировал — из первоначального описания простой подстановкой я получил эффективный и понятный код. Как минимум это приятно — подвигать куски только что написанного алгоритма и получить его в более понятной форме.
VD>Собственно от темы мы отделились уже конкретно.
Да фигня
VD>Если принять за аксиому принцип "чудес не бывает", то приходится признать, что карринг идет в разрез с перегрузкой. А раз так, то приходится делать выбор. В F# сделали выбор в пользу дуализма и карринга, в немерле в пользу перегрузки и стройности языка. На мой взгляд последний последний выбор оправдан.
Мне тоже нравится, но ты мне уже показывал давным-давно, что карринг и плейсхолдер примерно равны — у обоих свои преимущества и недостатки. А поскольку функционал у них схож, в одном языке иметь и то и то большого смысла не вижу. Особенно если учесть, что карринг можно замечательно сделать руками.
Здравствуйте, Lloyd, Вы писали:
L>Тут не в логике дело. Просто вы эту фразу по-разному читате:
L>Вот твоя трактовка: L>
L>- Что нужно для частичного применеия?
L>- Каррирование.
L>Очевидно, это неверное утверждение.
L>А вот что имел в виду твой собеседник: L>
L>- Для чего нужно каррирование? Какого его предназначение?
L>- Для частичного применения.
Я глубоко извиняюсь, но вот эта фраза:
Каррирование нужно для частичного применения.
Как ее можно интерпретировать иначе?
Еще раз почеркну, что в Немерле ЕСТЬ ЧАСТИЧНОЕ ПРИМЕНЕНИЕ. Так зачем в Немреле нужно еще одна фича которая предоставит ему возможность которая и так уже есть в языке?
Так же нужно еще понимать, что каррирование (как это сделано в F#) очень плохо воспринимается большей частью дттнетчиков (читай C#/VB-программистов) и зачастую приводит к вывиху мозга.
Так зачем же добавлять столь спорное решение в язык где и без него все очень даже зашибись?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
ВВ>>Явное каррирование реализуется на любом языке с замыканиями, хоть на C#. VD>Я и раньше подозревал, но теперь окончательно понял, что ты неверно понимаешь термин карриннг. Возможно тебя сбивает с верного хода мыслей дурацкий русский перевод, что ты используешь — "каррирование". VD>Карринг — это не процесс, а фича.
Карринг — это преобразование функции одного вида в функцию другого вида. Это не фича. Просто в некоторых языках функции уже каррированные.
VD>Если проанализировать цитату выше, то становится очевидно, что это бред. VD>Итак. Я последний раз даю правильно определение термину карринг (он же каррирование). Карринг это способность представлять функцию типа (A * B) -> C, как функцию A -> (B -> C). Можно (и даже нужно) сказать даже не "представлять", а считать эквивалентными данные представления. VD>Исходя из этого ни в C#, ни в Nemerle карринг не поддерживается, так как (A * B) -> C в них всегда означает (A * B) -> C и ни что другое.
Вот это вот "считать эквивалентными данные представления" — уже твоя отсебятина. Каррирование — это *преобразование* функции вида (a,b) -> c в функции вида a->b->c. Это преобразование можно реализовать в явном виде — например, в виде библиотечной функции — в любом языке, где поддерживаются замыкания. В Скале так и сделано, например. Просто библиотечная функция.
В некоторых языках — т.е., насколько я знаю во всех языках семейства ML, — операции "каррирования" попросту нет, посколько все функции уже каррированы, т.е. имеют вид a->b->c. Именно это я называю первоклассным каррингом. Термин, кажется, не я придумал.
VD>Как я понял, ты понимаешь под каррингом просто трансформацию одних функций в другие, которые к слову не обязательно делать только лишь с помощью лямбд (хотя с их помощью, конечно, тоже можно делать).
Если под "трансформацией одних функций в другие" ты имеешь в виду преобразование функции вида (a,b)->c в функцию вида a->b->c, то именно это я под каррированием и понимаю. И именно это и является каррированием.
VD>Если же принять за верное твое утверждение о том, что карринг — это и есть само преобразование функций, то придется признать, что карринг есть и Немреле, и даже в Шарпе. Что бессмысленно в контексте данного разговора.
Да, это так и есть. Каррирование можно реализовать и в Немерле, и в Шарпе. Это действительно так. Именно так каррирование и реализовано в Скала.
В данном разговоре имелось в виду "сделать как в F#", где все функции уже каррированы, т.е. их сигнатура имеет вид a->b->c и, соответственно, никакое преобразование не требуется.
VD>Так вот как бы ты не называел карринг "первоклассным каррированием" или еще как-то. Но эта хрень не вписывается в концепции языка поддерживающего перегрузку и сишный способ вызова функций. Конечно в каком-то виде всегда можно прилепить к языку что угодно, но при этом вылезут проблемы в других местах.
Перегрузка с каррированием не дружит, это факт. Но перегрузки и нет для локальных функций, о которых был разговор.
Что такое "сишный способ вызова функций" я не понимаю. Это уже какой-то новый термин от тебя.
VD>Так что таки, ДА, в языках синтаксис и семантика тесно связанны. Семантические решения определяют синтаксические и на оборот. Если бы это было не так, то разницы между языками практически не было бы.
Ага, ничего, что в том самом Си, к синтаксису которого ты постоянно аппелируешь, никакой перегрузки функций нет?
VD>Нет, не отличаются. Правила вызова просты и однозначны. Выражение к которому применены скобки с параметрами является вызовом, если среди параметров нет плэйсхолдеров. Не больше, не меньше. ВВ>>Упс, "дуализм" VD>Тебе показалось.
Ты меня, честно, утомил уже. Правила вызова перегруженной функции и правила вызова функции-значения у тебя одинаковые? Одинаковые потому что там, и там "скобки с параметрами"?
И этот человек объясняет мне, что такое каррирование.
VD>>>Ну, раз уж ты открыл нам всем глаза на этот неочевидный факт, то может до кучи объяснишь нам невеждам, как этот факт влияет на наличие или отсутствие "принципа перекрытия имен введенных с помощью def"? VD>Игнорирование данного предложения засчитываю за слив.
Что еще за принцип перекрытия имен введенных с помощью def? Затенение переменных что ли?
Или ты про локальные функции? Я вообще-то тебе объяснял это в предыдущем сообщении. Разрешишь в них перегрузку — они перестанут быть первоклассными значениями по определению. Останутся анонимные функции. Все, что до этого говорилось в отношении локальных функций, будет справедливо для анонимных. Все, ты ничего в сущности не поменял.
VD>Меня сильно утомило разжевывание свои мыслей до битов и пустая философия которой приходится заниматься. По сему я пожалуй воздержусь от ее развития. Я и так слишком много времени убил на этот бесполезный треп.
Ага. Вот только сам его и начал. Особенно меня порадовала дискуссия с тобой на тему многогранного значения такого сложного слова русского языка как "нужен".
демонстрацию того, что описанных тобой проблем не появляется. Мощный алгоритм вывода типов разрулит эти проблемы.
Какое отношение имеет твоя демонстрация к этому? Сейчас объявление def sum(x, y) { x + y } — это первоклассная функция. Введешь перегрузку — она не будет первоклассной функцией. Мощный вывод типов — ну, видимо, разрулит, да. Останутся по-прежнему функции вида def sum = fun(x, y) { x + y }, для которых перегрузка это нонсенс.
ВВ>>Но не в этом дело. Сейчас ничто, кроме распаковки кортежей *принципиально* не мешает сделать карринг. VD>Сейчас у нас есть единый механизм интерпретации синтаксиса вызова и единый тип функции — функция.
Ах, вот что тебя беспокоит-то. Ну и что? Будет разный "механизм интерпретации синтаксиса вызова". (Заметь, как хорошо — сейчас ты наконец сказал правильные слова. Не "правила вызова", которых даже в C# вагон и маленькая тележка, а разный "механизм интерпретации синтаксиса вызова"). Ну так, собственно, какая проблема в том, что будут, так сказать, два таких механизма? Почему это должно портить язык?
А единый тип "функция" как был, так и останется.
VD>Если же ввести карринг для локальных функций, то мы утратим эти единые механизмы и получит тот самый дуализм, что сейчас есть в F# и который очень сильно портит этот язык.
VD>Кроме того нужно понять ради чего вводить в язык этот самый карринг? Что мы получим взамен усложнению языка (и его компилятора)? За что мы платим манипуляции функциями? Да она у нас была с самого начала. В немреле есть частичное применение и те самые замыкания которые позволяют добиться всего чего можно добиться с помощью карринга. VD>Так на хрен нужно портить язык не получая в замен никаких ощутимых преимуществ?
Ты знаешь, так вообще вопрос не стоял, собственно. Я высказал мысль, кстати, абсолютно верную, что в Немерле, вместо распаковки кортежей, можно все локальные функции сделать каррированными, т.е. имеющими сигнатуру a->b->c. Я сам раньше считал, что каррирование не столь нужно, если есть другие механизмы для частичного применения, но попробовав реально пописать на языке с каррированием, понял, что это просто удобно. Собственно, я и сам склонялся к тому, что на Немерле это может оказаться менее полезным, чем в F#, где есть большая библиотека, представленная в виде каррированных функций. Все. Потом пришел ты и вылил на меня ушат дерьма, в очередной раз доказывая, что каррирование "не совместимо с Сишным синтаксисом". А в итоге я еще и оказался "флудерастом", который спорит ради спортивного интереса.
Такова обстановочка в "официальном представительстве" Немерле.
Вы еще удивляетесь, что народ к вам толпами не валит? Причем мне-то по фиг, я тебя давно знаю, собственно, ничего другого от тебя и не ожидаю. А вот люди с более нежной психикой могут и не выдержать.
Здравствуйте, lomeo, Вы писали:
L>Я понимаю, что можно. Но, к сожалению, так писать на Nemerle нехорошо — нет элиминации промежуточных структур.
Это вопрос оптимизации в компиляторе, а не языкового дизайна. Не стоит их смешивать!
В F#, между прочем, тоже "нет элиминации промежуточных структур".
Я тебе по секрету скажу, что только компилятор Хаскля и дошел до таких вершин оптимизации. Но раз дошел он, то потенциально все могут дойти.
А в Немерле или F#, в случае необходимости можно просто перейти на императивный стиль и отказаться от применения ФВП.
VD>>Проблема с твои кода в другом. Не смотря на компактность читать его сильно сложнее. Для его чтения нужно долго и упорно упражняться в том самом комбинировании функций. И если тебе этот код будет понятен, то многим другим прграммистам не очень.
L>Я знаю и меня это огорчает На самом деле это поразительный факт — код с функциями и данными вперемешку понятнее кода с функциями. L>
L>saving = 0
L>for employee in staff
L> if employee.isFired
L> saving += employee.salary
L>return saving
L>
L>понятнее чем L>
L>(sum . map salary . filter isFired) staff
L>
+1
Возможно это потому, что имена параметров/переменных/полей многое говорят о происходящем. Т.е. получается меньше подразумеваемых тонкосей.
Но, как говорится, не все потеряно.
Можно же найти золотую середину. Ну, что-то вроде:
L>Но это было бы не так интересно, если бы у комбинаторного кода не было других преимуществ помимо краткости. Но ведь ещё код получается модульным сам собой, в то время как для того, чтобы не сделать код, обрабатывающий данные явно, лапшой необходимо прилагать усилия. Это как одно из условий выразительности.
Модульности? Тут я что-то не догоняю. Может быть обобщенности?
Что под этим имелось в виду?
L>Плюс equational reasoning — очень полезная техника — гораздо проще применять на комбинаторном коде.
С этим не знаком.
L>Да не в строках дело, хоть я и написал "ужал" — это было пустое бахвальство. И сейчас и тогда я говорил о возможности работать с кусками программы на качественно другом уровне. У WH код монолитен — вся логика размазана по матчингу. Комбинаторный код позволяет чётко выделять подзадачи. Видно что в какой последовательности делается. Следовательно, мы можем брать эти куски и работать с ними, что я и демонстрировал — из первоначального описания простой подстановкой я получил эффективный и понятный код. Как минимум это приятно — подвигать куски только что написанного алгоритма и получить его в более понятной форме.
Откровенно говоря лично мне важно быстро понимать что код делает. И код Вольфхаунда я понимаю без напряга, а твой... откровенно говоря даже не возьмусь сказать, что вообще понимаю. Мне нужно совершать столько "обратных преобразований функций", что найти ошибку я вряд ли смогу в таком коде.
L>Мне тоже нравится, но ты мне уже показывал давным-давно, что карринг и плейсхолдер примерно равны — у обоих свои преимущества и недостатки.
Так и есть. Только постоянно находятся войны которым надо это доказывать вновь и вновь. Причем Воронков то как раз о частичном применении знает не плохо, так как реализовал похожую фичу для своего языка Ела. Так что вообще не ясно что он торолит.
L>А поскольку функционал у них схож, в одном языке иметь и то и то большого смысла не вижу. Особенно если учесть, что карринг можно замечательно сделать руками.
+1
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Я устал, так что отвечаю на последнее сообщение (кратенько).
ВВ>Какое отношение имеет твоя демонстрация к этому? Сейчас объявление def sum(x, y) { x + y } — это первоклассная функция. Введешь перегрузку — она не будет первоклассной функцией. Мощный вывод типов — ну, видимо, разрулит, да. Останутся по-прежнему функции вида def sum = fun(x, y) { x + y }, для которых перегрузка это нонсенс.
Сейчас "def sum(x, y) { x + y }" не является первоклассной функцией, а является объявлением локальной функции.
Если под первоклассностью понимается возможность передать ссылку на функцию (или саму функцию, если так удобнее выражаться), то она осуществляется почти как в С — путем оперирования с именем функции. Например, чтобы получить аналог лямбды "(x, y) => x + y" нужно написать такой код:
{ def sum(x, y) { x + y }; sum }
Именно это и делает компилятор когда встречает лямбду.
Перегрузке это нисколечко не мешает, так как фактическая функция без проблем может определяться по сочетанию имени и типа функции.
Потенциально нет ни малейших проблем сделать так, чтобы следующий код компилировался и работал:
def func(x) { x * x }
def func(x, y) { x + y }
WriteLine(func(2));
WriteLine(func(3, 4));
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Карринг — это не процесс, а фича.
VD>Если проанализировать цитату выше, то становится очевидно, что это бред. VD>Итак. Я последний раз даю правильно определение термину карринг (он же каррирование). Карринг это способность представлять функцию типа (A * B) -> C, как функцию A -> (B -> C). Можно (и даже нужно) сказать даже не "представлять", а считать эквивалентными данные представления.
VD>Исходя из этого ни в C#, ни в Nemerle карринг не поддерживается, так как (A * B) -> C в них всегда означает (A * B) -> C и ни что другое.
Исходя из этого ни F#, ни даже Haskell, не поддерживают карринг.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, hardcase, Вы писали:
ВВ>>>Да, и сейчас по факту для локальных функций перегрузки нет. И я вправе рассматривать запись вида: ВВ>>>def sum(x, y) { x + y } ВВ>>>Как аналогичную: ВВ>>>def sum = fun(x, y) { x + y } ВВ>>>Если ввести перегрузку — они равнозначность потеряют. H>>Они не равнозначны.
ВВ>Приведешь пример, из которого будет видна их неравнозначность?
Здравствуйте, samius, Вы писали:
VD>>Если проанализировать цитату выше, то становится очевидно, что это бред. VD>>Итак. Я последний раз даю правильно определение термину карринг (он же каррирование). Карринг это способность представлять функцию типа (A * B) -> C, как функцию A -> (B -> C). Можно (и даже нужно) сказать даже не "представлять", а считать эквивалентными данные представления.
VD>>Исходя из этого ни в C#, ни в Nemerle карринг не поддерживается, так как (A * B) -> C в них всегда означает (A * B) -> C и ни что другое.
S>Исходя из этого ни F#, ни даже Haskell, не поддерживают карринг.
Как раз наоборот.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А тех кто ищет причины чтобы оправдать свою предвзятость, они всегда найдут то что им нужно. В этом ты не оригинален.
Ты забыл что я таки писал на nemerle, вернее пытался.
G>>Ну собственно и все, ни книг нету, ни в блога о nemerle не пишут и в реальных (необязательно коммерческих) проектах nemerle не найдешь.
VD>Еще раз повторюсь, что материалов для освоения выше крыши. Людей которые освоили немрел так же порядочно. Причем многие освоили его прочитав одну статью или даже поигравшись с ним недельку.
"Всех" как-то подозрительно мало.
VD>Практика показывает, что те люди которые применяли немерл в течении 1-2 месяцев в реальном проекте становятся его сторонниками.
И сколько тысяч таких?
Здравствуйте, gandjustas, Вы писали:
VD>>А тех кто ищет причины чтобы оправдать свою предвзятость, они всегда найдут то что им нужно. В этом ты не оригинален. G>Ты забыл что я таки писал на nemerle, вернее пытался.
Дык надо не стараться, а делать.
В общем, если есть желание разобраться — вешкам. Поможем с удовольствием.
Выбери себе задачу и реши ее на немреле. Попутно консультируйся на форуме или через скайп. Мой скайп-ID соответствует моему нику на РСДН.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Я знаю и меня это огорчает На самом деле это поразительный факт — код с функциями и данными вперемешку понятнее кода с функциями. L>
L>saving = 0
L>for employee in staff
L> if employee.isFired
L> saving += employee.salary
L>return saving
L>
L>понятнее чем L>
L>(sum . map salary . filter isFired) staff
L>
L>Но это было бы не так интересно, если бы у комбинаторного кода не было других преимуществ помимо краткости. Но ведь ещё код получается модульным сам собой, в то время как для того, чтобы не сделать код, обрабатывающий данные явно, лапшой необходимо прилагать усилия. Это как одно из условий выразительности. Плюс equational reasoning — очень полезная техника — гораздо проще применять на комбинаторном коде.
Это все потому что в haskell принята запись не очень человеческая. Люди читают слева направо, поэтому чтобы понятнее стало надо написать что-то вроде:
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, samius, Вы писали:
VD>>>Если проанализировать цитату выше, то становится очевидно, что это бред. VD>>>Итак. Я последний раз даю правильно определение термину карринг (он же каррирование). Карринг это способность представлять функцию типа (A * B) -> C, как функцию A -> (B -> C). Можно (и даже нужно) сказать даже не "представлять", а считать эквивалентными данные представления.
VD>>>Исходя из этого ни в C#, ни в Nemerle карринг не поддерживается, так как (A * B) -> C в них всегда означает (A * B) -> C и ни что другое.
S>>Исходя из этого ни F#, ни даже Haskell, не поддерживают карринг.
VD>Как раз наоборот.
Prelude> let addC a b = a + b
Prelude> :t addC
addC :: (Num a) => a -> a -> a
Prelude> let addC1 = addC 1
Prelude> :t addC1
addC1 :: Integer -> Integer
Prelude> let add (a,b) = a + b
Prelude> :t add
add :: (Num t) => (t, t) -> t
Prelude> let add1 = add 1
<interactive>:1:15:
No instance for (Num (t, t))
arising from the literal `1' at <interactive>:1:15
Здравствуйте, lomeo, Вы писали:
L>Да, я понимаю, можем же мы в систему уравнений дописать typeof(sum1) | typeof(sum2) | typeof(sum3) для переменной, которой присваиваем перегруженную функцию. И при использовании переменной с этим типом решить оконачательно какой именно выбираем. Если по завершении вывода тип не выбран — то ошибка с type ambiguity.
Примерно так. Если уж мы обрабатываем перегрузки то пара лишних не проблема.
L>С другой стороны как далеко за пределы функции выводить тип? Хотя, если в Nemerle вывод типов только в пределах функции и её локальных функций, то всё должно получиться.
С технической точки зрения это ограничение обосновано лишь замедлением вывода типов. Для текущего алгоритма это просто ужос.
Для нового алгоритма в режиме компиляции замедление будет не существенным. Хотя пока не напишу точно сказать трудно.
Но есть еще режим интелисенса где выводить типы во всей сборке при каждом изменении в любом случае будет накладно.
Плюс есть мнение что публичные интерфейсы нужно фиксировать явно.
И еще нужно не забыть про то что глобальный вывод типов хрен распаралеишь, а в случае с локальным можно типизировать разные функции в разных потоках.
L>А какие сложности ты видишь, кроме очевидного перебора вариантов?
Если делать карринг то придется делать перегрузку по возвращаемому значению. Сделать это можно но такая перегрузка сильно выбивается из соглашений .НЕТ.
Плюс появится неоднозначность вот в таком коде:
Foo(a : A, b : B) : C;
Foo(a : A) : B -> C;
...
Foo(a);
Без карринга все однозначно. С каррингом даже не понятно как явно указать какую функцию брать.
Хотя как вариант можно ввести правило разрешающее данный конфликт в пользу функции у которой откусили меньше аргументов.
В любом случае без понимания того что это приведет к существенному профиту эту фичу никто прикручивать не станет.
Профит от каррирования есть во всяких хаскелях где код пишут вот в таком стиле:
map foo $ map bar $ l
В немерле сигнатуры функций устроены иначе. У нас список идет первым аргументом и вызов идет через ".":
l.Map(bar).Map(foo)
Как следствие польза от карринга становится весьма сомнительной.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Но есть еще режим интелисенса где выводить типы во всей сборке при каждом изменении в любом случае будет накладно. WH>И еще нужно не забыть про то что глобальный вывод типов хрен распаралеишь, а в случае с локальным можно типизировать разные функции в разных потоках.
О, точно, спасибо, я про интеллисенс и распараллеливание даже не думал.
WH>Плюс есть мнение что публичные интерфейсы нужно фиксировать явно.
+1. Глобальный вывод не нужен.
С другой стороны — я нажимаю кнопку и тип хаскелевской функции у меня вставляется автоматом. Для интелисенса было бы полезно?
WH>Без карринга все однозначно. С каррингом даже не понятно как явно указать какую функцию брать. WH>Хотя как вариант можно ввести правило разрешающее данный конфликт в пользу функции у которой откусили меньше аргументов. WH>В любом случае без понимания того что это приведет к существенному профиту эту фичу никто прикручивать не станет.
Да хрен с ним с каррингом
WH>Как следствие польза от карринга становится весьма сомнительной.
+1. Карринг удобен для описания DSL-ей, например. В Nemerle для этого есть средства.
Здравствуйте, VladD2, Вы писали:
VD>В F#, между прочем, тоже "нет элиминации промежуточных структур".
М? И цепочка функций map/filter/foldr/etc порождает промежуточные списки?
VD>Это вопрос оптимизации в компиляторе, а не языкового дизайна. Не стоит их смешивать! VD>Я тебе по секрету скажу, что только компилятор Хаскля и дошел до таких вершин оптимизации. Но раз дошел он, то потенциально все могут дойти.
Мне кажется, что эта оптимизация сильно связана с тем, что язык чистый. Для нечистого языка написать подобное было бы гораздо сложнее.
VD>Возможно это потому, что имена параметров/переменных/полей многое говорят о происходящем. Т.е. получается меньше подразумеваемых тонкосей.
VD>saving = staff.Where(_.isFired).Sum(_.salary);
Смотри, что я имею в виду — вот для тебя лично этот код более понятен, чем явный цикл с явной проверкой и явным заведением и изменением переменной? Ведь это всё — детали реализации, перемешанные с логикой. Здесь же только голая логика задачи, из-за чего код становится более декларативным. Для меня декларативность — это "меньше реализации, больше спецификации". Как следствие — код становится понятным, если понятна спецификация.
Если этот код более понятен, то вряд ли имена данных играют роль в понимании. Они играют роль в понимании работы того кода. Избавившись от деталей мы избавляемся и от необходимости их понимать.
VD>Модульности? Тут я что-то не догоняю. Может быть обобщенности? VD>Что под этим имелось в виду?
Composable код — в отличие от монолитного кода — содержит явные куски, разделённые синтаксически, которые можно выделять в отдельные более абстрактные задачки. Пример из жизни — нужно обойти рекурсивно директорию, вычленяя из неё пути элементов (файлов/директорий), удовлетворяющих какому-то условию, полученный список вернуть. Особенность — если директория не удовлетворяет условию, всё её содержимое не включать в результат, соответственно не читать содержимое этой директории.
Что делается на обычном человеческом языке? Пишется код, реализующий эту задачу. Что делается в ленивом языке? Пишутся подзадачи — прочитать лениво всю (!) директорию в дерево, отфильтровать дерево в соответствии с предикатом, flatten (не знаю как по русски) дерево в список, отображения списка файлов в список путей файлов. Кроме первой и последней задачи — остальные совершенно абстрактны и уже наверняка есть в библиотеке, работающей с абстракцией дерево (да и последняя задача это просто map filePath). Акцент на абстракции, а не на том, что уже эти задачки реализованы.
L>>Плюс equational reasoning — очень полезная техника — гораздо проще применять на комбинаторном коде. VD>С этим не знаком.
Замена эквивалентных частей с определённой целью.
Composable код, в связи с чётким разбиением на блоки позволяет делать такие замены сильно проще.
VD>Откровенно говоря лично мне важно быстро понимать что код делает. И код Вольфхаунда я понимаю без напряга, а твой... откровенно говоря даже не возьмусь сказать, что вообще понимаю. Мне нужно совершать столько "обратных преобразований функций", что найти ошибку я вряд ли смогу в таком коде.
Я наоборот — помню долго пытался въехать, что там куда передаётся Всё таки явную рекурсию я очень плохо понимаю.
В моём случае всё просто — транспонируем матрицу (transpose), затем каждую строку (map) поэлементно умножаем на ks (zipWith (*) ks), результат складываем (sum). Вектор этих сумм и есть результат.
Впрочем, ты прав — для понимания нужна практика. Но это как везде.
L>>Мне тоже нравится, но ты мне уже показывал давным-давно, что карринг и плейсхолдер примерно равны — у обоих свои преимущества и недостатки. VD>Так и есть. Только постоянно находятся войны которым надо это доказывать вновь и вновь. Причем Воронков то как раз о частичном применении знает не плохо, так как реализовал похожую фичу для своего языка Ела. Так что вообще не ясно что он торолит.
Так мы же в философии! Почему бы не подумать о лучших мирах?
Здравствуйте, gandjustas, Вы писали:
G>Это все потому что в haskell принята запись не очень человеческая. Люди читают слева направо, поэтому чтобы понятнее стало надо написать что-то вроде:
G>staff |> (filter isFired >> map salary >> sum)
G>Сразу в разы понятнее.
Думаю, не в разы, но да, есть такое дело. Изначально, привыкнув к тому, что надо реализовывать, а не описывать, я так и писал справа-налево Некоторые для этого даже свои комбинатор обратной композиции придумавают, как в твоём примере. Позже, начав описывать, что надо получить, а не как, я увидел, что и пишется и читается гораздо проще, если писать прямой композицией:
"Сумма зарплат уволенных сотрудников" — сразу и пишешь — sum . map salary . filter isFired. Читается точно также. Твой же код для меня сейчас читается даже чуточку сложнее, потому что я воспринимаю его как последовательность, а не как декларацию.
Здравствуйте, lomeo, Вы писали:
L>С другой стороны — я нажимаю кнопку и тип хаскелевской функции у меня вставляется автоматом. Для интелисенса было бы полезно?
В принципе это можно сделать.
Правда в местах вызова этой функции будет ошибка до тех пор пока типы не будут указаны явно.
L>Да хрен с ним с каррингом
Я не только тебе объяснял.
L>+1. Карринг удобен для описания DSL-ей, например. В Nemerle для этого есть средства.
А что и с какой легкостью можно будет творить в немерле2
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, lomeo, Вы писали:
L>Здравствуйте, gandjustas, Вы писали:
G>>Это все потому что в haskell принята запись не очень человеческая. Люди читают слева направо, поэтому чтобы понятнее стало надо написать что-то вроде:
L>
G>>Сразу в разы понятнее.
L>Думаю, не в разы, но да, есть такое дело. Изначально, привыкнув к тому, что надо реализовывать, а не описывать, я так и писал справа-налево Некоторые для этого даже свои комбинатор обратной композиции придумавают, как в твоём примере. Позже, начав описывать, что надо получить, а не как, я увидел, что и пишется и читается гораздо проще, если писать прямой композицией:
L>"Сумма зарплат уволенных сотрудников" — сразу и пишешь — sum . map salary . filter isFired. Читается точно также. Твой же код для меня сейчас читается даже чуточку сложнее, потому что я воспринимаю его как последовательность, а не как декларацию.
Естественные языки наш мозг парсит быстрее, чем языки программирования, поэтому даже в таком случае для человека привычнее.
Зато если написать что-то длинное и непривычное "сумма зарплат уволенных по четным дням, с фамилией начинающейся на А, имеющим трех работающих в том же отделе детей сотрудников". Такое уже читается во много раз сложнее.
А если переписать в варианте dataflow: "взять сотрудников, уволенных в четные дни, у которых фамилия начинается на А, у которых трое детей работают в том же отделе, и сложить их зарплаты" то становится проще.
Хотя это все чисто психология, можно нетренировать себя читать справа налево и все будет ОК.
Здравствуйте, WolfHound, Вы писали:
L>>+1. Карринг удобен для описания DSL-ей, например. В Nemerle для этого есть средства. WH>А что и с какой легкостью можно будет творить в немерле2
Здравствуйте, VladD2, Вы писали:
ВВ>>Дано — в функциональном языке сами функции и алгребраические типы идут вразрез с платформой. VD>А вот это не верный вывод. Все же у тебя и правд не все ОК с логическим выводом.
Ага, вот только это не вывод. Но я, конечно, ценю твои советы мне почитать учебник по логике, с учетом того, что я защищал диссертацию по феноменологии. Могу в ответ порекомендовать тебе почитать книгу "Для начинающих пользователей ПК".
VD>То что платформа не предоставляет примитивов для представления некоторых фич языке еще не означает, что фичи идут в разрез с платформой. VD>Скорее это говорит о недоработках в платформе.
Ну вот в платформе нет, к примеру, такого понятия как "структурный тип". И отсутствие "примитивов для представления некоторых фич языка" тут попросту означает, что эти самые фичи за пределами самого языка будут уже никому не понятны. Можешь называть или не называть это противоречием, суть от этого не меняется.
VD>Если ты хочешь пофилософствовать по поводу платформы, то могу высказать свои (крамольные для многих) мысли. VD>Я считаю, что ошибочно было вводить в платформу классы (и особенно их наследование). Достаточно было ввести типы разделив их на ссылочные и значений.
А я считаю, что ошибкой было разделять типы на ссылочные и по значению И все ради того, чтобы System.Object был у нас "any type". Куча неочевидной хрени ради сомнительного преимущества. Были бы Object и Object^.
А по поводу вводить в платформу классы — с одной стороны логично. С другой — ты что под платформой имеешь в виду? "Классы" тут введены так глубоко, что их даже через анальный зонд не достанешь. Они на уровне ассемблера у них. Причем не просто некие "классы", а именно ООП — виртуальные вызовы и проч.
Т.е. нужен другой MSIL? Другие метаданные. Как ты все это себе представляешь? Коллекцию "модулей" а ля Бейским с плоским процедурным API?
Ну хорошо, положим. Теперь возникает другой вопрос. Вот у нас есть на платформе ОО-язык. Платформа представляет не просто низкоуровневое API, а, в чем ее преимущество-то, целые проблемно-ориентированные библиотеки, так сказать. Т.е., к примеру, "все что нужно для разработки вин-приложений", "все что нужно для веб", "все что нужно для распределенки". Т.е. это уже не модуль File с функциями Open/Delete/Close, а нечто большее. И очевидно, что такие вкусные библиотеки хочется использовать из разных языков. Также очевидно, что эти библиотеки должны иметь какой-то... эээ... внутренний дизайн. На одном процедурном стиле далеко не уедешь.
Ну хорошо, предположим — пусть они все-таки в таком ключе и созданы — модули и функции. Никакого наследования, ни грамма ООП. Удобно с такими библиотеками будет работать из нашего ООП-языка? Да нифига. А из ФЯ? Да нифига. А что делать? Ясно, что делать — нужно писать обвертки над библиотеками, заточенные под конкретный язык. Ну и чем это отличается от того, что сейчас?
VD>Далее ошибкой было введение делегатов. Вместо этого лучше было бы ввести в платформу ссылку на функцию и понятие замыкания. Это действительно базовые вещи требующие абстрагирования.
Что такое "ссылка на функцию"? Делегаты были ошибкой, но это по сути то, что Хейлсберг выдавал за преимущество дотнета. Я бы предпочел видеть первые версии без делегатов и без какой-либо замены для них вообще. События могли бы быть реализованы точно также, но в качестве колл-беков использовались бы абстрактные классы. Компилятор мог бы все это добро генерить.
Когда пришло бы время — сделали бы функциональный тип.
Здравствуйте, gandjustas, Вы писали:
G>Зато если написать что-то длинное и непривычное "сумма зарплат уволенных по четным дням, с фамилией начинающейся на А, имеющим трех работающих в том же отделе детей сотрудников". Такое уже читается во много раз сложнее. G>А если переписать в варианте dataflow: "взять сотрудников, уволенных в четные дни, у которых фамилия начинается на А, у которых трое детей работают в том же отделе, и сложить их зарплаты" то становится проще.
Мне обычно задачи в таком виде не ставят. А вот "что-то длинное и непривычное" — постоянно. Это уже ты подсознательно вместо постановки расписал решение. Поэтому — нет, не проще.
G>Хотя это все чисто психология, можно нетренировать себя читать справа налево и все будет ОК.
Я как раз говорю о том, что не нужно этого делать. С тем, что это психология, согласен. Думаешь, это вкусовщина или особенности конкретного человека?
Здравствуйте, lomeo, Вы писали:
VD>>В F#, между прочем, тоже "нет элиминации промежуточных структур". L>М? И цепочка функций map/filter/foldr/etc порождает промежуточные списки?
Смотря о каких map/filter и проч. идет речь. Если имеются в виду функции из модуля Seq, то там же не списки, а ленивые итераторы, т.е. это по сути аналог Linq, и здесь-то все в порядке. Те, что в модуле List, создают промежуточные списки, да, куда им деться-то.
Здравствуйте, lomeo, Вы писали:
L>Да я смотрю вы там вовсю усиливаете макросы.
Я вообще думаю о том чтобы сделать не столько макросы сколько движок для создания статически типизированных eDSL со своей семантикой и системой типов.
А базовый немерле сделать просто одним из частных случаев.
Как следствие придется делать расширемым не только парсер но и поиск имен и вывод типов и кодогенератор.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, lomeo, Вы писали:
L>Я как раз говорю о том, что не нужно этого делать. С тем, что это психология, согласен. Думаешь, это вкусовщина или особенности конкретного человека?
Это разница между физиками и лириками обычными людьми и математиками. А Хаскель, как известно, создавали математики. Вот ML в этом плане демократичнее — хочешь так, хочешь этак.
Здравствуйте, Воронков Василий, Вы писали:
L>>Я как раз говорю о том, что не нужно этого делать. С тем, что это психология, согласен. Думаешь, это вкусовщина или особенности конкретного человека? ВВ>Это разница между физиками и лириками обычными людьми и математиками. А Хаскель, как известно, создавали математики. Вот ML в этом плане демократичнее — хочешь так, хочешь этак.
Ну! На Haskell тоже хочешь так, хочешь эдак. Ведь, как известно, Haskell — самый лучший императивный язык в мире!
Здравствуйте, lomeo, Вы писали:
L>Ну! На Haskell тоже хочешь так, хочешь эдак. Ведь, как известно, Haskell — самый лучший императивный язык в мире!
Я имею в виду парные операторы — forward pipe (|>) и backward pipe (<|), forward composition (>>) и backward composition (<<). Хотя, конечно, никто не мешает написать свои, если поведение стандартных не устраивает.
Здравствуйте, gandjustas, Вы писали:
G>Это все потому что в haskell принята запись не очень человеческая. Люди читают слева направо, поэтому чтобы понятнее стало надо написать что-то вроде:
G>
Подтверждаю, вот в OCaml'ских батарейках (альтернативная стандартная библиотека) передрали из F# казалось бы фигню все
эти закорючки типа |> код реально с ними становится сильно читабельней.
Здравствуйте, lomeo, Вы писали:
L>М? И цепочка функций map/filter/foldr/etc порождает промежуточные списки?
Да, если они конечно со списками работают. Часто это IEnumerable[T], что сильно дешевле (один новый объект на вызов).
Плюс ЖЦ в дотнете весьма шустрый и это не так уж сильно сказывается на производительности.
Но факт остается фактом, императивная реализация может быть значительно эффективнее.
L>Мне кажется, что эта оптимизация сильно связана с тем, что язык чистый. Для нечистого языка написать подобное было бы гораздо сложнее.
В общем случае — да. Для стандартных же функций делать оптимизации можно смело.
VD>>Возможно это потому, что имена параметров/переменных/полей многое говорят о происходящем. Т.е. получается меньше подразумеваемых тонкосей. L>
L>Смотри, что я имею в виду — вот для тебя лично этот код более понятен, чем явный цикл с явной проверкой и явным заведением и изменением переменной?
Но надеюсь, что не только для меня.
L>Ведь это всё — детали реализации, перемешанные с логикой. L>Здесь же только голая логика задачи, из-за чего код становится более декларативным. Для меня декларативность — это "меньше реализации, больше спецификации". Как следствие — код становится понятным, если понятна спецификация.
Я бы не сказал что в данном коде есть какие-то детали реализации.
L>Если этот код более понятен, то вряд ли имена данных играют роль в понимании. Они играют роль в понимании работы того кода. Избавившись от деталей мы избавляемся и от необходимости их понимать.
Не. Если мы говорим о коде, то важно чтобы программист мог быстро и легко понять что в этом коде происходит.
Этому могут препятствовать как низкоуровневые детали реализации (такие как детали поиска информации в императивном алгоритме), так и запутанность создаваемая перестановкой действий и необходимостью разбираться в том какие трансформации происходят с функциями.
Фактически твой вариант ничем не лучше императивного. Просто программисту приходится разбираться с деталями другого рода.
Думаю, что если бы твой вариант был бы записан на в оду строчку, а сприменением именованных функций, т.е. каждое преобразование функции получало бы отдельное имя, то проблем с чтением кода было бы меньше (если вообще были бы).
VD>>Модульности? Тут я что-то не догоняю. Может быть обобщенности? VD>>Что под этим имелось в виду?
L>Composable код — в отличие от монолитного кода — содержит явные куски, разделённые синтаксически, которые можно выделять в отдельные более абстрактные задачки.
Дык твой код более "Composable", потому что ты как раз не произвел эту декомпозицию.
L>Пример из жизни — нужно обойти рекурсивно директорию, вычленяя из неё пути элементов (файлов/директорий), удовлетворяющих какому-то условию, полученный список вернуть. Особенность — если директория не удовлетворяет условию, всё её содержимое не включать в результат, соответственно не читать содержимое этой директории.
L>Что делается на обычном человеческом языке?
Пишется функция фильтрации возвращающая итератор, а потом на его основе реализуется основной алгоритм.
L>Пишется код, реализующий эту задачу. Что делается в ленивом языке? Пишутся подзадачи — прочитать лениво всю (!) директорию в дерево, отфильтровать дерево в соответствии с предикатом, flatten (не знаю как по русски) дерево в список, отображения списка файлов в список путей файлов.
Ты отстал от жизни. Даже в C# 2.0 эта задача решается точно так же.
Более того в дотнет 4.0 такая функция уже входит в стандартную библиотеку: EnumerateDirectories
Я написал аналогичную функцию в 1995-ом году: http://rsdn.ru/forum/src/1403639.1.aspx
L> Кроме первой и последней задачи — остальные совершенно абстрактны и уже наверняка есть в библиотеке, работающей с абстракцией дерево (да и последняя задача это просто map filePath). Акцент на абстракции, а не на том, что уже эти задачки реализованы.
Да, да. Все так. Только вот причем тут композиция функций? Ну, и все это можно в совершенно гражданских языках. О немерле тут уже даже как-то и говорить неудобно. Уж в нем это само собой разумеется.
Так что тут дело скорее не в языке, а в том как мыслит программист.
На мой взгляд ты преувеличиваешь значимость композиции функций. Это несомненно один из удобных механизмов программирования. Но не более чем еще один способ получения новой функции. Тех же результатов можно добиться просто написав новую функцию которая будет использовать другие функции. Где-то композиция дает уменьшение кода, где-то удобнее другие подходы.
L>Замена эквивалентных частей с определённой целью. L>Composable код, в связи с чётким разбиением на блоки позволяет делать такие замены сильно проще.
Ясно. Согласен. Но все же кроме изменяемости важна еще и понятность. А вот она хромает.
VD>>Откровенно говоря лично мне важно быстро понимать что код делает. И код Вольфхаунда я понимаю без напряга, а твой... откровенно говоря даже не возьмусь сказать, что вообще понимаю. Мне нужно совершать столько "обратных преобразований функций", что найти ошибку я вряд ли смогу в таком коде.
L>Я наоборот — помню долго пытался въехать, что там куда передаётся
Возможно — это эффект чтения мало знакомого языка. Идиомы то конечно одинаковые, но все же нюансов всегда хватает. Плюс привычки. Тот кто привык к МЛьным языкам, читает сишный код с трудом, и наоборот.
L>Всё таки явную рекурсию я очень плохо понимаю.
Да ладно тебе. Циклы ты ведь понимаешь?
L>В моём случае всё просто — транспонируем матрицу (transpose), затем каждую строку (map) поэлементно умножаем на ks (zipWith (*) ks), результат складываем (sum). Вектор этих сумм и есть результат.
Нет, нет, нет и нет! В твоем случае производится ряд "махинаций" с функциями. Например, функция sum у тебя появляется в самом начале. Это дико мешает понять суть алгоритма (по крайне мере мне)! Вот код:
saving = staff.Where(_.isFired).Sum(_.salary);
я читаю легко, так как я сразу вижу, что мы обрабатываем (staff), и что мы с этим делаем (сначала фильтруем, а потом суммируем). Причем последовательность записи соответствует происходящему. При этом в коде отсутствуют лишние детали (вроде формирования функций Where и Sum). Посему этот код я читаю очень просто: отфильтровать staff по значению поля isFired в его элементах и суммировать в полученном результате значения полей salary.
L>Впрочем, ты прав — для понимания нужна практика. Но это как везде.
Ага. Нужна. Причем не только практика читать код, но и практика писать понятный код. Это далеко не всегда получается даже у тех кто умеет это делать. На любом языке можно нагородить совершенно не читаемого кода. И совершенно все равно как это будет сделано (композицией функций или морем императива).
L>Так мы же в философии! Почему бы не подумать о лучших мирах?
Дык он не только в Философии троллит.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>"Сумма зарплат уволенных сотрудников" — сразу и пишешь — sum . map salary . filter isFired. Читается точно также. Твой же код для меня сейчас читается даже чуточку сложнее, потому что я воспринимаю его как последовательность, а не как декларацию.
Проблема в том, что в твоем коде есть "sum . map" и "salary . filter". Эти действия к алгоритму отношения не имеют. Ты просто получаешь составные функции. Если бы ты вынес их в отдельные строки и дал бы им имена, то твой код что справа налево, что слева направо читался бы одинаково хорошо.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>Подтверждаю, вот в OCaml'ских батарейках (альтернативная стандартная библиотека) передрали из F# казалось бы фигню все FR>эти закорючки типа |> код реально с ними становится сильно читабельней.
А если содрали бы скобки и точки из С++-подобных языков, то код бы стал понятен и всем окружающим .
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Да, я понимаю, можем же мы в систему уравнений дописать typeof(sum1) | typeof(sum2) | typeof(sum3) для переменной, которой присваиваем перегруженную функцию. И при использовании переменной с этим типом решить оконачательно какой именно выбираем. Если по завершении вывода тип не выбран — то ошибка с type ambiguity.
Это только на словах просто. На самом же деле тип — это узел в графе типов. Изменение одного узла часто приводит к серьезному перестроению всего графа. То о чем вы говорите — это создание эдаких виртуальных ветвлений в графе которые позволят иметь как бы несколько версий происходящего. Но не стоит забывать, что исходно это был граф! А после такой модификации я даже не знаю как такую структур данных назвать.
Такое ветвление скорее всего будет приводить к экспоненциальному росту количества переменных типов. Так что не факт, что это все "взлетит".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, WolfHound, Вы писали:
L>>Да я смотрю вы там вовсю усиливаете макросы. WH>Я вообще думаю о том чтобы сделать не столько макросы сколько движок для создания статически типизированных eDSL со своей семантикой и системой типов. WH>А базовый немерле сделать просто одним из частных случаев. WH>Как следствие придется делать расширемым не только парсер но и поиск имен и вывод типов и кодогенератор.
Мечтать тут многие горазды.
Но чтобы мечты превратились в реальность нужно решать текущие задачи. А у нас пока что они очень сильно пробуксовывают.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>>>+1. Карринг удобен для описания DSL-ей, например. В Nemerle для этого есть средства. WH>>А что и с какой легкостью можно будет творить в немерле2
L>Да я смотрю вы там вовсю усиливаете макросы.
Несмотря на то что немерл пионер в области макросов и вывода типов и у него казалось бы пока нет серьезных конкурентов, но тем не менее есть кое какие проблемы которые хотелось бы решить.
И проблемы эти в основном крутятся вокруг легкости и гибкости написания макросов, а так же вокруг вывода типов.
На мой взгляд макры доказали свою пользу на практике. Но хочется чтобы их можно было намного проще писать, и при этом сталкиваться с как можно меньшими ограничениями.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
VD>>А если содрали бы скобки и точки из С++-подобных языков, то код бы стал понятен и всем окружающим .
FR>Вот и этот человек возражает против каррирования в немерле
А причем тут оно то?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Показать тебе первоклассное каррирование в языке с Си-подобным синтаксисом?
Google:
No results found for "первоклассный карринг".
No results found for "первоклассное каррирование".
"first class currying" — 6 results из которых только два имеют отношение к функциональному программированию.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, FR, Вы писали:
FR>>>Вот и этот человек возражает против каррирования в немерле VD>>А причем тут оно то? FR>Оно так же уместно как и C++ синтаксис в ML
А почему в МЛ-е то?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Я бы не сказал что в данном коде есть какие-то детали реализации.
Релизация обхода циклом — раз, реализация ветвления конструкцией if — два, ну и результат накапливается в аккумуляторе — три.
L>>Если этот код более понятен, то вряд ли имена данных играют роль в понимании. Они играют роль в понимании работы того кода. Избавившись от деталей мы избавляемся и от необходимости их понимать. VD>Не. Если мы говорим о коде, то важно чтобы программист мог быстро и легко понять что в этом коде происходит.
В этом смысле понятность обоих примеров идентична. Я имею в виду понятность, относящуюся к постановке задачи — что делает код, а не как он это делает.
VD>Фактически твой вариант ничем не лучше императивного. Просто программисту приходится разбираться с деталями другого рода.
Какими?
VD>Думаю, что если бы твой вариант был бы записан на в оду строчку, а сприменением именованных функций, т.е. каждое преобразование функции получало бы отдельное имя, то проблем с чтением кода было бы меньше (если вообще были бы).
Это же демонстрационный пример. Длинные цепочки так писать не стоит (здесь у Хаскеля минус — он их поощряет) и обычно их так никто и не пишет. Пойнт в том, что в случае комбинаторного кода выделение этих преобразований в отдельные функции становится очень простой задачей.
VD>Дык твой код более "Composable", потому что ты как раз не произвел эту декомпозицию.
В другом примере декомпозиции тоже нет. Где её сделать проще?
VD>Пишется функция фильтрации возвращающая итератор, а потом на его основе реализуется основной алгоритм. VD>Ты отстал от жизни. Даже в C# 2.0 эта задача решается точно так же. VD>Более того в дотнет 4.0 такая функция уже входит в стандартную библиотеку: VD>EnumerateDirectories VD>Я написал аналогичную функцию в 1995-ом году: VD>http://rsdn.ru/forum/src/1403639.1.aspx
Спасибо, я по привычке с ущербной Явой сравниваю. Тем не менее! Правильно ли я понимаю, что функция рекурсивного обхода директории и функция фильтрации — это две отдельные, независимые функции?
VD>Да, да. Все так. Только вот причем тут композиция функций? Ну, и все это можно в совершенно гражданских языках. О немерле тут уже даже как-то и говорить неудобно. Уж в нем это само собой разумеется.
У меня пока ещё нет полного понимания, поэтому позже, если не пойму, я попрошу набросок решения этой задачи на Немерле.
VD>Так что тут дело скорее не в языке, а в том как мыслит программист.
Правильно ли я понимаю, что решение, описанное мной идиоматично для Nemerle?
VD>На мой взгляд ты преувеличиваешь значимость композиции функций. Это несомненно один из удобных механизмов программирования. Но не более чем еще один способ получения новой функции. Тех же результатов можно добиться просто написав новую функцию которая будет использовать другие функции. Где-то композиция дает уменьшение кода, где-то удобнее другие подходы.
Разумеется. Композиция была выбрана с демонстрационной целью — всё таки синтаксически (точка), семантически (аж пара функций) и исторически (узнаваемость) это замечательный кандидат. Как следует из Why FP matters любая ФВП годится для модульности — выделяем из фильтра предикат, а из мапа трансформер.
L>>Замена эквивалентных частей с определённой целью. L>>Composable код, в связи с чётким разбиением на блоки позволяет делать такие замены сильно проще. VD>Ясно. Согласен. Но все же кроме изменяемости важна еще и понятность. А вот она хромает.
Вот я и пытаюсь выяснить почему. Ты же сам написал "Но надеюсь, что не только для меня" — так почему у нас не хромает, а "вообще" хромает. С чем это может быть связано?
VD>Возможно — это эффект чтения мало знакомого языка. Идиомы то конечно одинаковые, но все же нюансов всегда хватает. Плюс привычки. Тот кто привык к МЛьным языкам, читает сишный код с трудом, и наоборот.
Я не о синтаксисе, если ты о нём. Для меня твой код на Nemerle и мой на Haskell (из примера с зарплатами уволенных) почти одинаково понятен.
L>>Всё таки явную рекурсию я очень плохо понимаю. VD>Да ладно тебе. Циклы ты ведь понимаешь?
Циклы понимаю лучше, рекурсивную функцию стараюсь представлять как рекурсивную декларацию — "предок есть родитель или предок родителя". Поэтому стараюсь прятать явную рекурсию как можно глубже
VD>Нет, нет, нет и нет! В твоем случае производится ряд "махинаций" с функциями. Например, функция sum у тебя появляется в самом начале. Это дико мешает понять суть алгоритма (по крайне мере мне)! Вот код: VD>я читаю легко, так как я сразу вижу, что мы обрабатываем (staff), и что мы с этим делаем (сначала фильтруем, а потом суммируем). Причем последовательность записи соответствует происходящему. При этом в коде отсутствуют лишние детали (вроде формирования функций Where и Sum). Посему этот код я читаю очень просто: отфильтровать staff по значению поля isFired в его элементах и суммировать в полученном результате значения полей salary.
А-а-а, блин, спасибо! Я только сейчас осознал важность этого аргумента.
Итак. Я уже писал про "декларацию vs последовательность действий". Ты там предложил выделить составные функции в отдельные строки и дать им имена. Для такого маленького примера это кажется не нужным, поэтому просто добавлю скобки
sum . (map salary) . (filter isFired)
Я читаю это как "сумма зарплат уволенных". Декларация. Для тебя же важна реализация — что обрабатываем, в какой именно последовательности. Мне кажется причина в этом. Не надо декларацию читать как последовательность действий — именно поэтому такие сложности с пониманием комбинаторного кода.
Здравствуйте, WolfHound, Вы писали:
WH>record Item WH>{ WH> Name : string!; WH> Value : int!; WH> Count : int!; WH> Total = Value * Count; WH>} WH>def items : array![Item]; WH>! признак реактивности. WH>Теперь если что-то поменяется все что зависит от этого чегото будет пересчитано.
Это условный псевдокод, или на Nemerle уже делается/сделано ?
Здравствуйте, lomeo, Вы писали:
L>Релизация обхода циклом — раз, реализация ветвления конструкцией if — два, ну и результат накапливается в аккумуляторе — три.
Я про свой вариант на базе линк-а.
VD>>Фактически твой вариант ничем не лучше императивного. Просто программисту приходится разбираться с деталями другого рода. L>Какими?
Я об этом чуть ниже сказал.
VD>>Думаю, что если бы твой вариант был бы записан на в оду строчку, а сприменением именованных функций, т.е. каждое преобразование функции получало бы отдельное имя, то проблем с чтением кода было бы меньше (если вообще были бы).
L>Это же демонстрационный пример. Длинные цепочки так писать не стоит (здесь у Хаскеля минус — он их поощряет) и обычно их так никто и не пишет. Пойнт в том, что в случае комбинаторного кода выделение этих преобразований в отдельные функции становится очень простой задачей.
Ну, дык ты показал пример и я говорю именно о нем. О том что в Хаскеле есть переменные я тоже догадываюсь .
VD>>Дык твой код более "Composable", потому что ты как раз не произвел эту декомпозицию.
L>В другом примере декомпозиции тоже нет. Где её сделать проще?
Я сравнивал со своим, линковским решением. В нем декомпозиция и не нужна, так как уже есть функции решающие задачу кратчайшим образом.
L>Спасибо, я по привычке с ущербной Явой сравниваю. Тем не менее!
Ну, да. Проблема только в том, что почему-то все любители чистого ФП почему-то постоянно забывают (или в упор не замечают), что ленивость, лямбды и замыкания уже есть даже в C#. Соответственно выводы делаются мягко говоря неверные. И это повторяется из раза в раз.
L>Правильно ли я понимаю, что функция рекурсивного обхода директории и функция фильтрации — это две отдельные, независимые функции?
Правильно, хотя это конечно зависит от выбора функций. Вообще, чтобы понять все и до конца надо понять очень простую вещь. Под видом LINQ-а Меер протощил в дотнет копию Перелюда Хаскеля адаптированную под реалии C# 3.0. Так что многое что можно было делать на хаскеле теперь можно делать даже на C#, ну, а Nemerle — это такой правильный клон C#-а в котором ФП не кастрированный, а самый что ни на есть настоящий.
VD>>Да, да. Все так. Только вот причем тут композиция функций? Ну, и все это можно в совершенно гражданских языках. О немерле тут уже даже как-то и говорить неудобно. Уж в нем это само собой разумеется.
L>У меня пока ещё нет полного понимания, поэтому позже, если не пойму, я попрошу набросок решения этой задачи на Немерле.
Ну, ты ее опиши более детально. И если не я, то кто-то другой тебе точно ее нарисует. Здесь многие любят "олимпиадные задачки" порешать .
Хотя смысл в этом в общем-то отсутствует. Ведь достаточно понять, что почти любой код который можно написать на хаскеле можно повторить на немреле 1 в 1. Другим будет только синтаксис, список функций, подход к ленивости и подход к полиморфизму. Собственно на то он и ФЯ, чтобы можно было одни идиомы использовать.
Так что разница между немерлом и хасклем скорее определяется менталитетом программиста. Немерловый программист не держится за ФП. Для него это просто освоенная парадигма. Посему упражнений с комбинированием функций у них найти трудно. И чистоте частенько предпочитается производительность и/или гибкость. По сему конечно твое решение — это не немерловое решение. Повторить его можно, но вот никто, скорее всего, сам писать не будет.
VD>>Так что тут дело скорее не в языке, а в том как мыслит программист.
L>Правильно ли я понимаю, что решение, описанное мной идиоматично для Nemerle?
Я не понимаю значения этого слова. В прочем, на пальцах я уже выше отношение немерла и этого решения.
L>Разумеется. Композиция была выбрана с демонстрационной целью — всё таки синтаксически (точка), семантически (аж пара функций) и исторически (узнаваемость) это замечательный кандидат. Как следует из Why FP matters любая ФВП годится для модульности — выделяем из фильтра предикат, а из мапа трансформер.
Я не разделяю самого "FP matters". Да и для достижения модульности мне больше нравится применять классы/объекты. Но в принципе, конечно, сами ФВП (как в прочем и интерфейсы в ООП) созданы для отделения интерфейса от реализации и для выделения чистых алгоритмов, так что модульности они способствуют. Но вот комбинация функций все же не более чем удобный механизм получения новых функций .
VD>>Ясно. Согласен. Но все же кроме изменяемости важна еще и понятность. А вот она хромает.
L>Вот я и пытаюсь выяснить почему.
Я уже много раз ответил. Плюс рядом тут ребята отвечали.
Проблемы две:
1. Ты (как и императивщик) залепил в код обрабатывающий данные код формироания новых функций, чем резко усложнил понимание конкретного куска кода.
2. Нам, людям не тренирующимся читать композиции функций каждый день, проще читать код слева на право в последовательности его выполнения.
Ну, и конечно же нет опыта использования Хакеля, так что читать код на нем сложнее чем на языке который каждый день используется.
L>Я не о синтаксисе, если ты о нём.
Дык синтаксис первое что мы видим в коде. Я могу читать и хаскель и F#, делать это мне в разы сложнее чем читать С-подобный код.
Все же 15 лет привычки!
L>Для меня твой код на Nemerle и мой на Haskell (из примера с зарплатами уволенных) почти одинаково понятен.
Ну, если чесно, то хаскелевский код с "." (и особенно flip-ами) меня почти сразу сбивает с толку. Если разнести каждое применение выделить в отдельную строку и дать ему отдельное (понятное!) имя, то проблем тоже, наверно не будет.
Плюс еще не привычно то, что любое вычисление может быть отложенным. Уже в мозжечке сидит привычка рассматривать процесс вычислений монолитно.
В моем коде лениво обычно выполняются только обработка списков и вызов функций (в том смысле что их упоминание не приводит к вычислению).
L>>>Всё таки явную рекурсию я очень плохо понимаю. VD>>Да ладно тебе. Циклы ты ведь понимаешь?
L>Циклы понимаю лучше, рекурсивную функцию стараюсь представлять как рекурсивную декларацию — "предок есть родитель или предок родителя". Поэтому стараюсь прятать явную рекурсию как можно глубже
Ну, вот в подобном коде рекурсия — это такой гибкий вид цикла. Можешь считать — это императивным мышлением в функционалом программировании .
VD>>Нет, нет, нет и нет! В твоем случае производится ряд "махинаций" с функциями. Например, функция sum у тебя появляется в самом начале. Это дико мешает понять суть алгоритма (по крайне мере мне)! Вот код: VD>>я читаю легко, так как я сразу вижу, что мы обрабатываем (staff), и что мы с этим делаем (сначала фильтруем, а потом суммируем). Причем последовательность записи соответствует происходящему. При этом в коде отсутствуют лишние детали (вроде формирования функций Where и Sum). Посему этот код я читаю очень просто: отфильтровать staff по значению поля isFired в его элементах и суммировать в полученном результате значения полей salary.
L>А-а-а, блин, спасибо! Я только сейчас осознал важность этого аргумента.
L>Итак. Я уже писал про "декларацию vs последовательность действий". Ты там предложил выделить составные функции в отдельные строки и дать им имена. Для такого маленького примера это кажется не нужным, поэтому просто добавлю скобки L>
L>sum . (map salary) . (filter isFired)
L>
Пойми, это тебе с нехеровым опытом чтения кода на Хасклее кажется не важным. Я вот тоже иной раз спокойно читаю лапшу в стиле С, а другие охренивают с нее. Но я все же понимаю, что я читаю эту лапшу только потому, что у меня огромный опыт ее чтения.
Но писать так нельзя! И знаешь почему? Потому что код пишется не для себя, а для других.
Однажды, я обратил внимание, что пишу более качественный код когда пишу код к статьям. Я понял, что чтобы написать хороший код нужно не просто изложить код в терминах используемого языка, и даже не написать код используя максимум возможностей языка, а нужно написать код так, чтобы при его объяснении (устном или на бумаге) было максимально просто объяснить что же происходит в твоем коде.
Отсюда я сделал вывод, что иногда лучше написать больше кода. Скажем иногда лучше ввести функцию или переменную даже если они используются в коде только один раз! А иногда лучше отказаться от наворотов языка и выбрать более тупое решение, но интуитивно более понятное окружающим. Вот когда речь идет об оптимизации, то на это можно наплевать.
В общем код должен быть как бы комментарием к самому себе. Отсюда вытекают эти правила что логика должна идти слева на правло, и что в код нельзя включать части реализации (ни в виде императива, ни в виде инлайн-комбинаторов).
Крутой код — плохой код!
L>Я читаю это как "сумма зарплат уволенных".
Понимаешь ли... твои слова очень похоже на слова из первой Матрицы "А я даже уже не замечаю числе. Я вижу за ними девушку...". Ну, да. Может ты и видишь, а я вот вижу кучу приседаний с "." которые моему мозгу нужно сначала мысленно превратить в результирующие функции, а потом восстановить тот порядок вычислений который будет происходить. В итоге мой мозг сворачивается в трубочку после третей ".". Вот как-то так.
L> Декларация. Для тебя же важна реализация — что обрабатываем, в какой именно последовательности. Мне кажется причина в этом. Не надо декларацию читать как последовательность действий — именно поэтому такие сложности с пониманием комбинаторного кода.
Да хреновая это декларация. Мы же все же пишем декларацию алгоритма. И в нем важно что и как происходит. Даже в Прологе важно как происходит вычисления. А уж в менее декларативных языках она важна и подавно. Как минимум от этого может зависит производительность, а как максимум и смысл.
А декларативность — это здорово. Но на более высоком уровне. Вот когда ты мне дашь ДСЛ который я смогу осознавать в терминах прикладной задачи, то я перестрою сознание и не буду искать последовательности. Но я все равно захочу знать как это работает (что там под капотом).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Silver_s, Вы писали:
S_> Это условный псевдокод, или на Nemerle уже делается/сделано ?
Это пока что мечты. И они так и останутся мечтаии, если уважаемый WolfHound вместо того чтобы дописать то что он начал, будет в сотый раз доказывать всем прописные истины.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
VD>>Дело не в линке. Дело в способе вызова функций. ВВ>А он и так разный. Есть там каррирование, нет там каррирования.
А вобще у каррирования есть полезные применения кроме перестановки аргументов местами? Просто я не в курсе патернов ФП. Вобще частичное применение может и полезно, но в карировании только по-порядку нужно частично применять.
Здесь то оно применяется только чтоб последний параметр вперед закинуть, точнее чтобы имя функции между аргументами вклинить:
lst |> List.map (fun ...)
В других языках для этого точка есть.
Неприятный побочный эффект F# карринга — задом наперед параметры надо расставлять. Там где на C# первым параметром будешь ставить Enumerable<T>, потом остальные (чтобы инфиксная запись получилась, для extension метода). Как в F# потом эту функцию в цепочку вставить (чтобы первый аргумент перед именем функции оказался)?
Спасибо за объяснение понимания моего кода! Например, я даже не думал о том, что в моём коде можно думать о том, как работает композиция. Я её просто не замечаю. Ну и остальное в том же духе. По крайней мере теперь я понимаю в чём нужно практиковаться для применения/чтения комбинаторного кода и могу с умным видом давать бесполезные советы
L>>Релизация обхода циклом — раз, реализация ветвления конструкцией if — два, ну и результат накапливается в аккумуляторе — три. VD>Я про свой вариант на базе линк-а.
Сорри, туплю.
VD>Ну, да. Проблема только в том, что почему-то все любители чистого ФП почему-то постоянно забывают (или в упор не замечают), что ленивость, лямбды и замыкания уже есть даже в C#. Соответственно выводы делаются мягко говоря неверные. И это повторяется из раза в раз.
Позор мне! Постараюсь впредь такого не допускать.
L>>Правильно ли я понимаю, что функция рекурсивного обхода директории и функция фильтрации — это две отдельные, независимые функции? VD>Правильно, хотя это конечно зависит от выбора функций. Вообще, чтобы понять все и до конца надо понять очень простую вещь. Под видом LINQ-а Меер протощил в дотнет копию Перелюда Хаскеля адаптированную под реалии C# 3.0. Так что многое что можно было делать на хаскеле теперь можно делать даже на C#, ну, а Nemerle — это такой правильный клон C#-а в котором ФП не кастрированный, а самый что ни на есть настоящий.
Это очень важный момент, который только усилил моё непонимание. Прелюд Хаскеля всё таки не работает с деревьями. А задача у нас именно такая.
L>>У меня пока ещё нет полного понимания, поэтому позже, если не пойму, я попрошу набросок решения этой задачи на Немерле. VD>Ну, ты ее опиши более детально. И если не я, то кто-то другой тебе точно ее нарисует. Здесь многие любят "олимпиадные задачки" порешать .
Задача — написать функцию, возвращающую список путей к файлам/директориям, находящимся в указанной директории на любом уровне вложенности, и удовлетворяющим определённому условию. Если какая-то директория не удовлетворяет этому условию, то всё её содержимое на любом уровне вложенности в результат не включать.
Задача на Хаскеле решается так (синтаксис а-ля Java/C# для понимания, функции сделаны методами соответствующих классов)
// библиотека для работы с файлами/директориямиclass File {
Boolean IsDir();
String FilePath();
List<File> ReadDirectory();
}
// библиотека для работы с деревьямиclass Tree<A> {
A Element();
List<Tree<A>> Subtrees();
List<A> Flatten(); // преобразование дерево -> список
Tree<A> Filter(Fun<A, Boolean> predicate); // фильтрация узлов в соответствии с предикатом
}
// наш код
// рекурсивно читаем директорию в дерево
Tree<File> ReadDirTree(File file) {
if (file.isDir()) {
return new Tree(file, ReadDirectory(file).Map(ReadDirTree));
}
else {
return new Tree(file, EmptyList());
}
}
// сама функция
List<String> GetFilePathsBy(File dir, Fun<File, Boolean> condition) {
return ReadDirTree(dir).Filter(condition).Flatten().Map(_.FilePath());
}
Из-за ленивости директории, не удовлетворяющие условию, читаться дальше не будут. Хотя в коде ReadDirTree нет и намёка на это. Благодаря настолько явному разделению код очень модульный. Можно решение на Nemerle? Не такое же, а как бы ты написал.
VD>Хотя смысл в этом в общем-то отсутствует. Ведь достаточно понять, что почти любой код который можно написать на хаскеле можно повторить на немреле 1 в 1. Другим будет только синтаксис, список функций, подход к ленивости и подход к полиморфизму. Собственно на то он и ФЯ, чтобы можно было одни идиомы использовать.
Вот у меня есть сомнение, что описанная мной идиома используется активно в Nemerle.
VD>Так что разница между немерлом и хасклем скорее определяется менталитетом программиста. Немерловый программист не держится за ФП. Для него это просто освоенная парадигма. Посему упражнений с комбинированием функций у них найти трудно. И чистоте частенько предпочитается производительность и/или гибкость. По сему конечно твое решение — это не немерловое решение. Повторить его можно, но вот никто, скорее всего, сам писать не будет.
Чистота — не самоцель. Поэтому правильнее было бы написать "модульности предпочитается производительность и/или гибкость". Что такое гибкость, кстати?
VD>Ну, если чесно, то хаскелевский код с "." (и особенно flip-ами) меня почти сразу сбивает с толку. Если разнести каждое применение выделить в отдельную строку и дать ему отдельное (понятное!) имя, то проблем тоже, наверно не будет.
Убрал композицию и вынес определения — получился тихий ужас:
sum(salaries(firedOnly(staff)))
where
salaries = map salary
firedOnly = filter isFired
VD>В моем коде лениво обычно выполняются только обработка списков и вызов функций (в том смысле что их упоминание не приводит к вычислению).
Во! Значит так, как я писал задачу обхода директорий ты не пишешь. Следовательно, модульности в твоём коде будет меньше.
VD>Однажды, я обратил внимание, что пишу более качественный код когда пишу код к статьям. Я понял, что чтобы написать хороший код нужно не просто изложить код в терминах используемого языка, и даже не написать код используя максимум возможностей языка, а нужно написать код так, чтобы при его объяснении (устном или на бумаге) было максимально просто объяснить что же происходит в твоем коде.
Золотые слова! С другой стороны — для читателей/слушателей с разным бэкграундом разный код оказывается проще, как мы тут с тобой уже убедились.
VD>Отсюда я сделал вывод, что иногда лучше написать больше кода. Скажем иногда лучше ввести функцию или переменную даже если они используются в коде только один раз!
Всё верно, почему восклицательный знак? Именование абстракции — одна из мощных практик в программировании. И её цель вовсе не избегать дублирования.
VD>В общем код должен быть как бы комментарием к самому себе. Отсюда вытекают эти правила что логика должна идти слева на правло, и что в код нельзя включать части реализации (ни в виде императива, ни в виде инлайн-комбинаторов).
Грешен, просто композиция, все эти map/filter, монады настолько воспринимаются как конструкции языка, что уже и забываешь, что они тоже имеют свой уровень абстракции и не всегда их стоит переть наверх.
VD>А декларативность — это здорово. Но на более высоком уровне. Вот когда ты мне дашь ДСЛ который я смогу осознавать в терминах прикладной задачи, то я перестрою сознание и не буду искать последовательности. Но я все равно захочу знать как это работает (что там под капотом).
Сходу не придумаю пример, который отражал бы обсуждаемую проблему, поэтому пока отложу ответ на это замечание.
Здравствуйте, lomeo, Вы писали:
L>Задача — написать функцию, возвращающую список путей к файлам/директориям, находящимся в указанной директории на любом уровне вложенности, и удовлетворяющим определённому условию. Если какая-то директория не удовлетворяет этому условию, то всё её содержимое на любом уровне вложенности в результат не включать.
L>Задача на Хаскеле решается так (синтаксис а-ля Java/C# для понимания, функции сделаны методами соответствующих классов) L>
L>// сама функция
L>List<String> GetFilePathsBy(File dir, Fun<File, Boolean> condition) {
L> return ReadDirTree(dir).Filter(condition).Flatten().Map(_.FilePath());
L>}
L>
Можно вставлю пару замечаний?
Метод Flatten должен быть обобщенный и иметь сигнатуру
Func<T, Func<T, IEnumerable<T>, IEnumerable<T>>
или
a -> (a -> [a]) -> [a]
Если словами, то он принимает что-то и метод отображения что-то на его детей, возвращает плоский список детей. Метод обобщенный и к дереву каталога не имеет никакого отношения.
Теперь о фильтрации. Достаточно наложить условие на метод, возвращающий детей дерева, при подаче его во Flatten. Т.е. метод фильтрации тоже можно выкинуть из класса дерева.
А еще нужно проверить условие над корнем дерева.
IEnumerable<String> GetFilePathsBy(File dir, Func<File, Boolean> condition) {
var tree = ReadDirTree(dir);
return condition(tree)
? Flatten(tree, t => t.Subtrees().Where(condition)).Map(_.FilePath())
: new string[]{};
}
Более того, сам класс дерева становится не нужным, т.к. в нем остается лишь путь и метод чтения дочерних директорий по этому пути (как правило есть библиотечный).
IEnumerable<String> GetFilePathsBy(string dir, Func<string, Boolean> condition) {
return condition(dir)
? Flatten(dir, d => Directory.GetDirectories(d).Where(condition))
: new string[]{};
}
Здравствуйте, Silver_s, Вы писали:
S_>А вообще у каррирования есть полезные применения кроме перестановки аргументов местами?
Я уже вроде отвечал на этот вопрос — каррирование нужно для частичного применения (пользуясь случаем, передаю привет Владу ). То, что этот самый Влад называет "частичным применением" в Немерле — это просто специальный синтаксис для объявления лямбд. Синтаксис сам по себе весьма удобен. Но по сути для частичного применения одной функции мы описываем другую — точно так же вы можете делать и в C# — просто благодаря лаконичности записи с "_" вы практически не замечаете, что объявляете функцию. Т.е. собственно говоря, нет вообще ничего общего между подчеркиванием "_" и каррированием, у них лишь финальный итог может быть один — частично примененная функция.
Каррированная функция — это такая функция, которая может принимать свои аргументы по одному. Это позволяет вам как бы специализировать эту функцию для конкретного применения. У вас есть "обобщенный" List.map, а есть и такой: List.map (fun x -> x ** 2). Эта запись выглядит чище чем с "подчеркиванием", никаких лишних знаков препинания писать не надо, к тому же тут у нас нет никакого двойного вызова, т.к. вариант с подчеркиванием List.map(x => x ** 2, _) это сахар для записи вида: y => List.map(x => x ** 2, y).
S_>Просто я не в курсе патернов ФП. Вобще частичное применение может и полезно, но в карировании только по-порядку нужно частично применять.
Для тех пишет на ФЯ порядок аргументов в функциях самый что ни на есть правильный. Вы же руководствуетесь каким-то принципом, когда аргументы в определенном порядке расставляете? Вот и здесь то же самое, просто принцип другой.
S_> Здесь то оно применяется только чтоб последний параметр вперед закинуть, точнее чтобы имя функции между аргументами вклинить: S_>lst |> List.map (fun ...) S_>В других языках для этого точка есть.
Вот в отличие от пайпов, которые наглядно показывают, что *действительно* происходит — т.е. мы берем список и "протаскиваем" его через цепочку вызовов — точка вызывает скорее недоумение. Точка — это костыль, которым пользуются за неимением возможности расширить синтаксис и писать цепочечные вызовы как-то более наглядно.
S_>Неприятный побочный эффект F# карринга — задом наперед параметры надо расставлять. Там где на C# первым параметром будешь ставить Enumerable<T>, потом остальные (чтобы инфиксная запись получилась, для extension метода). Как в F# потом эту функцию в цепочку вставить (чтобы первый аргумент перед именем функции оказался)?
Т.е. на C# вас не смущает, что следует порядок аргументов расставлять "для extension метода"?
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Я имею в виду парные операторы — forward pipe (|>) и backward pipe (<|), forward composition (>>) и backward composition (<<). Хотя, конечно, никто не мешает написать свои, если поведение стандартных не устраивает.
Так в haskell операторы композиции тоже парные: (>>>) и (<<<), (>>=) и (=<<), (>=>) и (<=<). Вообще, для любителей dataflow в haskell есть Control.Arrow. А (.), ($) и (<$>) — это все же другая техника, суть которой lomeo совершенно правильно описал здесь
Здравствуйте, samius, Вы писали:
S>Можно вставлю пару замечаний? S>Метод Flatten должен быть обобщенный и иметь сигнатуру S>Func<T, Func<T, IEnumerable<T>, IEnumerable<T>> S>или S>a -> (a -> [a]) -> [a] S>Если словами, то он принимает что-то и метод отображения что-то на его детей, возвращает плоский список детей. Метод обобщенный и к дереву каталога не имеет никакого отношения.
List<A> у меня и есть шарповский IEnumerable<A>.
S>Теперь о фильтрации. Достаточно наложить условие на метод, возвращающий детей дерева, при подаче его во Flatten. Т.е. метод фильтрации тоже можно выкинуть из класса дерева.
Т.е. одна функция делает две вещи — это и есть уменьшение модульности, о которой я говорил.
S>А еще нужно проверить условие над корнем дерева.
Мой Filter проверяет.
S>Более того, сам класс дерева становится не нужным, т.к. в нем остается лишь путь и метод чтения дочерних директорий по этому пути (как правило есть библиотечный).
Здравствуйте, lomeo, Вы писали:
L>Здравствуйте, samius, Вы писали:
S>>Теперь о фильтрации. Достаточно наложить условие на метод, возвращающий детей дерева, при подаче его во Flatten. Т.е. метод фильтрации тоже можно выкинуть из класса дерева.
L>Т.е. одна функция делает две вещи — это и есть уменьшение модульности, о которой я говорил.
Какая функция делает 2 вещи?
S>>А еще нужно проверить условие над корнем дерева.
L>Мой Filter проверяет.
и возвращает Tree<A>? Как этот Filter может выкинуть корень, фактически свой экземпляр?
S>>Более того, сам класс дерева становится не нужным, т.к. в нем остается лишь путь и метод чтения дочерних директорий по этому пути (как правило есть библиотечный).
L>И получаем всё более монолитный код.
Может быть
Здравствуйте, samius, Вы писали:
S>>>Теперь о фильтрации. Достаточно наложить условие на метод, возвращающий детей дерева, при подаче его во Flatten. Т.е. метод фильтрации тоже можно выкинуть из класса дерева. L>>Т.е. одна функция делает две вещи — это и есть уменьшение модульности, о которой я говорил. S>Какая функция делает 2 вещи?
Flatten — она и выпрямляет дерево и фильтрует его.
S>>>А еще нужно проверить условие над корнем дерева. L>>Мой Filter проверяет. S>и возвращает Tree<A>? Как этот Filter может выкинуть корень, фактически свой экземпляр?
Здравствуйте, Klapaucius, Вы писали:
K>Здравствуйте, Воронков Василий, Вы писали:
ВВ>>Я имею в виду парные операторы — forward pipe (|>) и backward pipe (<|), forward composition (>>) и backward composition (<<). Хотя, конечно, никто не мешает написать свои, если поведение стандартных не устраивает.
K>Так в haskell операторы композиции тоже парные: (>>>) и (<<<), (>>=) и (=<<), (>=>) и (<=<). Вообще, для любителей dataflow в haskell есть Control.Arrow. А (.), ($) и (<$>) — это все же другая техника, суть которой lomeo совершенно правильно описал здесь
Здравствуйте, gandjustas, Вы писали:
K>>Так в haskell операторы композиции тоже парные: (>>>) и (<<<), (>>=) и (=<<), (>=>) и (<=<). Вообще, для любителей dataflow в haskell есть Control.Arrow. А (.), ($) и (<$>) — это все же другая техника, суть которой lomeo совершенно правильно описал здесь
.
G>Ну это с точки зрения теории другая техника, а F# — практичный язык (ибо ocaml), поэтому там используют то что удобно.
Ничего не понимаю. В F# в стандартной библиотеке есть только урезанный (без разветвлений и соединений) dataflow, а в haskell есть нормальный dataflow и еще много чего. И это потому, что F# практичный язык? А если мне удобно то, что в F# нет?
А практичный он потому, что не ocaml? Ну, ответ может и правильный, но только потому, что тут две ошибки, которые друг-друга скомпенсировали. Потому, что:
1) F# — это не ocaml.
2) ocaml — язык сомнительной практичности. С абсолютно непрактичной реализацией.
... << 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
Здравствуйте, Воронков Василий, Вы писали:
S_>>В других языках для этого точка есть. ВВ>Вот в отличие от пайпов, которые наглядно показывают, что *действительно* происходит — т.е. мы берем список и "протаскиваем" его через цепочку вызовов — точка вызывает скорее недоумение. Точка — это костыль, которым пользуются за неимением возможности расширить синтаксис и писать цепочечные вызовы как-то более наглядно.
А что в точке плохого? Цепочки вызовов вроде неплохо выглядят.
Если на уровне текстового перпроцессора менять arg.Func на arg |> Func , от этого мало что меняется. Какие-то неувязки в синтаксисе полезут, но это уже другой вопрос.
Да и в C# можно было бы (чисто теоретически, если не обращать внимание что что-то отвалится, какие-то неоднозначности вылезут), для точки сделать такую семантику: передает левый аргумент в функцию справа. Если аргумента слева нету, то это частичное применение в котором первый аргумент не применен:
Т.е. такой условый код (разные функции обозначил через Select)
var obj = new int[10];
var v0 = obj.Select(_ => _ + 1).Select(_ => _ / 2).Select(_ => _+3);
Тогда бы мог существовать и в разложенном виде
var v1 = .Select(_ => _ + 1).Select(_ => _ / 2);
var v2 = .Select(_ => _ + 3);
var V1toV2 = v1.v2;
var v4 = obj.V1toV2;
ВВ>Т.е. на C# вас не смущает, что следует порядок аргументов расставлять "для extension метода"?
Немного смущает то что не совпадает с C# и другими языками, соглашение (или традиция) ставить более важные аргументы на первое место. А вконце списка всякая мелочевка которую можно задать как default значения. И на первом месте которые присутствуют в разных переопределениях в которых только хвост отличается.
Функции написанные на C# сложнее будет использовать в F#, и в обратную сторону тоже.
S_> ... передает левый аргумент в функцию справа. Если аргумента слева нету, то это частичное применение в котором первый аргумент не применен:
Кстати многие форматируют цепочки LINQ так с точкой (и я тоже):
var res= someEnum
.Func1( _ => ...)
.Func2( _ => ...)
.Func3( _ => ...)
.Func4( _ => ...);
В таком виде оно и воспринимается как частичное применение или каррирование. Только действует ограничение — часть цепочки не является полноценным объектом. В этом ограничении наверное острой необходимости нет, без него было бы даже лучше. А при желении можно было бы и дальше пойти, и второй аргумент оставить недоопределенным.
Например была функция
TypeRet Func(Type1 p1, Type2 p2, Type3 p3){...}
Здравствуйте, Silver_s, Вы писали:
S_>>>В других языках для этого точка есть. ВВ>>Вот в отличие от пайпов, которые наглядно показывают, что *действительно* происходит — т.е. мы берем список и "протаскиваем" его через цепочку вызовов — точка вызывает скорее недоумение. Точка — это костыль, которым пользуются за неимением возможности расширить синтаксис и писать цепочечные вызовы как-то более наглядно. S_> А что в точке плохого? Цепочки вызовов вроде неплохо выглядят. S_> Если на уровне текстового перпроцессора менять arg.Func на arg |> Func , от этого мало что меняется. Какие-то неувязки в синтаксисе полезут, но это уже другой вопрос.
Точка — это доступ к члену. Зачем здесь эта семантика? Смысл операций ведь не такой. Ну т.е. в качестве решения точка, конечно, подходит за неимением лучшего, но запись через пайпы и каррирование выглядит куда естественнее. Собственно, на F#-то как раз никаких проблем нет записать "с точкой" и без каррирования. Но ведь не пишут так.
Опять же с пайпами я могу писать так, как мне удобно, в т.ч. и отталкиваясь от результата, скажем Select <| Where <| list.
S_> Да и в C# можно было бы (чисто теоретически, если не обращать внимание что что-то отвалится, какие-то неоднозначности вылезут), для точки сделать такую семантику: передает левый аргумент в функцию справа. Если аргумента слева нету, то это частичное применение в котором первый аргумент не применен:
Эту мысль я не понял. И так же все работает. Собственно, Линк как библиотеку ФВП можно было сделать и без экстеншин методов, но "с точкой". Писали бы по типу From(list).Where(...).Select(...). Разница ИМХО небольшая.
ВВ>>Т.е. на C# вас не смущает, что следует порядок аргументов расставлять "для extension метода"? S_> Немного смущает то что не совпадает с C# и другими языками, соглашение (или традиция) ставить более важные аргументы на первое место. А вконце списка всякая мелочевка которую можно задать как default значения. И на первом месте которые присутствуют в разных переопределениях в которых только хвост отличается.
Каким же образом функция селектор или там компаратор относится ко "всякой мелочевке"? Ради нее, собственно, все и затевается.
S_> Функции написанные на C# сложнее будет использовать в F#, и в обратную сторону тоже.
Модули, написанные на F#, из C# выглядят как дикая лапша. То, что там параметры не в том месте — на это уже и внимания не обращаешь.
Здравствуйте, lomeo, Вы писали:
L>Задача — написать функцию, возвращающую список путей к файлам/директориям, находящимся в указанной директории на любом уровне вложенности, и удовлетворяющим определённому условию.
Что за условие?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Эту мысль я не понял. И так же все работает. Собственно, Линк как библиотеку ФВП можно было сделать и без экстеншин методов, но "с точкой". Писали бы по типу From(list).Where(...).Select(...). Разница ИМХО небольшая.
Я имел ввиду что вот этот хвост в C# отделить нельзя как полноценный объект (функция)
var hvost = .Where(...).Select(...)
чтобы потом его приделать куда нибудь: From(list).hvost
Тип у этой переменной hvost был бы, в данном случае, функция принимающая один аргумент IEnumerable, и возвращающая то что там последний Select возвращает.
Но не скажу что это мне очень уж надо, поэтому нет желания этот вопрос дальше мусолить.
Но этот ужа я уже понимаю без малейшего напряжения мозга и даже без знания деталей работы функций.
Только вот названия у функций не очень хорошо подобраны. Лучше как-то так:
sum(toSalaries(getFired(employees)))
where
toSalaries = map salary
getFired = filter isFired
Вот такая хитрая фигня получается. И кстати, наши сишные скобочки на месте
Теперь если развернуть функции с помощью операторов аля |> и >> мы получил очень легко читаемый вариант.
И что характерно будет короче твоего первоначально (если брать отбросить код вводящий функции).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
var hvost = .Where(...).Select(...)
В F# то так можно сделать (хоть и не с точкой) а в C# такое только так:
Func<IEnumerable<int>, IEnumerable<int>> hvost =( inputEnum => inputEnum.Select(...).Where(...));
.
Здравствуйте, Silver_s, Вы писали:
S_>Неприятный побочный эффект F# карринга — задом наперед параметры надо расставлять. Там где на C# первым параметром будешь ставить Enumerable<T>, потом остальные (чтобы инфиксная запись получилась, для extension метода). Как в F# потом эту функцию в цепочку вставить (чтобы первый аргумент перед именем функции оказался)?
О! Для этого придумана обалденная фича — функция flip. С ее помощью можно переставлять аргументы местами.
В прочем, без привычки такое читать очень сложно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Хм, я и не знал что в Nemerle частичное применение даже так работает _.salary.
Только вот второй раз к аргументу обратиться не получится, т.к. для каждого _ создается аргумент в функции.
Так сделать никак нельзя, чтоб _ , был одной и той же переменной?
staff.Sum(_.salary + _.bonus);
Может добавить какие-то фичи чтобы второй раз можно было обращаться?
_ с циферкой показывающий номер аргумента.
staff.Sum(_1.salary + _1.bonus);
А для обычных имен запретить имена где только подчеркивание и цифры.
Здравствуйте, Silver_s, Вы писали:
S_>Так сделать никак нельзя, чтоб _ , был одной и той же переменной? S_>staff.Sum(_.salary + _.bonus); S_> Может добавить какие-то фичи чтобы второй раз можно было обращаться?
Между x => x.salary + x.bonus и _1.salary + _1.bonus разници силшком мало чтобы было оправданным корежить язык.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Между x => x.salary + x.bonus и _1.salary + _1.bonus разници силшком мало чтобы было оправданным корежить язык.
Хотя это так просто даже и не получится. В Nemerle сейчас _.X+_.Y создает две функции с одним аргументом и пытается их суммировать, а не одну функцию с двумя аргументами. Все выражение менять на лямбду тяжело.
Func(_1.X + ( _1.Y + _2 + Math.Sqrt(_1)));
Чтобы такое выражение (_1.X + ( _1.Y + _2 + Math.Sqrt(_1)) превратилось в лямбду пришлось бы шаманить с выводом типов, подниматься наверх пока не попадется функция где ожидается лямбда с двумя аргументами.
Т.е. чтобы компилятор не пытался в Math.Sqrt(_1) втиснуть лямбду.
Здравствуйте, VladD2, Вы писали:
VD>Так же нужно еще понимать, что каррирование (как это сделано в F#) очень плохо воспринимается большей частью дттнетчиков (читай C#/VB-программистов) и зачастую приводит к вывиху мозга. VD>Так зачем же добавлять столь спорное решение в язык где и без него все очень даже зашибись?
А можно пример, который будет конфликтовать с C-подобным синтаксисом?
И как вообще в С-подобном синтаксисе было бы лучше описать частичное применение?
Здравствуйте, Silver_s, Вы писали:
S_> Хм, я и не знал что в Nemerle частичное применение даже так работает _.salary.
Работает.
S_>Только вот второй раз к аргументу обратиться не получится, т.к. для каждого _ создается аргумент в функции.
Ага, но в более сложных случаях можно использовать лямбды.
S_>Так сделать никак нельзя, чтоб _ , был одной и той же переменной? S_>staff.Sum(_.salary + _.bonus);
Ну, дык при таком раскладе наличие лямбды уже не приводит к раздутию кода:
staff.Sum(e => e.salary + e.bonus);
По большому счету в частичном применении нет необходимости, так как его всегда можно заменить замыканиями и лямбдами. Но в ряде случаев частичное применение позволяет существенно сократить код или даже предоставить новый путь решения задачи.
S_> Может добавить какие-то фичи чтобы второй раз можно было обращаться?
В этом нет необходимости. Просто Воронкову по нужны темы для обсуждения вот он и зацепился за частичное применение.
В прочем, были предложения сделать частичное применение на манер МатЛаба или С++-ного буста, где параметры "неявной лямбды" являются нумерованными. Получается что-то вроде:
staff.Sum(#1.salary + #1.bonus);
Подразумевается, что параметров может быть более одного (т.е. #2, #3, ...).
Но встает вопрос вложенности подобных конструкций и области действия.
И тут мы плавно приходим к вопросу — А чем все это лучше явно введенной лямбды?.
И ответ на него, лично я дать не могу. Дизайн лямбд рекурсивный, есть именованные аргументы. Зачем выдумывать что-то еще? Чтобы сэкономить объявление аргументов?
В принципе я не против подобного расширения, но хотелось бы услышать четкое описание семантики и увидеть, что решение не приводит к другим проблемам.
S_>_ с циферкой показывающий номер аргумента. S_>staff.Sum(_1.salary + _1.bonus);
Во, во. А как отличить вложенные конструкции? Скажем так:
staff.Sum(_1.salary + _1.bonus.Sum(_1.x + __1));
Здесь предполагается, что "_1" — это первый параметр первой невидимой лямбды, а "__1" первый параметр второй невидимо лямбды. То есть этот код переписывается в:
Ну, и главное! Это уже не частичное применение (функции или оператора) — это какой-то сокращенный синтаксис для лямбд.
S_>А для обычных имен запретить имена где только подчеркивание и цифры.
Это похоже на наваристый бульон от яиц сваренных в крутую .
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vdimas, Вы писали:
VD>>Так же нужно еще понимать, что каррирование (как это сделано в F#) очень плохо воспринимается большей частью дттнетчиков (читай C#/VB-программистов) и зачастую приводит к вывиху мозга. VD>>Так зачем же добавлять столь спорное решение в язык где и без него все очень даже зашибись?
V>А можно пример, который будет конфликтовать с C-подобным синтаксисом?
Проще привести обратный пример, так как попытавшись это сделать поймешь что получается бред.
V>И как вообще в С-подобном синтаксисе было бы лучше описать частичное применение?
А так как есть сейчас. В свободные параметры записываются "_", в остальные выражения. Например:
x = someList.Filter(_ is SomeType); // Частичное применение оператора. Результат: функция с одним аргументом возвращающая bool
y = ints.Reduce(_ + _); // Частичное применение оператора. Результат: функция с двумя аргументами суммирующая их
def f = SomeMethod(_, "тест"); // Частичное применение функции/метода. Результат: функция с одним аргументом аналогичная: x => SomeMethod(x, "тест")
f(z);
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>В прочем, были предложения сделать частичное применение на манер МатЛаба или С++-ного буста, где параметры "неявной лямбды" являются нумерованными. Получается что-то вроде: VD>
VD>staff.Sum(#1.salary + #1.bonus);
VD>
VD>Но встает вопрос вложенности подобных конструкций и области действия.
В Mathematica решили эти вопросы довольно легко вложенность запретили совсем, даже заключив в скобочки нельзя одну лямбду в другую втиснуть. А для задания области действия ввели обязательный значок & , там где он попадается заканчивается лямбда выражение. Что не есть хорошо.
Вобщем то,да, с таким синтаксисом лямбд проблемы есть.
VD>
А что касается именования в C#, это дело вкуса. Мне первый вариант нравится даже больше.
В лямбдах указывать длинные имена из нескольких слов как то не очень, название коллекции говорит само за себя, что то там внутри лежит и так понятно. Имена "e", "x" и прочие все равно ни о чем не говорят, а только усложняют чтение т.к. надо убедиться что этот x не снаружи захвачен.
Выражения с вложенными лямбдами вобще тяжелее читаются, усугубляется еще тем что надо вычитывать где захваченные переменные снаружи где захваченые из внешней лямбды, где свои. А тут достаточно мельком глянуть и все сразу видно, где что:
Здравствуйте, Silver_s, Вы писали:
S_> А что касается именования в C#, это дело вкуса. Мне первый вариант нравится даже больше. S_>В лямбдах указывать длинные имена из нескольких слов как то не очень,
Используй одно- или двух-буквенные имена. Но это все же будут имена, а не безликие _1.
S_>Имена "e", "x" и прочие все равно ни о чем не говорят,
Очень даже говорят. Ты же сам говоришь, что все это в контексте применения. Если мы имеем дело с эмплоерами применение e будет вполне понятно и адекватно.
S_>а только усложняют чтение т.к. надо убедиться что этот x не снаружи захвачен.
Лямбды обычно очень мелкие, так что имена видно сразу. Плюс есть помощью IDE. Навел мышку на имя и увидел где одно определено.
S_>Выражения с вложенными лямбдами вобще тяжелее читаются, усугубляется еще тем что надо вычитывать где захваченные переменные снаружи где захваченые из внешней лямбды, где свои. А тут достаточно мельком глянуть и все сразу видно, где что:
S_>
Здравствуйте, VladD2, Вы писали:
L>>Задача — написать функцию, возвращающую список путей к файлам/директориям, находящимся в указанной директории на любом уровне вложенности, и удовлетворяющим определённому условию. VD>Что за условие?
Определённное Т.е. то, что определил пользователь функции — например, предикат File -> Bool, переданный в эту функцию, если говорить в терминах реализации.
Здравствуйте, VladD2, Вы писали:
VD>Проще привести обратный пример, так как попытавшись это сделать поймешь что получается бред.
Ну, в boost::bind это делается в другом синтаксисе, как бы через перечисление имени исходной ф-ии и следом всех подставляемых в нее аргументов.
VD>А так как есть сейчас. В свободные параметры записываются "_", в остальные выражения. Например: VD>
VD>x = someList.Filter(_ is SomeType); // Частичное применение оператора. Результат: функция с одним аргументом возвращающая bool
VD>y = ints.Reduce(_ + _); // Частичное применение оператора. Результат: функция с двумя аргументами суммирующая их
VD>def f = SomeMethod(_, "тест"); // Частичное применение функции/метода. Результат: функция с одним аргументом аналогичная: x => SomeMethod(x, "тест")
VD>f(z);
VD>
А что насчет порядковых номеров аргументов? Например, в boost::bind для частичного применения используются т.н. placeholders, которые обозначают эти порядковые номера.
Выглядит это все примерно так:
Есть ли нечто подобное в N?
Т.е. предположим что существует некий класс/неймспейс bind такой, чтобы можно было указывать порядковые номера аргументов, получая нечто вроде:
op_minus = ints.Reduce(_ - _); // это одно _1 - _2
difference = ints.Reduce(bind::_2 - bind::_1) // а это совсем другое
S_>В лямбдах указывать длинные имена из нескольких слов как то не очень, название коллекции говорит само за себя, что то там внутри лежит и так понятно. Имена "e", "x" и прочие все равно ни о чем не говорят, а только усложняют чтение т.к. надо убедиться что этот x не снаружи захвачен. S_>Выражения с вложенными лямбдами вобще тяжелее читаются, усугубляется еще тем что надо вычитывать где захваченные переменные снаружи где захваченые из внешней лямбды, где свои. А тут достаточно мельком глянуть и все сразу видно, где что:
Сделать так, чтобы студия подсвечивала или выделяла болдом захваченные x,e — достаточно просто. И студия уже сейчас при даблклике выделяет все вхождения если есть сомнения насчёт захвата. Имхо это куда лучше будет чем коверкание синтаксиса лямбд ради непонятно чего. Да и плюсов слишком мало, короче был бы тут Эрик Липперт — сказал бы что фича порог -100 не проходит.
Кроме того в Nemerle и половины проблем нет тех которые есть в C#, просто из-за того что всё иммутабельно. Ну напутаешь ты с именами раз, захватишь чего-то, да и при этом случайно попадёшь в !тот же! тип. И получишь легко воспроизводимый бажок, который можно за секунду найти.
V>А что насчет порядковых номеров аргументов? Например, в boost::bind для частичного применения используются т.н. placeholders, которые обозначают эти порядковые номера. V>Есть ли нечто подобное в N? V>Т.е. предположим что существует некий класс/неймспейс bind такой, чтобы можно было указывать порядковые номера аргументов, получая нечто вроде: V>
V>op_minus = ints.Reduce(_ - _); // это одно _1 - _2
V>difference = ints.Reduce(bind::_2 - bind::_1) // а это совсем другое
V>
Мэйнстрим движется вообще в противоположную сторону — к передаче аргументов по имени, а номера это откат к ассемблерам.
Какую проблему решаем? Зачем в реальной жизни нужны порядковые номера аргументов?
def op_minus = _ - _; //вот операцияdef difference(x, y) { op_minus(y, x); } //а тут нам понадобилось "совсем другое"
G>Насчет проще изучать тоже спорный вопрос. Много ли учебным материалов по макросам Nemerle?
Я когда людей сажал за Nemerle — давал 2 первых статьи Влада (остальные когда писать нормально начали), плюс объясняли принципы функционального программирования тем кто не знал. Этого достаточно чтобы начать писать на Nemerle чуть лучше чем на C#. А метапрограммирование и рюшечки — потом.
G>Я нарыл четыре с половиной статьи, но примеры в них или слишком сложные, или нафиг ненужные.
Так напиши нужные Вот возьми и напиши кусок кода который тебе нужен так как получается. И спроси на форуме где чувствуешь что можно лучше, но не получается. А как доведём до идеала — опубликуем реальный нужный и простой пример.
G>Единственное показалось достойным — скринкасты по применению макросов в каком-то веб-приложении, ссылку к сожалению уже не найду.
Т.е. кто-то таки осилил, причём сразу с макросами. Нашёл же человек инфу где-то. И понадобилось в реальном приложиении. А ты для своего проекта получается не сдюжишь?
G>Ну собственно и все, ни книг нету, ни в блога о nemerle не пишут и в реальных (необязательно коммерческих) проектах nemerle не найдешь.
Что в этой книге должно быть? Какой именно информации нехватает? Неужели её совсем нет на nemerle.org, нет в статьях Влада, и она ни разу не обсуждалась на форуме?
Когда я решал переходить на N или нет — статей было всего пара штук, интеграция половину времени отваливалась, автокомплит показывал только пару ключевых слов. Нужные фичи дописывал сам. И таки осилил, а ты ноешь сейчас, когда даже express-версия есть и куча макробиблиотек, бери да изучай.
_>def op_minus = _ - _; //вот операция_>def difference(x, y) { op_minus(y, x); } //а тут нам понадобилось "совсем другое"_>
Не понял твой сумбур. При чем тут имена аргументов, для частичного применения в общем виде, т.е. когда произвольная подходящая ф-ия можут быть подана?
И у тебя в строке "совсем другое" просто роспись в бессилии, ибо традиционного способа никакие карринги и частичные применения не нужны.
Здравствуйте, hi_octane, Вы писали:
G>>Насчет проще изучать тоже спорный вопрос. Много ли учебным материалов по макросам Nemerle? _>Я когда людей сажал за Nemerle — давал 2 первых статьи Влада (остальные когда писать нормально начали), плюс объясняли принципы функционального программирования тем кто не знал. Этого достаточно чтобы начать писать на Nemerle чуть лучше чем на C#.
А при чем здесь немерле ? Тренинги по C# и функциональщине разве нельзя проводить ?
Материал из Википедии — свободной энциклопедии, -_*
Здравствуйте, hi_octane, Вы писали:
_>Какую проблему решаем? Зачем в реальной жизни нужны порядковые номера аргументов? _>
_>def op_minus = _ - _; //вот операция_>def difference(x, y) { op_minus(y, x); } //а тут нам понадобилось "совсем другое"_>
Может тогда сразу:
def difference(x, y) { y — x; }
Считать то всеравно прийдется, тыкая карандашом в монитор, раз,два,три,четыре: Func(_,5,_,"str",_,_)
Чтобы на пришлось считать прийдется такие комментарии писать
Func(_ /*первый аргумент*/ ,5,_ /*... аргумент*/ ,"str",_ /*... аргумент*/,_ /*... аргумент*/)
LR>А при чем здесь немерле ? Тренинги по C# и функциональщине разве нельзя проводить ?
По функциональщине вообще на листике с ручкой и без особого синтаксиса проводили. К тому-же в то время был C#2, а он ну очень слаб и многословен, даже лямбд нету.
Здравствуйте, Silver_s, Вы писали:
S_> Может тогда сразу: S_> def difference(x, y) { y — x; }
S_>Считать то всеравно прийдется, тыкая карандашом в монитор, раз,два,три,четыре: Func(_,5,_,"str",_,_)
Специально оставил предыдущий твой абзац в цитировании. Ты абсолютно прав, ибо любой карринг и частичное применение — write-only, так же, как и туплы в качестве возвращаемого значения. Зато замечательно эти инструменты подходят для решений "по-месту", которые не имеют самостоятельной ценности, т.е. обычно выкидываемы вместе с объемлющим целевым решением, если не подошли. В общем, создавай себе именные ф-ии с такими же аргументами, там где требуется читабельность и сопровождаемость. А тут мы обсуждали возможности языков именно в плане "быстренько по-месту".
Здравствуйте, WolfHound, Вы писали:
WH>Я вообще думаю о том чтобы сделать не столько макросы сколько движок для создания статически типизированных eDSL со своей семантикой и системой типов.
Да, библиотека поддержки создания компиляторов. Абсолютно правильно. И рядом с ней — совместимую библиотеку поддержки интерпретаторов под эти же (статически-типизируемые) языки. Вот в таком уже можно и поучаствовать. Ибо регулярно надо.
WH>А базовый немерле сделать просто одним из частных случаев.
+100
Тем более, что и в ML-синтаксисе можно сделать нечто более привычное функциональщикам, но с сохранением макро-фич.
WH>Как следствие придется делать расширемым не только парсер но и поиск имен и вывод типов и кодогенератор.
Не принципиально. Главное, чтобы они были достаточно универсальны без заточки на конкретный язык. А это уже потребуется нескучный дизайн представления метаинформации для библиотеки...
Здравствуйте, vdimas, Вы писали:
V>Ну, в boost::bind это делается в другом синтаксисе, как бы через перечисление имени исходной ф-ии и следом всех подставляемых в нее аргументов.
В Бусте каррингом и не пахнет. Там синтаксис для сделан. Это все же разные вещи.
V>А что насчет порядковых номеров аргументов?
А зачем? Повторяю еще раз. Нет задачи сделать более короткий синтаксис для лямбд. Он и так весьма не плох. Была задача сделать частичное применение фцнций и оператора. И эта задача решена.
V>
Нет и не будет, так как уже есть полноценные лямбды и локальные фукнции для полдобных случаев. Сразвни сам. Вариант с лямбдой:
def newFunc = (a, b) => someFunc(a, "test", a, b);
Вариант с локальной функцией:
def newFunc(a, b) { someFunc(a, "test", a, b) }
На фиг экономить на спичках теряя читабельность?
V>Т.е. предположим что существует некий класс/неймспейс bind такой, чтобы можно было указывать порядковые номера аргументов, получая нечто вроде: V>
V>op_minus = ints.Reduce(_ - _); // это одно _1 - _2
V>difference = ints.Reduce(bind::_2 - bind::_1) // а это совсем другое
V>
Да не нужно это на практике.
Тут оно вообще как. Вот есть теоретики вроде Воронкова, которые рассуждают абстракно ("в общем"), а есть практики. Практик он проблемы не обсуждает, а чует жопрой. Надоедает этому практику что-то и он начинает говорить об устранении этого чего-то. Но пока это что-то не вызывает боли в заднице, то и осбуждать нечего. Вот вопрос частичного применения и синтаксиса для лямбд он как раз такой. На практике, используя Nemerle, никто не пользуется операторами вроде |> и >> (хотя они есть), так как используют методы расширений (создать которые можно в течении минуты). Ощущения нехватки короткого синтаксиса для лямбд тоже нет, так как создавать переходники для фукнций нужно не часто и это без прблем можно сделать обычной лямбдой.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Silver_s, Вы писали:
S_> Может тогда сразу: S_> def difference(x, y) { y — x; }
Дык так и делают в большинстве случаев. Точнее для операторов конечно проще частичное применение. А вот для чего-то сложного локальные функции или лямбды очень удобны. Там ведь и посчитать можно, и точку останова поставить...
S_>Считать то всеравно прийдется, тыкая карандашом в монитор, раз,два,три,четыре: Func(_,5,_,"str",_,_) S_>Чтобы на пришлось считать прийдется такие комментарии писать
Вот такой вот хрени в коде я пока не видел. Обычно свободным оставляется один параметр. Так что если не использовать высосанные из пальца примеры, то все получается замечательно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Silver_s, Вы писали:
S_>> Может тогда сразу: S_>> def difference(x, y) { y — x; }
S_>>Считать то всеравно прийдется, тыкая карандашом в монитор, раз,два,три,четыре: Func(_,5,_,"str",_,_)
V>Специально оставил предыдущий твой абзац в цитировании. Ты абсолютно прав, ибо любой карринг и частичное применение — write-only, так же, как и туплы в качестве возвращаемого значения.
-1 000 000
V> Зато замечательно эти инструменты подходят для решений "по-месту", которые не имеют самостоятельной ценности, т.е. обычно выкидываемы вместе с объемлющим целевым решением, если не подошли. В общем, создавай себе именные ф-ии с такими же аргументами, там где требуется читабельность и сопровождаемость. А тут мы обсуждали возможности языков именно в плане "быстренько по-месту".
Решение по месту хорошо пока оно простое. Дальше начинают отлично работать локальные функции.
ЗЫ
Если не философствовать, а пробовать обсуждаемые вещи на практике, то становится отчетливо видно, что в этой теме идет борьба с ветряными мельницами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>>>Задача — написать функцию, возвращающую список путей к файлам/директориям, находящимся в указанной директории на любом уровне вложенности, и удовлетворяющим определённому условию. VD>>Что за условие?
L>Определённное Т.е. то, что определил пользователь функции — например, предикат File -> Bool, переданный в эту функцию, если говорить в терминах реализации.
Ну, так и нужно писать — "предикат определяемый пользователем".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
L>>Определённное Т.е. то, что определил пользователь функции — например, предикат File -> Bool, переданный в эту функцию, если говорить в терминах реализации. VD>Ну, так и нужно писать — "предикат определяемый пользователем".
Не хотелось привязываться к реализации.
Ну что, покажешь? У меня сомнения вот в этом:
VD>Хотя смысл в этом в общем-то отсутствует. Ведь достаточно понять, что почти любой код который можно написать на хаскеле можно повторить на немреле 1 в 1. Другим будет только синтаксис, список функций, подход к ленивости и подход к полиморфизму. Собственно на то он и ФЯ, чтобы можно было одни идиомы использовать.
Т.е. то, что повторить можно, это естественно, важно повторить удобно. А это мне кажется невозможным в общем случае, что наш конкретный случай и демонстрирует — в моей дискуссии с samius. Т.к. средства языка позволяют более удобно выражать одни мысли и менее удобно другие. В связи с чем и появляются специфичные для конкретного языка идиомы. Например, в нашем примере на Haskell присутствует ленивое дерево, позволяющее разделить две функции — фильтрации и генерации дерева, что, очевидно, добавляет модульности программе. На C#/Nemerle ленивое дерево строится сложнее, чем список, поэтому там скорее всего функции фильтрации и генерации будут объединены.
Больше скажу, есть сомнения в том, что Nemerle/Scala функциональные языки. Для меня функциональный язык не тот, что позволяет писать функциональный код (Ява тоже позволяет), а тот, который позволяет делать это удобно. Здесь могут быть разногласия в термине "удобно" — критерием является только практика — как много на этих языках пишут функциональный код. Как показывает моя практика на Scala и сообщения типа этого
Здравствуйте, lomeo, Вы писали:
L>Больше скажу, есть сомнения в том, что Nemerle/Scala функциональные языки. Для меня функциональный язык не тот, что позволяет писать функциональный код (Ява тоже позволяет), а тот, который позволяет делать это удобно. Здесь могут быть разногласия в термине "удобно" — критерием является только практика — как много на этих языках пишут функциональный код. Как показывает моя практика на Scala и сообщения типа этого
Здравствуйте, VladD2, Вы писали:
VD>Если не философствовать, а пробовать обсуждаемые вещи на практике, то становится отчетливо видно, что в этой теме идет борьба с ветряными мельницами.
Дык, из практики примеры и привожу. В С++ нет замыканий, поэтому через boost::bind делается, скажем так, чуть больше, чем ты делаешь через '_'. И без адресации параметров зачастую никак.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>А что на твой взгляд мешает гибридным языкам быть "по-настоящему" функциональными? Кстати, OCaml — функциональный язык?
Я пока не готов ответить на твой вопрос. Мне кажется, что это связано с жёсткой реализацией ОО, под которую нужно подстраиваться, но я пока не могу это обосновать. Более очевидная причина — императивность и как следствие энергичность и impurity — не так интересна. Истинно функциональный язык — это лямбда исчисление
Здравствуйте, lomeo, Вы писали:
L>Я пока не готов ответить на твой вопрос. Мне кажется, что это связано с жёсткой реализацией ОО, под которую нужно подстраиваться, но я пока не могу это обосновать.
Хех, я как-то пытался высказать мысль, что ООП и ФП идеологически не совместимы, но, видимо, удачно сформулировать это у меня не получается. В итоге меня закидали шапками.
L>Более очевидная причина — императивность и как следствие энергичность и impurity — не так интересна. Истинно функциональный язык — это лямбда исчисление
А не получится ли так, что истинно-функциональный язык должен быть обязательно ленив? Что в общем-то не лишено смысла — ведь именно энергичность приводит к тому, что язык по-прежнему рассматривает программу как *последовательность* операций, пусть и выраженную более декларативно? Но тогда у нас ФП очень сильно сужается
Здравствуйте, Воронков Василий, Вы писали:
ВВ>А не получится ли так, что истинно-функциональный язык должен быть обязательно ленив? Что в общем-то не лишено смысла — ведь именно энергичность приводит к тому, что язык по-прежнему рассматривает программу как *последовательность* операций, пусть и выраженную более декларативно? Но тогда у нас ФП очень сильно сужается
Вообще-то ленивые языки с аппликативным порядком вычислений не менее детерминированы чем строгие, просто правила чуть сложнее для восприятия.
Ну и чистота вообще ортогональна строгости.
Здравствуйте, FR, Вы писали:
ВВ>>А не получится ли так, что истинно-функциональный язык должен быть обязательно ленив? Что в общем-то не лишено смысла — ведь именно энергичность приводит к тому, что язык по-прежнему рассматривает программу как *последовательность* операций, пусть и выраженную более декларативно? Но тогда у нас ФП очень сильно сужается FR>Вообще-то ленивые языки с аппликативным порядком вычислений не менее детерминированы чем строгие, просто правила чуть сложнее для восприятия.
Я не говорю, что они не детерминированы. Вообще что такое "недетерминированный" язык? Как на таком в принципе можно написать что-то полезное? Просто, как бы это сказать, программу даже на OCaml я могу читать в стиле — вот здесь я получаю то-то и то-то, здесь я трансформирую это в то-то и так далее. Программу на Хаскеле я так читать не буду. Опять же мне сложновато это с ходу сформулировать. В энергичном языке у меня программа вычисляется. В ленивом она как бы уже вычислена изначально — нет последовательности *вычислений* (что, конечно же, не означает, что в ленивых языках нет вообще никакой последовательности ).
FR>Ну и чистота вообще ортогональна строгости.
Мне кажется не совсем. Ну т.е. энергичный язык, конечно же, может быть чистым, но вот "грязный" ленивый язык я себе вообще не представляю Вернее, представить-то можно, но это будет какая-то дичь.
Здравствуйте, VladD2, Вы писали:
V>>Ну, в boost::bind это делается в другом синтаксисе, как бы через перечисление имени исходной ф-ии и следом всех подставляемых в нее аргументов.
VD>В Бусте каррингом и не пахнет. Там синтаксис для сделан. Это все же разные вещи.
Если связываемый аргумент является константой, то это и есть карринг:
typedef int(*int_op)(int, int);
function<int(int)> inc = bind((int_op)operator+, _1, 1);
int x = inc(10); // x=11
VD>А зачем? Повторяю еще раз. Нет задачи сделать более короткий синтаксис для лямбд. Он и так весьма не плох. Была задача сделать частичное применение фцнций и оператора. И эта задача решена.
Да согласен, синтаксически через лямбды неплохо получается. А зачем тогда встала задача вводить частичное применение для операторов, если синтаксис лямбд такой короткий? Еще на пару символов укоротить?
Здравствуйте, Воронков Василий, Вы писали:
L>>Я пока не готов ответить на твой вопрос. Мне кажется, что это связано с жёсткой реализацией ОО, под которую нужно подстраиваться, но я пока не могу это обосновать. ВВ>Хех, я как-то пытался высказать мысль, что ООП и ФП идеологически не совместимы, но, видимо, удачно сформулировать это у меня не получается. В итоге меня закидали шапками.
Я немного о другом. В гибридных языках есть определённая жёсткая реализация ОО. Вполне возможно, что в жертву такому дизайнерскому решению приносятся некоторые особенности, которые сильно облегчили бы использование ФП. Это пока всего лишь чувство, появившееся после использования Scala.
L>>Более очевидная причина — императивность и как следствие энергичность и impurity — не так интересна. Истинно функциональный язык — это лямбда исчисление ВВ>А не получится ли так, что истинно-функциональный язык должен быть обязательно ленив?
ВВ>Что в общем-то не лишено смысла — ведь именно энергичность приводит к тому, что язык по-прежнему рассматривает программу как *последовательность* операций, пусть и выраженную более декларативно? Но тогда у нас ФП очень сильно сужается
Ну и пусть. Функциональный подход — это работа с функциями. Если я вижу разбор ПМ-ом типа данных из другого модуля, или явную рекурсию — для меня этот код менее функционален, поскольку использует явную работу с данными.
Я, например, иногда встречал даже такой код (не говоря о более сложных вариантах)
А всё потому, что человек думал о данных, а не о функциях. Например, для многих этот код запишется как второй вариант потому, что это узнаваемый паттерн, а не потому что они думают в терминах функций, отбрасывая данные.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Я не говорю, что они не детерминированы. Вообще что такое "недетерминированный" язык? Как на таком в принципе можно написать что-то полезное?
Конечно можно, например в SICP есть пример недетерминированного интерпретатора схемы, вводится всего одна особая форма 'amb' http://mitpress.mit.edu/sicp/full-text/sicp/book/node91.html по мощности вполне пролог перекрывает, и даже в реальных схемах http://wiki.call-cc.org/eggref/4/amb?action=show и кажется в диалектах ML присутствует.
ВВ>Просто, как бы это сказать, программу даже на OCaml я могу читать в стиле — вот здесь я получаю то-то и то-то, здесь я трансформирую это в то-то и так далее. Программу на Хаскеле я так читать не буду. Опять же мне сложновато это с ходу сформулировать. В энергичном языке у меня программа вычисляется. В ленивом она как бы уже вычислена изначально — нет последовательности *вычислений* (что, конечно же, не означает, что в ленивых языках нет вообще никакой последовательности ).
Посмотри тот же SICP в начальных главах там объясняются нормальный и аппликативный порядки вычислений, сложность у них одинаковая. Но нормальный порядок
конечно гораздо лучше ложится на последовательное человеческое мышление и поэтому воспринимается намного легче.
FR>>Ну и чистота вообще ортогональна строгости.
ВВ>Мне кажется не совсем. Ну т.е. энергичный язык, конечно же, может быть чистым, но вот "грязный" ленивый язык я себе вообще не представляю Вернее, представить-то можно, но это будет какая-то дичь.
Да вполне возможно, но программировать на нем.. наверно легче застрелится
Здравствуйте, lomeo, Вы писали:
L>Я немного о другом. В гибридных языках есть определённая жёсткая реализация ОО. Вполне возможно, что в жертву такому дизайнерскому решению приносятся некоторые особенности, которые сильно облегчили бы использование ФП. Это пока всего лишь чувство, появившееся после использования Scala.
У меня вот нет опыта программирования на Scala. У многих здесь, я думаю, тоже. У тебя же, как я понимаю, нет опыта программирования на Немерле. В итоге тема получается достаточно туманной.
Например, было бы очень интересно, если бы ты перечислил те особенности, которые в Scala были принесены в "жертву ООП". Я же так понимаю, речь идет не только об очевидных вещах вроде неудобное каррирование и композиция.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Например, было бы очень интересно, если бы ты перечислил те особенности, которые в Scala были принесены в "жертву ООП". Я же так понимаю, речь идет не только об очевидных вещах вроде неудобное каррирование и композиция.
Если исключить каррирование можно посмотреть разницу между F# и OCaml в первом мейнстримный ООП во втором ООП вполне (насколько это вообще возможно)
гармонично вписанный в ФЯ.
Здравствуйте, FR, Вы писали:
FR>Если исключить каррирование можно посмотреть разницу между F# и OCaml в первом мейнстримный ООП во втором ООП вполне (насколько это вообще возможно) FR>гармонично вписанный в ФЯ.
Ну это проблемы F#, а не ООП. F# адаптировали под имеющуюся систему типов, которая создавалась явно не для ФЯ. В этом-то и кроется основная проблема. Возможно, в Scala сходные проблемы .
Опять же в F# все же присутствует четкое разделение на два мира. Т.е. из-за того, что к нему прикрутили "мейнстримный ООП" ФП не стал менее удобным.
Может, тут на самом деле ларчик просто открывается? Когда дизайнеры языка не хотят делать швы, а пытаются не просто "внедрить ООП", а полноценно приспособить язык к уже существующей платформе, чтобы он был "как родной", то это неизбежно ведет к некоторым компромиссам, и в итоге ФП получается "менее удобным".
Здравствуйте, FR, Вы писали:
FR>Посмотри тот же SICP в начальных главах там объясняются нормальный и аппликативный порядки вычислений, сложность у них одинаковая. Но нормальный порядок FR>конечно гораздо лучше ложится на последовательное человеческое мышление и поэтому воспринимается намного легче.
Воспринимается легче как раз аппликативный (evaluate the arguments and then apply).
Здравствуйте, samius, Вы писали:
S>Воспринимается легче как раз аппликативный (evaluate the arguments and then apply).
Да вечно их путаю
Конечно аппликативный легче воспринимается и используется в энергичных языках, а ленивый язык получается из языка с нормальным
порядком простой задержкой вычислений до тех пор пока они реально не потребуются.
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, samius, Вы писали:
S>>Воспринимается легче как раз аппликативный (evaluate the arguments and then apply).
FR>Да вечно их путаю
Я просто один раз запомнил, что то что кажется нормальным (привычным) не является формально нормальным порядком.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Например, было бы очень интересно, если бы ты перечислил те особенности, которые в Scala были принесены в "жертву ООП". Я же так понимаю, речь идет не только об очевидных вещах вроде неудобное каррирование и композиция.
1. Сложность реализации higher-order полиморфизма + неочевидность записи — сравни с Haskell. Мне кажется это из-за изначальной диспетчеризации по одному параметру.
Что за? Это же функции, а не методы, тут this совсем не будет использоваться.
2. Такое часто — из-за trait предпочитается ОО-полиморфизм вместо функционального — методы вместо функций. Если использовать объекты как неймспейс (объект — это синглтон в Scala, аналог модуля), то можно писать в ФП стиле в принципе.
3. В моих программах на Haskell мало ПМ, в программах на Scala — много. Видно, где я больше работаю с данными. С чем связано — пока не знаю. Может персональное.
4. Про карринг будем говорить. Я вынужден писать полную сигнатуру (с названиями параметров!) в Scala. В Haskell эта-редуцированная форма используется очень часто и не захламляет код. Cм мой пример с salaries, как бы определение этой фунции выглядело в Scala, чтобы было таким же:
А если тип — сложный generic (взятый из typeclasses в Haskell) — то сигнатура получается гораздо сложнее.
В Nemerle вывод типов, слышал, гораздо сильнее, поэтому возможно, что там будет
Здравствуйте, lomeo, Вы писали:
L>1. Сложность реализации higher-order полиморфизма + неочевидность записи — сравни с Haskell. Мне кажется это из-за изначальной диспетчеризации по одному параметру. L>2. Такое часто — из-за trait предпочитается ОО-полиморфизм вместо функционального — методы вместо функций. Если использовать объекты как неймспейс (объект — это синглтон в Scala, аналог модуля), то можно писать в ФП стиле в принципе.
А почему так выходит? Ведь traits по идее те же классы типов, вид сбоку. Мои познания Хаскеля правда основаны на книжке "с картинками" (хорошо хоть, не "раскраска"), но вроде как полиморфизм через классы типов производит впечатление вполне законной фичи, опять же проследить тут некоторую аналогию с ООП несложно.
L>3. В моих программах на Haskell мало ПМ, в программах на Scala — много. Видно, где я больше работаю с данными. С чем связано — пока не знаю. Может персональное.
Это момент интересный. Мало ПМ потому что более активно используется — в широком смысле — лямбда-исчисление? Т.е. вместо операций над данными, операции над функциями, в Скале же — наоборот, а причиной тому, видимо, что операции над функциями менее удобны? Ну т.е. в сущности это все те же самые "неудобные каррирование, композиция" и проч. Заметь, кстати, тут Влад тебе где-то по-соседству говорит, что в Немерле всякие ">>" и "<<" (в Хаскеле, я так понимаю, это ".") используются не так часто. Тоже показательно весьма.
Я к чему веду-то собственно — мне кажется, что в языке, подобном Немерле (и возможно Скала) сделать более удобные операции над функциями вполне можно.
L>4. Про карринг будем говорить. Я вынужден писать полную сигнатуру (с названиями параметров!) в Scala. В Haskell эта-редуцированная форма используется очень часто и не захламляет код. Cм мой пример с salaries, как бы определение этой фунции выглядело в Scala, чтобы было таким же: L>
L>А если тип — сложный generic (взятый из typeclasses в Haskell) — то сигнатура получается гораздо сложнее. L>В Nemerle вывод типов, слышал, гораздо сильнее, поэтому возможно, что там будет L>
L>def salaries = _.Map(_.salary)
L>
L>не знаю.
Ну в этом конкретном примере, что конкретно "рулит"? Вывод типов — убираем объявления. Каррированность функций. Лаконичный синтаксис для лямбд.
Например, как бы этот пример мог выглядеть у меня:
>let map(f, l) on _,x::xs -> f(x) + map(f, xs) on _,[] -> 0;
>let list = [(salary:120),(salary:12),(salary:245)]
>let salaries = map(_.salary)
>salaries(list)
377
Достаточно лаконично вроде. Если бы каррирования не было, то пришлось бы писать так:
>let salaries = map(_.salary, _)
Хуже. Но в конкретном примере — некритично. Вот вариант Скалы — да, длинноват.
Здравствуйте, Воронков Василий, Вы писали:
FR>>Ну и чистота вообще ортогональна строгости.
ВВ>Мне кажется не совсем. Ну т.е. энергичный язык, конечно же, может быть чистым, но вот "грязный" ленивый язык я себе вообще не представляю Вернее, представить-то можно, но это будет какая-то дичь.
И правильно, ленивость с наблюдаемыми сайд-эффектами ведет к непредсказуемому поведению.
Здравствуйте, lomeo, Вы писали:
L>Например, в нашем примере на Haskell присутствует ленивое дерево, позволяющее разделить две функции — фильтрации и генерации дерева, что, очевидно, добавляет модульности программе. На C#/Nemerle ленивое дерево строится сложнее, чем список, поэтому там скорее всего функции фильтрации и генерации будут объединены.
1. Нет проблем слабать ленивое дерево и на немрел. На то есть lazy. Ленивость конечно явная, но не думаю, что это создаст такие уж проблемы.
2. Задача твоя не требует работать с деревом как с деревом. Если я ее првильно понял, в задаче требуется ленивый обход дерева. А это не тоже самое. И это легко делается итераторами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Больше скажу, есть сомнения в том, что Nemerle/Scala функциональные языки. Для меня функциональный язык не тот, что позволяет писать функциональный код (Ява тоже позволяет), а тот, который позволяет делать это удобно. Здесь могут быть разногласия в термине "удобно" — критерием является только практика - как много на этих языках пишут функциональный код.
Золотые слова! Предлагая отборосить сомнения и начать практиковаться. А то в подобных рассуждениях без потери смысла можно заменить все слова:
Больше скажу, есть сомнения в том, что Хаскель функциональные языки. Для меня функциональный язык не тот, что позволяет писать функциональный код (Ява тоже позволяет), а тот, который позволяет делать это удобно. Вот писать на Хаскеле совершенно неудобно. Моя практика это всецело подтверждает .
L>Как показывает моя практика на Scala и сообщения типа этого
для гибридных языков есть ограничения Но это уже другой вопрос.
У всго на свете есть ограничения. Напиши что-то по сложнее детских примеров и вопросы твои отпадут сами собой. В прочем, ты все равно будешь пытаться отыскать Хаскель в любом языке. Так что без перестройки сознания ты так и останешься при своих убеждениях.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Я немного о другом. В гибридных языках есть определённая жёсткая реализация ОО. Вполне возможно, что в жертву такому дизайнерскому решению приносятся некоторые особенности, которые сильно облегчили бы использование ФП. Это пока всего лишь чувство, появившееся после использования Scala.
Гнилая философия опровергаемая практикой. А практика показывает, что ООП отлично подходит для дизайна системы, или иными словами крупноблочного программирования, а ФП при этом может являеться отличным средством борьбы с рзабуханием тел методов. Таким образом вместе они создают отличный тандем. ООП — дизайн системы, ФП — ее внутрення реализация и склеивание частей (например, реактивное программирование). Сюда же отлично подходит и МП.
Простой пример. Когда мы пишем парсер, то ФП и МП рулит, так как мы трансформируем что-то во что-то (грамматику в ее АСТ, АСТ в код парсера...). Когда мы пишем ГУЙ который позволяет отредактировать код, отпарсить его и вывести сообщения об ошибках, то рулит ООП. Когда мы пытаемся объедение все это в более большую систему, то опят же рулит ООП, или даже КООП, так как мы уже оперируем крупными строительный блоками.
И похоже, что ты уперся в код функций и боишься или не можешь взглянуть чуть выше. Вот и начинаются разговоры о трансформации миров и т.п. А кому они нужны то на практике? Кнопка они и в Африке кнопка. В философии трансформации мира она не нуждается. Она нуждается в банальном состоянии.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>4. Про карринг будем говорить. Я вынужден писать полную сигнатуру (с названиями параметров!) в Scala. В Haskell эта-редуцированная форма используется очень часто и не захламляет код. Cм мой пример с salaries, как бы определение этой фунции выглядело в Scala, чтобы было таким же: L>
L>А если тип — сложный generic (взятый из typeclasses в Haskell) — то сигнатура получается гораздо сложнее. L>В Nemerle вывод типов, слышал, гораздо сильнее, поэтому возможно, что там будет L>
L>def salaries = _.Map(_.salary)
L>
L>не знаю.
Так и есть. Вот реальный пример:
[Record] // автоматическая генерация конструктраclass A
{
public salary : int;
}
def salaries = _.Map(_.salary); // тип salaries list[A] -> list[int]
salaries([A(1), A(1)]) // если убрать эту функцию вывод типов не сработает
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, Воронков Василий, Вы писали:
ВВ>>Я не говорю, что они не детерминированы. Вообще что такое "недетерминированный" язык? Как на таком в принципе можно написать что-то полезное?
FR>Конечно можно, например в SICP есть пример недетерминированного интерпретатора схемы, вводится всего одна особая форма 'amb' http://mitpress.mit.edu/sicp/full-text/sicp/book/node91.html по мощности вполне пролог перекрывает, и даже в реальных схемах http://wiki.call-cc.org/eggref/4/amb?action=show и кажется в диалектах ML присутствует.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Ну в этом конкретном примере, что конкретно "рулит"? Вывод типов — убираем объявления. Каррированность функций. Лаконичный синтаксис для лямбд. ВВ>Например, как бы этот пример мог выглядеть у меня:
ВВ>
>>let map(f, l) on _,x::xs -> f(x) + map(f, xs) on _,[] -> 0;
>>let list = [(salary:120),(salary:12),(salary:245)]
ВВ>>let salaries = map(_.salary)
>>salaries(list)
ВВ>377
ВВ>
ВВ>Достаточно лаконично вроде. Если бы каррирования не было, то пришлось бы писать так:
Дык у тебя не Map, а Fold получился. Лаконичный бред .
И ни разу не более лаконичный нежели немерловый вариант.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>А почему так выходит? Ведь traits по идее те же классы типов, вид сбоку. Мои познания Хаскеля правда основаны на книжке "с картинками" (хорошо хоть, не "раскраска"), но вроде как полиморфизм через классы типов производит впечатление вполне законной фичи, опять же проследить тут некоторую аналогию с ООП несложно.
Например, trait реализуется конкретным классом, то есть аналогию c MPTC построить сложновато.
ВВ>Это момент интересный. Мало ПМ потому что более активно используется — в широком смысле — лямбда-исчисление? Т.е. вместо операций над данными, операции над функциями, в Скале же — наоборот, а причиной тому, видимо, что операции над функциями менее удобны? Ну т.е. в сущности это все те же самые "неудобные каррирование, композиция" и проч. Заметь, кстати, тут Влад тебе где-то по-соседству говорит, что в Немерле всякие ">>" и "<<" (в Хаскеле, я так понимаю, это ".") используются не так часто. Тоже показательно весьма.
Да. С чем это может быть связано?
ВВ>Я к чему веду-то собственно — мне кажется, что в языке, подобном Немерле (и возможно Скала) сделать более удобные операции над функциями вполне можно.
Да они и так уже достаточно удобные, только вот ими не пользуются.
ВВ>Ну в этом конкретном примере, что конкретно "рулит"? Вывод типов — убираем объявления. Каррированность функций. Лаконичный синтаксис для лямбд. ВВ>Например, как бы этот пример мог выглядеть у меня:
Окамл — не ОО язык. Тут он кажется не к месту.
ВВ>Хуже. Но в конкретном примере — некритично. Вот вариант Скалы — да, длинноват.
Здравствуйте, VladD2, Вы писали:
VD>Дык у тебя не Map, а Fold получился. Лаконичный бред .
Ага, хрень написал. Надо, видимо, как-то так:
let map(f, l) on _,x::xs -> f(x)::map(f, xs) on _,[] -> [];
Кстати, то же самое, но с экспериментальным ML-ным синтаксисом:
let map f x::xs = (f x)::(map f xs) | _ = [];
Скажи честно, тебе какой вариант больше нравится?
VD>И ни разу не более лаконичный нежели немерловый вариант.
Ну суть не в функции map. lomeo, как я понимаю, привык к этакой point free комбинаторике, а она — на мой взгляд — таки да требует для выразительности как каррирование, так и ML-ный синтаксис. Пример с зарплатами есть трансформация кода вида:
let salaries x = map salary x
Заметь, насколько естественным и красивым тут видится устранение этого самого "x". Так, возможно, неудобства, о которых говорит lomeo, комплексные. Часть могут быть и с синтаксисом связаны, почему нет.
Ага, спасибо, почитаю.
ВВ>>Это момент интересный. Мало ПМ потому что более активно используется — в широком смысле — лямбда-исчисление? Т.е. вместо операций над данными, операции над функциями, в Скале же — наоборот, а причиной тому, видимо, что операции над функциями менее удобны? Ну т.е. в сущности это все те же самые "неудобные каррирование, композиция" и проч. Заметь, кстати, тут Влад тебе где-то по-соседству говорит, что в Немерле всякие ">>" и "<<" (в Хаскеле, я так понимаю, это ".") используются не так часто. Тоже показательно весьма. L>Да. С чем это может быть связано?
Я не знаю
Мое подозрение — этому отчасти может мешать и менее наглядный Си-подобный синтаксис, к которому и в Немерле, и в Скала прилагается отсутствие каррирования "из коробки" (т.е. функции не являются уже каррированными).
А почему ты сам-то начинаешь более активно использовать ПМ? По логике — все нужные средства у тебя есть. Либо эти средства не работают (отсутствуют какие-либо необходимые возможности), либо они менее удобные — вроде другого не дано.
ВВ>>Ну в этом конкретном примере, что конкретно "рулит"? Вывод типов — убираем объявления. Каррированность функций. Лаконичный синтаксис для лямбд. ВВ>>Например, как бы этот пример мог выглядеть у меня: L>Окамл — не ОО язык. Тут он кажется не к месту.
Это не Окамл и да, пример, наверное, не к месту
А вот Окамл как раз — вполне ОО язык. "О" тут не случайно стоит. Причем Окамл — это МЛ, к которому прикрутили ООП так, как сочли нужным. Nemerle — язык, к которому прикрутили существующее ООП, которое уже было в платформе (в дотнете ж даже ассемблер объектно-ориентированный), причем постарались органично вписать в его сам язык (т.е. это повлияло на дизайн языка).
Т.е. если в Окамл — где задачка с зарплатами решается практически так же как на Хаскеле — ООП не вызывает неудобств, то значит не всякое ООП вредно для ФП.
Здравствуйте, VladD2, Вы писали:
VD>1. Нет проблем слабать ленивое дерево и на немрел. На то есть lazy. Ленивость конечно явная, но не думаю, что это создаст такие уж проблемы.
Слабать можно. Так делают?
VD>2. Задача твоя не требует работать с деревом как с деревом. Если я ее првильно понял, в задаче требуется ленивый обход дерева. А это не тоже самое. И это легко делается итераторами.
Конечно, не требует. Мне интересно посмотреть решение на итераторах, раз эта задача на Немерле скорее будет решена так.
VD>[Record] // автоматическая генерация конструктра
VD>class A
VD>{
VD> public salary : int;
VD>}
VD>def salaries = _.Map(_.salary); // тип salaries list[A] -> list[int]
VD>salaries([A(1), A(1)]) // если убрать эту функцию вывод типов не сработает
VD>
А на самом деле ты как напишешь этот код? Именно так или все же предпочтешь другое решение?
Честно, у меня есть сомнения — не доставай наган — что Немерлистом функция salaries будет вообще определена. В реальности (мне кажется) код будет скорее таким:
Здравствуйте, VladD2, Вы писали:
VD>Больше скажу, есть сомнения в том, что Хаскель функциональные языки. Для меня функциональный язык не тот, что позволяет писать функциональный код (Ява тоже позволяет), а тот, который позволяет делать это удобно. Вот писать на Хаскеле совершенно неудобно. Моя практика это всецело подтверждает .
Тебе на Хаскель удобнее писать императивный код?
VD>У всго на свете есть ограничения. Напиши что-то по сложнее детских примеров и вопросы твои отпадут сами собой. В прочем, ты все равно будешь пытаться отыскать Хаскель в любом языке. Так что без перестройки сознания ты так и останешься при своих убеждениях.
Ненаучный подход. Сначала выдвигается гипотеза, а потом даётся непроверяемое обоснование, в случае если она не сработает. Я тебя никак не смогу опровергнуть.
А так — да: любая смена убеждений подразумевает перестройку сознания, это вообще масло масляное Важна не смена убеждений, а основания для этой смены.
По теме:
1. Я писал (и пишу) вещи сложнее детских примеров на Scala. Вопросы только появляются.
2. Haskell в языках не ищу. Тем более в Scala, в которой совсем другие плюшки.
3. Разговор конкретный — язык заявляет о себе как о ФП, но в стиле ФП на нём пишут очень мало.
4. Есть исключение — работа с последовательностями (и то! см. пост Клапауциуса о nemerle-std), что заставляет думать, что это воспринимается как приём, а не как подход. Функционального кода не связанного со списками критически мало — я перед ответом специально облазил http://code.google.com/p/nemerle/source/browse/#svn/nemerle/trunk и ниже.
Под стилем ФП я понимаю стиль, описанный в Why FP matters, например.
Т.е. можно сделать кучу предположений почему так, но дело должно быть или в языке или в разработчиках. С одной стороны, поскольку есть другие языки, на которых те же разработчики пишут в ФП стиле, то можно предположить, что дело в языке. С другой стороны пункт 4 бросает тень на разработчиков. Возможно, истина где-то посередине. Я — не знаю, о чём с самого начала и написал.
Здравствуйте, lomeo, Вы писали:
L>Т.е. можно сделать кучу предположений почему так, но дело должно быть или в языке или в разработчиках. С одной стороны, поскольку есть другие языки, на которых те же разработчики пишут в ФП стиле, то можно предположить, что дело в языке. С другой стороны пункт 4 бросает тень на разработчиков. Возможно, истина где-то посередине. Я — не знаю, о чём с самого начала и написал.
Скорее дело больше в разработчиках и пользователях языка, вот например в OCaml наблюдается обратный перекос ОО возможности
используются редко, даже там где ОО вполне приемлем пишут на модулях и функторах.
Здравствуйте, VladD2, Вы писали:
L>>Я немного о другом. В гибридных языках есть определённая жёсткая реализация ОО. Вполне возможно, что в жертву такому дизайнерскому решению приносятся некоторые особенности, которые сильно облегчили бы использование ФП. Это пока всего лишь чувство, появившееся после использования Scala. VD>Гнилая философия опровергаемая практикой. А практика показывает, что ООП отлично подходит для дизайна системы, или иными словами крупноблочного программирования, а ФП при этом может являеться отличным средством борьбы с рзабуханием тел методов. Таким образом вместе они создают отличный тандем. ООП — дизайн системы, ФП — ее внутрення реализация и склеивание частей (например, реактивное программирование). Сюда же отлично подходит и МП.
1. Чья практика? Если твоя — то ты просто не пробовал другого. Если общая — то есть масса замечательных дизайнов, построенных без ООП.
2. Я могу написать что ООП отвратительно подходит для дизайна системы, но ты же скажешь, что я его просто неправильно готовлю, (= твоя практика > моей практики), верно?
3. При чём тут вообще это? В предположении говорилось совсем о другом. Ну подходит ООП для дизайна, а ФП для методов. Речь о компромиссах, на которые надо идти в случае их объединения в одном языке.
В любом случае, практикой эта "философия" не опровергнута, иначе бы я её отбросил. Потом. Это всего лишь предположение. Я думаю, что оно возможно, я не уверен, что так и есть.
VD>Простой пример. Когда мы пишем парсер, то ФП и МП рулит, так как мы трансформируем что-то во что-то (грамматику в ее АСТ, АСТ в код парсера...). Когда мы пишем ГУЙ который позволяет отредактировать код, отпарсить его и вывести сообщения об ошибках, то рулит ООП. Когда мы пытаемся объедение все это в более большую систему, то опят же рулит ООП, или даже КООП, так как мы уже оперируем крупными строительный блоками.
Мы уже о другом спорим, ну да ладно, почему бы и да?
Я считаю это всего лишь одним из подходов. Не самым лучшим, не самым худшим.
VD>И похоже, что ты уперся в код функций и боишься или не можешь взглянуть чуть выше. Вот и начинаются разговоры о трансформации миров и т.п. А кому они нужны то на практике? Кнопка они и в Африке кнопка. В философии трансформации мира она не нуждается. Она нуждается в банальном состоянии.
Это замечание я вообще не понял. Что значит "упёрся в код функций и боишься или не можешь взглянуть чуть выше"? Про состояние я тоже не понял. Трансформация миров, изменяемые состояния — это всего лишь возможные реализации поведения кнопки. Кроме них есть ещё масса. Как это связано с ООП?
Здравствуйте, lomeo, Вы писали:
L>1. Я писал (и пишу) вещи сложнее детских примеров на Scala. Вопросы только появляются. L>2. Haskell в языках не ищу. Тем более в Scala, в которой совсем другие плюшки. L>3. Разговор конкретный — язык заявляет о себе как о ФП, но в стиле ФП на нём пишут очень мало. L>4. Есть исключение — работа с последовательностями (и то! см. пост Клапауциуса о nemerle-std), что заставляет думать, что это воспринимается как приём, а не как подход. Функционального кода не связанного со списками критически мало — я перед ответом специально облазил http://code.google.com/p/nemerle/source/browse/#svn/nemerle/trunk и ниже. L>Под стилем ФП я понимаю стиль, описанный в Why FP matters, например.
Ты знаешь, тут замкнутый круг. Основная масса "обращенцев" в стан Немерле — это дотнетчики, которые ФП, пользуясь твоими словами, воспринимают именно как прием, а не как подход. (Они, кстати, совсем тут не виноваты — ибо именно так ФП и рекламируется самим вендором платформы, который тут царь и бог).
Те же для кого ФП — это совсем не прием смотрят на их код и думают, что Немерле — какой-то не "тру" функциональный язык, потому что в функциональном стиле на нем практически не пишут.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>lomeo, как я понимаю, привык к этакой point free комбинаторике
Большей частью я пишу на императивных языках, часто с поддержкой ОО. Основной язык — так вообще Java. Говорить, что я привык к pointfree по-моему неправильно.
Речь о моём представлении, что такое ФП. Возможно, оно сильно отличается от других.
Здравствуйте, lomeo, Вы писали:
L>Большей частью я пишу на императивных языках, часто с поддержкой ОО. Основной язык — так вообще Java. Говорить, что я привык к pointfree по-моему неправильно.
ОК, тогда я не угадал.
L>Речь о моём представлении, что такое ФП. Возможно, оно сильно отличается от других.
Пока мы говорили, что такое ФЯ. Для большинства здесь (опять попробую угадать) — ФЯ это язык, в котором есть ФП не обязательно в ущерб другим парадигмам. Так что неудивительно, если в каких-то случаях функциональному пути может быть выбран другой путь для решения проблемы. Есть, конечно, и более радикальная точка зрения.
"Что такое ФП" — вопрос по-моему уж очень сильно философский. Я вот затрудняюсь сформулировать.
Ну т.е. понятно, что в некой редуцированной форме для функционального программирования достаточно двух функций-комбинаторов, однако оно уже как-то очень далеко от практики.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>А почему ты сам-то начинаешь более активно использовать ПМ? По логике — все нужные средства у тебя есть. Либо эти средства не работают (отсутствуют какие-либо необходимые возможности), либо они менее удобные — вроде другого не дано.
Хороший вопрос! Чтобы на него ответить я стал пересматривать свой код и вот что обнаружил. Буду говорить на одном примере, чтобы выделить общую мысль на деталях.
Вот есть у меня разбор Option, а в одной из веток ещё один Option разбирается. Почему бы не сделать один разбор пары? Потому что лишнее вычисление, которое нужно выполнить только в одной из веток. Почему бы не использовать аналог функции maybe? Потому что у меня встречается императивный код.
В других случаях то же самое. Возможность смешивать императивный и функциональный код приводит к тому, что решения на таком смешанном коде + ПМ писать проще (и они, кстати, эффективнее), чем их предварительное разделение. Код получается достаточно понятный и эффективнее, чем ФП. Плата — бОльшая связанность. Возможность выделять типичные разборы ПМ в функции на самом деле неудобна из-за того, что части ПМ становятся аргументами (читай — энергично вычисляются). Делать их ленивыми — дополнительная работа, уменьшающая (правда, слегка) удобство и понятность.
Ещё момент — в ветке может часто оказаться несколько строчек (из-за смешивания). А делать их аргументами — будет уже не так симпатично выглядеть.
ВВ>Т.е. если в Окамл — где задачка с зарплатами решается практически так же как на Хаскеле — ООП не вызывает неудобств, то значит не всякое ООП вредно для ФП.
Здравствуйте, FR, Вы писали:
FR>Скорее дело больше в разработчиках и пользователях языка, вот например в OCaml наблюдается обратный перекос ОО возможности
Мы сменили язык — так что дело может быть и в нём Один и тот же человек, который пишет и на Nemerle и на Ocaml — использует одни и те же идиомы?
FR>используются редко, даже там где ОО вполне приемлем пишут на модулях и функторах.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, lomeo, Вы писали:
L>>Я немного о другом. В гибридных языках есть определённая жёсткая реализация ОО. Вполне возможно, что в жертву такому дизайнерскому решению приносятся некоторые особенности, которые сильно облегчили бы использование ФП. Это пока всего лишь чувство, появившееся после использования Scala.
VD>Гнилая философия опровергаемая практикой. А практика показывает, что ООП отлично подходит для дизайна системы, или иными словами крупноблочного программирования, а ФП при этом может являеться отличным средством борьбы с рзабуханием тел методов. Таким образом вместе они создают отличный тандем. ООП — дизайн системы, ФП — ее внутрення реализация и склеивание частей (например, реактивное программирование).
Практика как раз показывает что не подходит. Identity и инкапсуляция состояния обычно мешает уменьшает реюз кода. Что из ООП используется это интерфейсы (те группы функций) и динамическая диспетчеризация. Это то что в свое время назвали SOA.
F# например отлично поддерживает интерфейсы: позволяет создавать анонимные объекты, реализующие эти интерфейсы.
В haskell подобная работа с группами функций реализуется с помощью typeclasses и и расширений компилятора для динамической диспетчеризации. Там даже не придется передавать инстанс интерфейса при композиции, он сам подтянется через typeclass. Кроме того инстансы тайпклассов можно определять для существующих типов.
VD>Сюда же отлично подходит и МП.
Непонятно чем, покажешь?
VD>И похоже, что ты уперся в код функций и боишься или не можешь взглянуть чуть выше. Вот и начинаются разговоры о трансформации миров и т.п. А кому они нужны то на практике? Кнопка они и в Африке кнопка. В философии трансформации мира она не нуждается. Она нуждается в банальном состоянии.
А причем тут состояние и ООП? Далеко не все языки чисты, многие позволяют работать с состоянием.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Пока мы говорили, что такое ФЯ. Для большинства здесь (опять попробую угадать) — ФЯ это язык, в котором есть ФП не обязательно в ущерб другим парадигмам. Так что неудивительно, если в каких-то случаях функциональному пути может быть выбран другой путь для решения проблемы. Есть, конечно, и более радикальная точка зрения.
Разумеется! Но пойнт то не в том, что есть два удобных пути и выбирают тот, что более удобен. Пойнт в том, что ФП путь на таких языках изначально неудобен. Выбирать, собственно, не из чего.
Правда, признаю, что в таком случае не работает обоснование "в ФП стиле на таких языка не пишут". Спасибо за это замечание. Значит я могу основываться только на своём опыте работы со Scala и замечаниях типо того, что дал Klapaucius о Nemerle.
Здравствуйте, gandjustas, Вы писали:
G>В haskell подобная работа с группами функций реализуется с помощью typeclasses и и расширений компилятора для динамической диспетчеризации. Там даже не придется передавать инстанс интерфейса при композиции, он сам подтянется через typeclass. Кроме того инстансы тайпклассов можно определять для существующих типов.
Было уже. Влад говорил, что typeclasses в Haskell из мира ОО, так что ты лишь подтверждаешь его мысль
Здравствуйте, lomeo, Вы писали:
L>Разумеется! Но пойнт то не в том, что есть два удобных пути и выбирают тот, что более удобен. Пойнт в том, что ФП путь на таких языках изначально неудобен. Выбирать, собственно, не из чего.
Если судить по твоему соседнему сообщению, то складывается впечатление, что сам факт наличия *двух* удобных путей приводит к тому, что и сам код на таком языке становится как бы гибридным, а в результате, естественно, и не "тру" ФП.
(
Для сравнения — возьмем F# и Немерле. На F#, ноги к-го растут из OCaml, можно писать в императивном стиле, но это менее удобно, чем, скажем, на C#, хотя бы потому что нет конструкций для чисто императивного control flow. На Немерле императивный код писать так же удобно, как на C#. При этом формально оба языка — и Немерле, и F# — считаются гибридными.
Разумеется, несложно представить ситуацию, где важна эффективность, а императивный путь является самым эффективным. Однако на F# я, возможно, не буду, что называется, "жрать кактус" и пожертвую эффективностью. На Немерле — напишу так, как мне это удобно.
)
Иначе говоря, получается, что проблема гибридных языков не в том, что в ФП стиле на них писать неудобно, а в том, что на них удобно писать в *гибридном* стиле.
L>Правда, признаю, что в таком случае не работает обоснование "в ФП стиле на таких языка не пишут". Спасибо за это замечание. Значит я могу основываться только на своём опыте работы со Scala и замечаниях типо того, что дал Klapaucius о Nemerle.
Мне кажется его замечание не показательно в том смысле, что речь идет всего лишь о некоторых ограничения стандартного макроса для list comprehension. Нет никаких идеологических причин в том, чтобы это ограничение существовало. Просто некий добрый человек хорошо доработал *макрос* foreach (поэтому он более удобен, хотя императивен), но *макрос* list comprehension попросту "не допилен". Если его доделать, то замечание нивелируются, а язык от этого вряд ли кардинально изменится.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Иначе говоря, получается, что проблема гибридных языков не в том, что в ФП стиле на них писать неудобно, а в том, что на них удобно писать в *гибридном* стиле.
Я описал причины, почему ФП-стиль неудобен. Приходится писать в ленивом стиле и неэффективный код. Я читаю это как не "неудобнее", а как "неудобно".
ВВ>Мне кажется его замечание не показательно в том смысле, что речь идет всего лишь о некоторых ограничения стандартного макроса для list comprehension. Нет никаких идеологических причин в том, чтобы это ограничение существовало. Просто некий добрый человек хорошо доработал *макрос* foreach (поэтому он более удобен, хотя императивен), но *макрос* list comprehension попросту "не допилен". Если его доделать, то замечание нивелируются, а язык от этого вряд ли кардинально изменится.
list comprehesion вообще не при чём. Общий смысл в том, что цепочка функций порождает промежуточные результаты. Это неизлечимо в общем случае для гибридных языков. Представь, что там не IEnumerable, а некий пользовательский тип (foldable, traversable).
Здравствуйте, lomeo, Вы писали:
L>list comprehesion вообще не при чём. Общий смысл в том, что цепочка функций порождает промежуточные результаты. Это неизлечимо в общем случае для гибридных языков.
Здравствуйте, Воронков Василий, Вы писали:
L>>list comprehesion вообще не при чём. Общий смысл в том, что цепочка функций порождает промежуточные результаты. Это неизлечимо в общем случае для гибридных языков. ВВ>Для гибридных или для энергичных?
Думаю, что для чистых энергичных вполне возможны такие оптимизации. В любом случае, неважно. Мы же о гибридных? А их у нас в обсуждении пока два (Nemerle и Scala), да иногда Ocaml с F# появляются.
Здравствуйте, Silver_s, Вы писали:
S_>Здравствуйте, Воронков Василий, Вы писали:
VD>>>Дело не в линке. Дело в способе вызова функций. ВВ>>А он и так разный. Есть там каррирование, нет там каррирования.
S_>А вобще у каррирования есть полезные применения кроме перестановки аргументов местами? Просто я не в курсе патернов ФП. Вобще частичное применение может и полезно, но в карировании только по-порядку нужно частично применять.
Есть один интересный аспект, который в обсуждениях каррирования пока не упоминался. Это типы функциональных аргументов, получаемых другими функциями. Я на примере OCaml'а дальше. List.map2 — применяет заданную функцию к элементам двух списков и выдает список результатов. Допустим, каррирования нет. Какой тип у нее должен быть? Есть два варианта
('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list или
(('a, 'b) -> 'c), 'a list, 'b list) -> 'c list
Фокус здесь в том, что первый аргумент этого мапа может иметь принципиально два "разных" типа. Это либо "честная" функция от двух аргументов, либо функция, возвращающая функцию. Второй вариант вполне может возникать, если у нас есть функции, возвращающие лямбду. Никаких частичных применений при этом не нужно (лямбда все же не частичное применение), хотя и вполне возможно. При написании удобно — можно не заботится приведениями типов к "правильным" функциям. Далее парочка примеров применения List.map2
(* identity f где f функция можно применять как (identify(f))(x) *).
let identity x = x;;
(* а это просто применение apply(f,x)).
let apply f x = f x;;
(* применяем обе *)
# List.map2 identity [(+) 1; (-) 1 ] [3;4];;
- : int list = [4; -3]
# List.map2 apply [(+) 1; (-) 1 ] [3;4];;
- : int list = [4; -3]
(* более реалистичный пример, какие-нибудь обработчики и диспетчеризация. Частичных применений нет. *)
let handlers = Hashtbl.create 2;;
let add_1 x = x + 1;;
let sub_1 x = x - 1;;
Hashtbl.add handlers 1 add_1;;
Hashtbl.add handlers 2 sub_1;;
(* Формальный тип функции - int -> (int -> int) *)
let find_handler x = Hashtbl.find handlers x;;
(* Применяем соответствующие обработчики к аргументам *)
#List.map2 find_handler [1; 2; 1; 1] [6; 9; 9; 3];;
- : int list = [7; 8; 10; 4]
(* И в то же время тот же самый List.map2 с функцией типа "(int, int) -> int" *)
let sum x y = x + y;;
# List.map2 sum [1;2;3] [3;2;1];;
- : int list = [4; 4; 4]
Во втором примере еще и лямбды из функций не возвращаются. Без "каррирования" было бы не слишком удобно, пришлось бы где-то вручную преобразования писать. В целом при "осутствии" каррирования либо затруднилось бы написание функций высшего порядка (нужно долго выбирать, какой вариант получать на входе), либо нужно было бы руками много преобразований типов писать.
На всякий случай — по определению функции let f x y = ... это функция, которая возвращает функцию. Можно написать и let f (x,y) = ..., это будет фунцкия от одного аргумента — tuple. Последний вариант не принят и используется только там, где в качестве аргументов идут уже сформированные ранее туплы. Ну и с учетом простого правила "все функции — только от одного аргумента" понятия "каррирование", "декаррирование" и "частичное применение" не нужны.
P.S. На практике все эти каррирования и частичные применения все же возникают в случае наличия в функциях побобчных эффектов. Важен будет момент, когда возникает этот самый эффект, а это зависит от того, как именно описана исходная функция. Но в чистом ФП все остается просто прекрасно.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Иначе говоря, получается, что проблема гибридных языков не в том, что в ФП стиле на них писать неудобно, а в том, что на них удобно писать в *гибридном* стиле.
Вот с этим согласен, с оговоркой — это не проблема, а достоинство.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
L>Я описал причины, почему ФП-стиль неудобен. Приходится писать в ленивом стиле и неэффективный код. Я читаю это как не "неудобнее", а как "неудобно".
А ты перестань читать между строк и задай интересующие тебя вопросы автору высказываний.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, lomeo, Вы писали:
ВВ>>Именно что оптимизации. Т.е. разговор переводится уже в другую плоскость. L>Ну так мы о практике.
Мне казалось мы говорим об удобстве
ВВ>>Какие там есть чистые энергичные языки? Что-то навскидку не вспомнил L>Достаточно иметь куски, явно объявленные для компилятора как чистые.
Компиляторы сейчас умные пошли, может, им и не надо кусков явно объявленных как чистые. Сами догадаются что где устранить. Я думаю такие оптимизации и для грязных императивных языков возможны. Но опять же я не понимаю — как это влияет на удобство
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Klikujiskaaan, Вы писали:
VD>>> претензии эти в неизменном виде повторяются одним и тем же человеком с завидной периодичностью.
K>>А воз и ныне там :-D
VD>Какой воз?
Я про недовольство\шапкозакидательство со стороны nemerle-hater vs nemerle addict. Сижу не так давно на рсдне (года 2а), а споры по этому вопросу все те же =)
Здравствуйте, VladD2, Вы писали:
VD>Ага. А если еще вспомнить, что на Скалу можно довольно легко переучить любого хорошего Ява-программиста, а на Немерл любого хорошего шарписта, то вопрос и вовсе начинает выглядеть надумано.
Значит, я — плохой шарпист с 7+ летним стажем и хороший явист с нулевым стажем... Так?
Здравствуйте, Wolverrum, Вы писали:
VD>>Ага. А если еще вспомнить, что на Скалу можно довольно легко переучить любого хорошего Ява-программиста, а на Немерл любого хорошего шарписта, то вопрос и вовсе начинает выглядеть надумано.
W>Значит, я — плохой шарпист с 7+ летним стажем и хороший явист с нулевым стажем... Так?
А какие у тебя проблемы то?
Хотя тебе конечно виднее .
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Хотя тебе конечно виднее .
Вот не поверишь — даже дженерик хаскель проще пошел Хотя немерле в поле зрения дай бог памяти где-то с версии 0.8.какой-то.
Здравствуйте, Wolverrum, Вы писали:
W>Вот не поверишь — даже дженерик хаскель проще пошел Хотя немерле в поле зрения дай бог памяти где-то с версии 0.8.какой-то.
Вообще-то такой в природе не было. За 0.3.х сразу появилась 0.9.
Может потому и не пошел, что "в поле зрения" держал, а не пробовал?
Вменяемый C#-щик должен освоить его максимум за месяц.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Wolverrum, Вы писали:
W>>Вот не поверишь — даже дженерик хаскель проще пошел Хотя немерле в поле зрения дай бог памяти где-то с версии 0.8.какой-то.
VD>Вообще-то такой в природе не было. За 0.3.х сразу появилась 0.9.
Ты прав. В общем. с 2005 года — точно
VD>Может потому и не пошел, что "в поле зрения" держал, а не пробовал?
Я его честно пробовал Со своими либами, помнится, проверял работоспособность, с помощью cs2n пытался врубиться, ибо доки были слегка "того" (кстати, положительный прогресс в этом плане — респект!) Потом — баги с интеграцией, а потом забил — все это было где-то в районе 2005й студии еще. Потом — да, "а не пробовал"...
VD>Вменяемый C#-щик должен освоить его максимум за месяц.
Согласен. Хотя лично я щас точу вражескую скалу
— в основном, последняя строка, вроде как обоюдной пользой грозит
Честно говоря меня очень заинтересовали твои слова. Главным образом мне хотелось бы понять, что не понятно. Понимание этого могло бы позволить понять что же нужно менять в документации и описании языка.
Если есть время и желание предлагаю связаться со мной по Скайпу (экаунт VladD2) или Windows Live Messenger (vc@rsdn.ru) и пообщаться тет-а-тет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, nikov, Вы писали:
ВВ>>Проблема с "ненастоящими" генериками, как я понимаю, прежде всего в упаковке.
N>С версии 2.8 дженерики в Scala не требуют упаковки — компилятор создаёт специализации.
Кстати, а что при этом происходит с размерами кода? В С++, в свое врем, это было серьезной проблемой, пока компиляторы не научились объединять бинарно-совместимый код и выкидывать дубликаты. Ява же джитит все в рантайме и этим точно заниматься не будет. Не увеличивает ли это расход памяти?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
N>>С версии 2.8 дженерики в Scala не требуют упаковки — компилятор создаёт специализации.
VD>Кстати, а что при этом происходит с размерами кода? В С++, в свое врем, это было серьезной проблемой, пока компиляторы не научились объединять бинарно-совместимый код и выкидывать дубликаты. Ява же джитит все в рантайме и этим точно заниматься не будет. Не увеличивает ли это расход памяти?
Да, код раздувается. Но в JVM value-типов: раз, два — и обчёлся (свои собственные определять нельзя). Так что рост ограниченный и предсказуемый.
Здравствуйте, lomeo, Вы писали:
L>Я знаю и меня это огорчает На самом деле это поразительный факт — код с функциями и данными вперемешку понятнее кода с функциями. L>
L>saving = 0
L>for employee in staff
L> if employee.isFired
L> saving += employee.salary
L>return saving
L>
L>понятнее чем L>
L>(sum . map salary . filter isFired) staff
L>
А если развернуть, то, имхо, становится понятнее и приятнее первого варианта...