Re[14]: [Lsip & Nemerle]
От: Turtle.BAZON.Group  
Дата: 29.01.07 10:28
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Он под Виндовс есть? А то на всех вариантах Лиспа что есть у меня это дело не прошло.


Есть. Для других лиспов надо читать implementation notes для CLOS.
... << RSDN@Home 1.2.0 alpha rev. 669>>
Re[8]: [Lsip & Nemerle]
От: cl-user  
Дата: 29.01.07 10:28
Оценка:
Здравствуйте, Turtle.BAZON.Group, Вы писали:

VD>>А тебе и отвечают НЕТ ВОЗМОЖНОСТИ ПОЛУЧАТЬ И ИСПОЛЬЗОВАТЬ ИНФОРМАЦИЮ О ТИПАХ.


TBG>Это Вы откуда такое прочитали? Может, ссылку на спецификацию? Чтобы не прослыть пустозвоном?


Да ладно, не придирайся. Это надо понимать как нет возможности получить информацию о типах переменных во время компиляции макроса. Т.е. если макросу передают не значение, а имя переменной, естественно во время компиляции CL узнать тип переменной не может. Стандартный CL стандартными средствами стандартными макрами

Часть работы по типизации могут взять на себя дженерики, но они работают с классами, а не с типми — есть некоторые ограничения.
Re[13]: [Lsip & Nemerle]
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 29.01.07 13:23
Оценка: +1
VladD2,

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


VD>Вот как выглядит код макроса реализующего оператор <->:

VD>
VD>macro @<-> (e1, e2)
VD>{
VD>  def (cached1, safe1) = Operators.cache_assign_expr (e1);
VD>  def (cached2, safe2) = Operators.cache_assign_expr (e2);    
VD>  <[
VD>    $cached1;
VD>    $cached2;
VD>    def tmp = $safe1;
VD>    $safe1 = $safe2;
VD>    $safe2 = tmp;
VD>  ]>
VD>}
VD>

...
VD>Как я понимаю, cache_assign_expr и once-only решают одни и те же цели, но немного по разному.

Меня за идиота считают? Или рассчет на то, что я настолько не компетентен в Немерле, что проглачу даже это?

Взгляни на повторяющийся паттерн в макросе <->
  def (cached1, safe1) = Operators.cache_assign_expr (e1);
  def (cached2, safe2) = Operators.cache_assign_expr (e2);    

    $cached1;
    $cached2;
    // далее код с использованием $safe1 и $safe2


Код в макросе <-> — это частное решение, а макрос once-only — общее. Чтобы создать действительный эквивалент, нужно написать что-то типа:

[OnceOnly(e1, e2)]
macro @<-> (e1, e2)
{
    <[
        def tmp = $safe1;
        $safe1 = $safe2;
        $safe2 = tmp;
    ]>
}

В таком виде стало немножко геморно правда?

В качестве workaround я вижу создание функции OnceOnly(le : List[PT.PExpr], e : PT.PExpr) : PT.PExpr, и что-то типа
macro @<-> (e1, e2)
{
    def re = OnceOnly([e1, e2], 
    <[
        def tmp = $e1;
        $e1 = $e2;
        $e2 = tmp;
    ]>);
    re;
}

но это уже похоже на закат космических тел вручную — уж точно сложнее, чем в лиспе, где всё есть список. Или таки проще?
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[14]: [Lsip & Nemerle]
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.07 23:14
Оценка: -1
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Меня за идиота считают? Или рассчет на то, что я настолько не компетентен в Немерле, что проглачу даже это?


Ты некорректно цитируешь мои слова. Ключевую фразу ты выбросил:

Кстати, похожая вещь исползуется в Немерлевом макросе <->


Я не утверждаю, что это полный аналог.

LCR>Код в макросе <-> — это частное решение, а макрос once-only — общее.


Бесспорно. Видимо общее решение просто не понадобилось.

Кстати, интересно... Сработает ли этот макрос в случае с массивами? Бдует ли возможно обменять значения ячеек массива если индекс задн randim-ом?

LCR>Чтобы создать действительный эквивалент, нужно написать что-то типа:


LCR>
LCR>[OnceOnly(e1, e2)]
LCR>macro @<-> (e1, e2)
LCR>{
LCR>    <[
LCR>        def tmp = $safe1;
LCR>        $safe1 = $safe2;
LCR>        $safe2 = tmp;
LCR>    ]>
LCR>}
LCR>

LCR>В таком виде стало немножко геморно правда?

Хрен его знает. Если не учитывать случай массива, то присвоения переменной вполне достаточно чтобы выражение исполнялось один раз. Так что и смысла в OnceOnly не много. В прочем сделать макрос как это хочешь ты тоже можно. Он будет тупо вызывать показанную выше фукнцию и присваивать результат переменной. Вопрос только в том зачем это делать. Ведь это совершенно не нужно.


LCR>В качестве workaround я вижу создание функции OnceOnly(le : List[PT.PExpr], e : PT.PExpr) : PT.PExpr, и что-то типа

LCR>
LCR>macro @<-> (e1, e2)
LCR>{
LCR>    def re = OnceOnly([e1, e2], 
LCR>    <[
LCR>        def tmp = $e1;
LCR>        $e1 = $e2;
LCR>        $e2 = tmp;
LCR>    ]>);
LCR>    re;
LCR>}
LCR>

LCR>но это уже похоже на закат космических тел вручную — уж точно сложнее, чем в лиспе, где всё есть список. Или таки проще?

Я не вижу причины почему нельзя было бы оформить это дело в виде макро-атрибута. И не вижу чем в Лиспе применение макроса было бы проще (атрибутов ведь в нем точно нет). Поясни, плиз.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: [Lsip & Nemerle]
От: Turtle.BAZON.Group  
Дата: 30.01.07 05:32
Оценка:
Здравствуйте, cl-user, Вы писали:

CU>Часть работы по типизации могут взять на себя дженерики, но они работают с классами, а не с типми — есть некоторые ограничения.


Классы есть типы. Если принять это ограничение, то очень даже может.
... << RSDN@Home 1.2.0 alpha rev. 669>>
Re[10]: [Lsip & Nemerle]
От: cl-user  
Дата: 30.01.07 07:57
Оценка: +1
Здравствуйте, Turtle.BAZON.Group, Вы писали:

CU>>Часть работы по типизации могут взять на себя дженерики, но они работают с классами, а не с типми — есть некоторые ограничения.


TBG>Классы есть типы. Если принять это ограничение, то очень даже может.


Принять его легко. А вот не забывать о нём — трудно
Сам пару раз наступал на эти грабли. Ведь типы в CL (определение типов для параметров/переменных) очень "пластичные". А классы — тут не особо навыёжываешся...
Re[15]: [Lsip & Nemerle]
От: Last Cjow Rhrr Россия lj://_lcr_
Дата: 03.02.07 10:16
Оценка:
VladD2,

LCR>>В качестве workaround я вижу создание функции OnceOnly(le : List[PT.PExpr], e : PT.PExpr) : PT.PExpr, и что-то типа

LCR>>macro @<-> (e1, e2)
LCR>>{
LCR>>    def re = OnceOnly([e1, e2], 
LCR>>    <[
LCR>>        def tmp = $e1;
LCR>>        $e1 = $e2;
LCR>>        $e2 = tmp;
LCR>>    ]>);
LCR>>    re;
LCR>>}

LCR>>но это уже похоже на закат космических тел вручную — уж точно сложнее, чем в лиспе, где всё есть список. Или таки проще?

VD>Я не вижу причины почему нельзя было бы оформить это дело в виде макро-атрибута. И не вижу чем в Лиспе применение макроса было бы проще (атрибутов ведь в нем точно нет). Поясни, плиз.


В общем, поковырялся я немного, и нашёл только так:
[Nemerle.MacroUsage (Nemerle.MacroPhase.BeforeInheritance,
    Nemerle.MacroTargets.Method)]
    macro OnceOnly (_ : TypeBuilder, m : ParsedMethod) {...}

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

В Лиспе/Схеме это проще, можно даже вытворять такие фокусы:
(defmacro tail (lst)
  (cdr (macroexpand lst)))

(defmacro add (a b)
  (+ (macroexpand a) (macroexpand b)))

(defmacro zipWith (op lst1 lst2)
  (let ((lst1 (macroexpand lst1))
    (lst2 (macroexpand lst2)))
    (cond
     ((null? lst1) '())
     ((null? lst2) '())
     (else
      (cons (macroexpand `(,op ,(car lst1) ,(car lst2)))
        `(zipWith ,op ,(cdr lst1) ,(cdr lst2)))))))

(defmacro fibs () '(1 1 . (zipWith add (fibs) (tail (fibs)))))

http://okmij.org/ftp/Scheme/lazy-macro-computation.txt
( Зто ненавистная тобой функция Фиббоначи но выполняемая на макроуровне. zipWith — это функция высшего порядка (на макроуровне).)

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

Короче, предлагаю мир.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[16]: [Lsip & Nemerle]
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.02.07 15:58
Оценка:
Здравствуйте, Last Cjow Rhrr, Вы писали:

LCR>В общем, поковырялся я немного, и нашёл только так:

LCR>
LCR>[Nemerle.MacroUsage (Nemerle.MacroPhase.BeforeInheritance,
LCR>    Nemerle.MacroTargets.Method)]
LCR>    macro OnceOnly (_ : TypeBuilder, m : ParsedMethod) {...}
LCR>

LCR>(то есть сделать его макросом второго уровня). А последнее уже неудобно: собираем макрос второго уровня, потом первого, и наконец собственно сборку. Поэтому мне и захотелось понизить уровень косвенности, заменив OnceOnly просто функцией. Но в обоих случаях сделать OnceOnly универсальной будет нелегко как мне кажется — ведь она должна уметь продираться через любые определения макросов — а в Немерле выражения могут быть очень разношёрстные, это не просто список на входе — список на выходе.

Была бы задача, решить можно. Выражения конечно — это просто списки на входе, и списки на выходе. Не придумывай. Вопрос только в семантике.
Ну, а не делатся это универсально толко по одной причине — на фиг не уперлось. Это только на РСДН ради пенисометрии народ может зафигачивать горы не нужного кода. Компиляторщиком, да и мене, есть над чем работать. Есть много сложных не решенных задач.

LCR>[/lisp]

LCR>http://okmij.org/ftp/Scheme/lazy-macro-computation.txt
LCR>( Зто ненавистная тобой функция Фиббоначи но выполняемая на макроуровне. zipWith — это функция высшего порядка (на макроуровне).)

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

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

Что касается частичного вычисления, то почитай вот это:
http://nemerle.org/Partial_evaluation

LCR>Разумеется, нужно постараться, чтобы заюзать такие возможности на практике, но сама принципиальная возможность говорит о возможностях (каламбурчик).


На самом деле данный вопрос не является вопросом мощньости макросов. Это опять статика vs. динамика. Немерле статически типизированный компилируемый язык. И макросы у него точно такие же. Что совершенно логично. Причем как показала практика задачи которе действительно невозможно решить без рантайма встречаются крайне редка, да и они решаются путем динамической компиляции. Все пробелмы возникают у ледей обычно из-за неумения переключить мышление в плоскость мышления статикии.

LCR>С другой стороны, типы — это хорошо, здесь плюс Немерле.


Не могу не согласиться.

LCR>Короче, предлагаю мир.


Ды мы вроде морды то и не бьем.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.