Re[3]: Ликбез по ComputationExpressions
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.04.10 14:49
Оценка:
Здравствуйте, WolfHound, Вы писали:

Согласен со всеми замечаниями кроме этого:

WH>

  • WH>Можно писать так:
    WH>
    WH>_testDo(10).Iter(WriteLine);
    WH>

    WH>местный вывод типов может даже в таких ситуациях разбираться...

    лучше пользоваться foreach-ем. Это делает код понятнее и лучше выглядит в отладчике (так как нет лишнего замыкания).
  • Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[5]: Ликбез по ComputationExpressions
    От: dsorokin Россия  
    Дата: 23.04.10 15:05
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>Нет не является. Продолжения вещь несомненно более мощьная. Их состояние можено сериализовать или клонировать.


    Вот, определение такой монады (пишу по памяти):

    type Cont a = (a -> Result) -> Result
    
    return a = \c -> c a
    
    bind m k = \c -> m (\a -> k a c)


    Более того, любую монаду можно свести к продолжению.

    VD>Представь себе, что некий ворфлоу заморозили в некоторой точке и это замороженное состояние превратили в поток байтов и записали в файл или поместили в поле БД.


    VD>Далее, через несколько дней, достали от туда, восстановили состояние в другой экземпляр и запустили с той же точки.


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

    А так можно дополнить монаду Cont функцией Save, которая будет принимать продолжение, сохранять его где-нибудь и затем завершать сеанс. Потом отдельно можно будет загрузить это продолжение и .. продолжить его выполнение. Computation expressions будут являться удобным eDSL для написания кода. Только я боюсь, что сериализовывать придется слишком много байт. Неэффективно будет.

    VD>Как я понимаю там есть только CSP который, лично я, не понимаю как можно сериализовать или клонировать.


    Не совсем понимаю.
    Re[3]: Ликбез по ComputationExpressions
    От: dsorokin Россия  
    Дата: 23.04.10 15:11
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>Нельзя ли реализовать что-то вроде такого варианта:

    VD>
    VD>    compdef filesUnderFolder (rootFolder : string) : IEnumerable [string]
    VD>    {
    VD>      foreach (file in System.IO.Directory.GetFiles (rootFolder))
    VD>        yield file;
    
    VD>      foreach (dir in System.IO.Directory.GetDirectories (rootFolder))
    VD>        yieldcomp (filesUnderFolder (dir))
    VD>    }
    VD>

    VD>?

    VD>Вот это было бы просто супер удобно.


    Я за такое не возьмусь. Это можно сделать параллельно. Мне кажется, что это не относится напрямую к самим computation expressions. Да и почему бы не написать лишнюю конструкцию comp enumerable {..}?

    Кстати, обновил svn. Enumerable comprehension стал на порядок эффективнее. Отдельное спасибо WolfHound за помощь в написание оптимизатора!
    Re[3]: Ликбез по ComputationExpressions
    От: WolfHound  
    Дата: 23.04.10 15:22
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>Нельзя ли реализовать что-то вроде такого варианта:

    хъ
    VD>Вот это было бы просто супер удобно.
    Вот так вот оно работает:
      public macro DefCompEnum (name, args, expr)
      {
        def args = (args :> PExpr.Tuple).args.Map(PParameter);
        def name = (name :> PExpr.Ref).name;
        def res = ComputationExpander.Expand (EnumerableBuilder.Instance, expr);
        <[
          def $(name : name)(..$args)
          {
            $res;
          }
        ]>
      }
    
        DefCompEnum(filesUnderFolder, (rootFolder : string, pattern),
        {
          foreach (file in Directory.GetFiles(rootFolder, pattern))
            yield file;
          foreach (dir in Directory.GetDirectories(rootFolder))
            yieldcomp filesUnderFolder(dir, pattern);
        });
        filesUnderFolder("H:\\Video", "*").Iter(WriteLine);

    Но как его облачить в красивый синтаксис я пока не понял.
    ... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
    Пусть это будет просто:
    просто, как только можно,
    но не проще.
    (C) А. Эйнштейн
    Re[6]: Ликбез по ComputationExpressions
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 23.04.10 15:42
    Оценка:
    Здравствуйте, dsorokin, Вы писали:

    D>Пожалуй, SharpDevelop стоит снова мне поглядеть. Давно его не видел.


    Погляди конечно, но пока что студия — это более надежный вариант.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[6]: Ликбез по ComputationExpressions
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 23.04.10 15:59
    Оценка:
    Здравствуйте, dsorokin, Вы писали:

    D>Вот, определение такой монады (пишу по памяти):


    D>
    D>type Cont a = (a -> Result) -> Result
    
    D>return a = \c -> c a
    
    D>bind m k = \c -> m (\a -> k a c)
    D>


    D>Более того, любую монаду можно свести к продолжению.


    Только к частному случаю.

    VD>>Представь себе, что некий ворфлоу заморозили в некоторой точке и это замороженное состояние превратили в поток байтов и записали в файл или поместили в поле БД.


    VD>>Далее, через несколько дней, достали от туда, восстановили состояние в другой экземпляр и запустили с той же точки.


    D>Наверное, можно что-то сделать


    Как? Добраться до состояния здесь практически не реально. А еще есть состояние окружающих объектов, которые получаются полностью изолированы.

    В общем, я не вижу как это сделать.

    D>, хотя все равно большого смысла пока не вижу.


    Это другой вопрос. К примеру, многие не видят смысла в монадах.
    Лично я смысл вижу. Сериализуемые континюэшоны — это натуральная бомба! С их помощью некоторые виды задач превращаются в элементарные, когда как без них решения получаются очень кривыми. Например, хранение сессии пользователя на сайте обеспечивающем сложную навигацию. Далее распараллеливание вычислений на разных машинах. Представь себя, просто сериализовал задачу и передал ее на другую машину. Там запустил и вычислил. Потом снова сериализовал и послал обратно. На этом деле даже STM реализуется в пол пинка.

    D> Но если делать через монаду продолжения (Cont), то сериализовать поток управления, думаю, можно.


    Ну, не знаю. Возможно я просто недооцениваю этот подход.
    А при этом мы сможем получить доступ к объектам обрабатываемым внутри этой монады? Ведь сериализовать нужно не только саму монаду, но и обрабатываемые в ней объекты.

    Вообще, если это реализовать — это было бы мега круто!

    D>Там исполнимый код как раз превращается в объекты памяти, которые уже поддаются сериализации средствами .NET (если функции сериализуются). Только какой ценой?


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

    D>А так можно дополнить монаду Cont функцией Save, которая будет принимать продолжение, сохранять его где-нибудь и затем завершать сеанс. Потом отдельно можно будет загрузить это продолжение и .. продолжить его выполнение. Computation expressions будут являться удобным eDSL для написания кода. Только я боюсь, что сериализовывать придется слишком много байт. Неэффективно будет.


    Почему много? По идее это должно быть аналогично слепку стека на момент сериализации, плсю все объекты достижимые из него.

    Учитывая те возможности которые открываются при наличии такого решения я бы заплатил бы даже пятикратным оверхэдом!

    VD>>Как я понимаю там есть только CSP который, лично я, не понимаю как можно сериализовать или клонировать.


    D>Не совсем понимаю.


    Сори — CPS.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[4]: Ликбез по ComputationExpressions
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 23.04.10 16:06
    Оценка:
    Здравствуйте, WolfHound, Вы писали:

    WH>Вот так вот оно работает:...

    WH>Но как его облачить в красивый синтаксис я пока не понял.

    Наверно как-то так:

      public macro DefCompEnum (name, args, expr)
      syntax ("compdef", fancName, args, expr)
      {
        def args = (args :> PExpr.Tuple).args.Map(PParameter);
        def name = (name :> PExpr.Ref).name;
        def res = ComputationExpander.Expand (EnumerableBuilder.Instance, expr);
        <[
          def $(name : name)(..$args)
          {
            $res;
          }
        ]>
      }

    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[5]: Ликбез по ComputationExpressions
    От: WolfHound  
    Дата: 23.04.10 16:14
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>Наверно как-то так:

    хъ
    VD>
    А ты попробуй
    ... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
    Пусть это будет просто:
    просто, как только можно,
    но не проще.
    (C) А. Эйнштейн
    Re[7]: Ликбез по ComputationExpressions
    От: dsorokin Россия  
    Дата: 23.04.10 16:35
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>Как? Добраться до состояния здесь практически не реально. А еще есть состояние окружающих объектов, которые получаются полностью изолированы.


    VD>В общем, я не вижу как это сделать.


    Там и код придется сериализовывать. Только он будет представлен в виде вычислений в монаде Cont. Фактически сначала по вычислительному выражению будет создано вычисление (некий объект), в котором будет закодирован весь процесс обработки. Затем это вычисление запускается и раскручивается. В любой момент можно прервать. Фактически нужно сериализовать функцию типа T -> void. Можно ограничится функцией FakeVoid -> void. Кстати, вот где нужна параметризация шаблона по void!

    VD>Это другой вопрос. К примеру, многие не видят смысла в монадах.

    VD>Лично я смысл вижу. Сериализуемые континюэшоны — это натуральная бомба! С их помощью некоторые виды задач превращаются в элементарные, когда как без них решения получаются очень кривыми. Например, хранение сессии пользователя на сайте обеспечивающем сложную навигацию. Далее распараллеливание вычислений на разных машинах. Представь себя, просто сериализовал задачу и передал ее на другую машину. Там запустил и вычислил. Потом снова сериализовал и послал обратно. На этом деле даже STM реализуется в пол пинка.

    Надо поразмыслить. Только повторюсь, медленно будет. И почему еще не сделали для F#?

    VD>Ну, не знаю. Возможно я просто недооцениваю этот подход.

    VD>А при этом мы сможем получить доступ к объектам обрабатываемым внутри этой монады? Ведь сериализовать нужно не только саму монаду, но и обрабатываемые в ней объекты.

    VD>Вообще, если это реализовать — это было бы мега круто!


    В своей библиотеке моделирования Aivika на F# я создал две монады Dynamics<'a> и DynamicsCont<'a>. Вторая есть частный случай монадного трансформера на базе Cont, параметризованного монадой Dynamics. В общем, монада Cont.

    Так вот, у меня там есть такие вещи как усыпление потока управления, блокировка в ожидании освобождения ресурса, возобновление через такой то промежуток времени и т.д. Сам код пишется как вычислительное выражение в монаде DynamicsCont<'a>. Выглядит как обычный код на F#. Только усыпление потока исполнения происходит в памяти. Сериализации нет. Но это все позволяет легко реализовать process-driven discrete event simulation (DES). Собственно, я пишу софт для моделирования, а эта библиотека — хобби.

    VD>Автоматическая сериализация в дотнете очень тормозная. Но ведь можно сделать и самопальную. Внутренние структуры ведь нам будут доступны?


    Будет функция типа FakeVoid -> void. Если сделаете параметризацию шаблона по void, то функция будет иметь тип void -> void. Вот, ее и надо сериализовать. А за этой простотой может скрываться очень много объектов!

    VD>Почему много? По идее это должно быть аналогично слепку стека на момент сериализации, плсю все объекты достижимые из него.


    VD>Учитывая те возможности которые открываются при наличии такого решения я бы заплатил бы даже пятикратным оверхэдом!


    Медленной будет не только сериализация, но и сам процесс исполнения кода. Фактически кода не будет. Будет запуск вычисления в монаде Cont. На самом деле, продолжения должны были бы поддерживаться на уровне CLR для эффективности. А так получится тормоз. Хотя в F# на это закрыли глаза и широко используют async.
    Re[2]: Ликбез по ComputationExpressions
    От: WolfHound  
    Дата: 23.04.10 16:51
    Оценка:
    Здравствуйте, dsorokin, Вы писали:

      public macro @compList (expr)
      syntax ("comp", "list", expr)
      {
        ComputationExpander.Expand (ListBuilder (), expr)
      }
      
      public macro @compArray (expr)
      syntax ("comp", "array", expr)
      {
        ComputationExpander.Expand (ArrayBuilder (), expr)
      }
      
      public macro @compEnumerable (expr)
      syntax ("comp", "enumerable", expr)
      {
        ComputationExpander.Expand (EnumerableBuilder.Instance, expr)
      }

    Нашол серьезную проблему с данным синтаксисом.
    Ключевые слова list и array из первых двух макросов конфликтуют со стандартными ключивыми словами list и array.

    Пофиксил вот так:
      public macro @comp (builder, expr)
      syntax ("comp", builder, expr)
      {
        def builder = match (builder)
        {
          | PExpr.Ref(name) when name.Id == "list"       => Extensions.ListBuilder()
          | PExpr.Ref(name) when name.Id == "array"      => Extensions.ArrayBuilder()
          | PExpr.Ref(name) when name.Id == "enumerable" => Extensions.EnumerableBuilder.Instance
          | _                                            => DefaultBuilder(builder)
        }
        ComputationExpander.Expand (builder, expr)
      }

    В svn залил.
    ... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
    Пусть это будет просто:
    просто, как только можно,
    но не проще.
    (C) А. Эйнштейн
    Re[6]: Ликбез по ComputationExpressions
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 23.04.10 17:09
    Оценка:
    Здравствуйте, WolfHound, Вы писали:

    VD>>Наверно как-то так:

    WH>хъ
    VD>>
    WH>А ты попробуй

    Я думал, что с мелочевкой ты справится. Вот рабочий вариант синтаксиса (начинку сам подставь):
      public macro DefCompEnum (prefix, body)
      syntax ("compdef", prefix, body)
      {
        match (prefix)
        {
          | <[ $name(..$args) ]> => <[ def $name = (..$args) => $body  ]>
          | _ => Message.FatalError(prefix.Location, "Expected fanc def: func_name(optional_parameters)")
        }
      }

    пример использования:
    compdef test(a, b)
    {
      a + b
    }
        
    WriteLine(test(2, 3));
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[8]: Ликбез по ComputationExpressions
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 23.04.10 17:24
    Оценка:
    Здравствуйте, dsorokin, Вы писали:

    D>Там и код придется сериализовывать. Только он будет представлен в виде вычислений в монаде Cont. Фактически сначала по вычислительному выражению будет создано вычисление (некий объект), в котором будет закодирован весь процесс обработки. Затем это вычисление запускается и раскручивается.


    А что будет с рекурсивными вызовами? Без рекурсии это будет ни чем не лучше итераторов (yield-методов).

    D>В любой момент можно прервать. Фактически нужно сериализовать функцию типа T -> void. Можно ограничится функцией FakeVoid -> void. Кстати, вот где нужна параметризация шаблона по void!


    Это не шаблоны — это типы (параметризованные типы или дженерики).

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

    D>Надо поразмыслить.


    +1

    D>Только повторюсь, медленно будет.


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

    D>И почему еще не сделали для F#?


    Хз. Возможно потому, что руки не дошли. Возможно просто в голову не пришло. А возможно есть какие-то сложности в реализации.

    Сам понимашь у них не так много народу который может это дело релизовать. Это ведь правка компилятора.

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

    D>Так вот, у меня там есть такие вещи как усыпление потока управления, блокировка в ожидании освобождения ресурса, возобновление через такой то промежуток времени и т.д. Сам код пишется как вычислительное выражение в монаде DynamicsCont<'a>. Выглядит как обычный код на F#. Только усыпление потока исполнения происходит в памяти. Сериализации нет. Но это все позволяет легко реализовать process-driven discrete event simulation (DES). Собственно, я пишу софт для моделирования, а эта библиотека — хобби.


    Понятно, профессор. Но все же... Взлетит?

    D>Будет функция типа FakeVoid -> void. Если сделаете параметризацию шаблона по void, то функция будет иметь тип void -> void. Вот, ее и надо сериализовать. А за этой простотой может скрываться очень много объектов!


    Я решительно не понимаю как можно сериализовать ссылку на функцию.

    D>Медленной будет не только сериализация, но и сам процесс исполнения кода. Фактически кода не будет. Будет запуск вычисления в монаде Cont. На самом деле, продолжения должны были бы поддерживаться на уровне CLR для эффективности. А так получится тормоз. Хотя в F# на это закрыли глаза и широко используют async.


    Да. Наверно ты прав. Так что остается только попытаться создать ограниченные продолжения на базе переписывания кода класса (как я задумывал). Там оверхэд будет только при вызове методов (их параметры придется вместо стека располагать в динамических массивах). При этом сериализация превращается в линейный и прозрачный процесс.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[3]: Ликбез по ComputationExpressions
    От: dsorokin Россия  
    Дата: 24.04.10 05:07
    Оценка:
    Здравствуйте, WolfHound, Вы писали:

    WH>Пофиксил вот так:

    WH>
    WH>  public macro @comp (builder, expr)
    WH>  syntax ("comp", builder, expr)
    WH>  {
    WH>    def builder = match (builder)
    WH>    {
    WH>      | PExpr.Ref(name) when name.Id == "list"       => Extensions.ListBuilder()
    WH>      | PExpr.Ref(name) when name.Id == "array"      => Extensions.ArrayBuilder()
    WH>      | PExpr.Ref(name) when name.Id == "enumerable" => Extensions.EnumerableBuilder.Instance
    WH>      | _                                            => DefaultBuilder(builder)
    WH>    }
    WH>    ComputationExpander.Expand (builder, expr)
    WH>  }
    WH>

    WH>В svn залил.

    Здорово! Это как раз было слабым местом. Так можно добавлять разные нестандартные или конфликтующие с чем-то другим воркфлоу. Например, comp async {..} или comp option {..}.

    Среди важных задач остаются такие:

    1. Довершить foreach. Хитрый случай, когда тело foreach представляет из себя варианты паттерн-матчинга. Код локализован методом ComputationBuilder.ForEach.

    2. Приручить try-finally и try-catch. Думаю, будет несложно.

    3. Добавить using/usingcomp. Предвижу некоторую копипасту со стандартных макросов using из core.n
    Re[9]: Ликбез по ComputationExpressions
    От: dsorokin Россия  
    Дата: 24.04.10 05:38
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>А что будет с рекурсивными вызовами? Без рекурсии это будет ни чем не лучше итераторов (yield-методов).


    В монаде Cont рекурсия часто используется. Например, монадический while определяется совершенно рекурсивно. Но там все дело в функциях. Рекурсия прячется в них и уже раскрывается во время их выполнения. Поэтому все нормально. Плюс работает оптимизация хвостовых вызовов.

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


    И здесь могут быть интересны вычислительные выражения (воркфлоу). Они выглядят как обычный на Немерле код, который мы можем интерпретировать как угодно. Плюс работает проверка типов. Еще единообразие кода — низкая кривая обучения. В принципе можно тоже перегонять в скрипт, если написать свой ComputationBuilder. Затем исполнять этот скрипт внешне. Причем четко разделяется код на дополнительный и монадический.

    VD>Кстати, как тебе макросы? Теперь ты о них уже можешь кое-что сказать?

    VD>Предрассудки по их поводу отпали?

    Сложные чувства. С одной стороны расширяемый язык. С другой стороны сложнее создавать макросы, потому что эти макросы должны учитывать другие макросы...

    Что касается вычислительных выражений, то там все получается красиво и очень просто, но этому способствует гениальная задумка создателей самой идеи. Мы лишь адаптируем.

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


    Может быть, вычислительные выражения и пригодятся.
    Re[4]: Ликбез по ComputationExpressions
    От: WolfHound  
    Дата: 24.04.10 11:09
    Оценка:
    Здравствуйте, dsorokin, Вы писали:

    У меня тут крутится одна мысль:
    А что если разделить разбор выражений и собственно генерацию кода.
    Те мы сначала запихиваем все в вариант типа:
    variant CompExpr
    {
        | Sequence { seq : list[CompExpr] }
        | Return { expr : PExpr }
        | ReturnComp { expr : CompExpr }
    ...
    }


    Потом по этой структуре уже генерируем код.

    Это позволит:
    1)Упростить логику.
    2)Даст возможность более гибко генерировать код.
    3)Даст возможность оптимизировать выражения.
    ... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
    Пусть это будет просто:
    просто, как только можно,
    но не проще.
    (C) А. Эйнштейн
    Re[6]: Ликбез по ComputationExpressions
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 24.04.10 11:12
    Оценка:
    Здравствуйте, dsorokin, Вы писали:

    D>Более того, любую монаду можно свести к продолжению.


    Вот именно, но не наоборот.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[10]: Ликбез по ComputationExpressions
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 24.04.10 11:47
    Оценка:
    Здравствуйте, dsorokin, Вы писали:

    VD>>А что будет с рекурсивными вызовами? Без рекурсии это будет ни чем не лучше итераторов (yield-методов).


    D>В монаде Cont рекурсия часто используется. Например, монадический while определяется совершенно рекурсивно. Но там все дело в функциях. Рекурсия прячется в них и уже раскрывается во время их выполнения. Поэтому все нормально. Плюс работает оптимизация хвостовых вызовов.


    Я говорю о том как будет сериализоваться информация о глубине рекурсии и значених параметров?

    D>И здесь могут быть интересны вычислительные выражения (воркфлоу). Они выглядят как обычный на Немерле код, который мы можем интерпретировать как угодно. Плюс работает проверка типов. Еще единообразие кода — низкая кривая обучения. В принципе можно тоже перегонять в скрипт, если написать свой ComputationBuilder. Затем исполнять этот скрипт внешне. Причем четко разделяется код на дополнительный и монадический.


    Скрипт то как раз не нужен. Нужны именно продолжения. Возможно ограниченные (например, ОО-классом), но с поддержкой рекурсии и вызовов функций.

    Пока что я что-то сомневаюсь, что на монадах может получиться что-то стоящее.

    D>Сложные чувства. С одной стороны расширяемый язык. С другой стороны сложнее создавать макросы, потому что эти макросы должны учитывать другие макросы...


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

    D>Что касается вычислительных выражений, то там все получается красиво и очень просто, но этому способствует гениальная задумка создателей самой идеи. Мы лишь адаптируем.


    Ну, так уж и гениальная . Просто хорошо продуманное решение. Я бы сказал — нормальная инженерная работа. К тому же база была хорошо проработана в хаскеле. Да что уж там? Можно даже сказать в теории категорий (если не ошибаюсь).

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


    D>Может быть, вычислительные выражения и пригодятся.


    В принципе можно даже попытаться сделать несколько реализаций. Где только на это взять времени и сил. Хотя это точно будет киллер-фичей... только как всегда для узкого круга посвященных .
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[5]: Ликбез по ComputationExpressions
    От: dsorokin Россия  
    Дата: 24.04.10 12:57
    Оценка:
    Здравствуйте, WolfHound, Вы писали:

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


    WH>У меня тут крутится одна мысль:

    WH>А что если разделить разбор выражений и собственно генерацию кода.
    WH>Те мы сначала запихиваем все в вариант типа:
    WH>
    WH>variant CompExpr
    WH>{
    WH>    | Sequence { seq : list[CompExpr] }
    WH>    | Return { expr : PExpr }
    WH>    | ReturnComp { expr : CompExpr }
    WH>...
    WH>}
    WH>


    WH>Потом по этой структуре уже генерируем код.


    WH>Это позволит:

    WH>1)Упростить логику.
    WH>2)Даст возможность более гибко генерировать код.
    WH>3)Даст возможность оптимизировать выражения.

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

    Сейчас предлагаю завершить текущую схему. Я добавил более полную реализацию foreach (с матчингом и приведением :>) и блок try-finally. Из основных остались try-catch и using/usingcomp.
    Re[7]: Ликбез по ComputationExpressions
    От: dsorokin Россия  
    Дата: 24.04.10 13:06
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    D>>Более того, любую монаду можно свести к продолжению.


    VD>Вот именно, но не наоборот.


    Зато можно построить монаду Cont. Этого достаточно для многих практических задач. Тогда с помощью вычислительных выражений становится очень легко и просто создавать эти самые продолжения. Async из F# в своей основе есть продолжение, но которое еще умеет распространять исключения между потоками исполнения.
    Re[11]: Ликбез по ComputationExpressions
    От: dsorokin Россия  
    Дата: 24.04.10 13:18
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>Я говорю о том как будет сериализоваться информация о глубине рекурсии и значених параметров?


    Наверное как граф объектов. Но для этого надо уметь сериализовывать функции и замыкания.

    VD>Ну, дык метапрограммировние по любому сложнее просто программирования.

    VD>Что касается учета других макросов, то это как раз требуется довольно редко. Обычно они получаются довольно назависимыми.
    VD>А вообще, просто нужен опыт. Ты ведь с ними возишся около недели. Правильно?

    Меньше Но время от времени еще увлекаюсь Common Lisp. Так что, к макросам привыкший.

    D>>Что касается вычислительных выражений, то там все получается красиво и очень просто, но этому способствует гениальная задумка создателей самой идеи. Мы лишь адаптируем.


    VD>Ну, так уж и гениальная . Просто хорошо продуманное решение. Я бы сказал — нормальная инженерная работа. К тому же база была хорошо проработана в хаскеле. Да что уж там? Можно даже сказать в теории категорий (если не ошибаюсь).


    Нет, здесь свое. На мой взгляд основная фишка в том, что код, написанный в вычислительных выражениях, почти ничем не отличается от обычного кода на F# или Немерле. Это просто гениальная вещь! В одном ряду с linq, где по забавному совпадению тоже монады
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.