Amplifying C
От: yumi  
Дата: 25.01.10 11:51
Оценка: 29 (5) -1 :)
Здесь.
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org
Re: Amplifying C
От: Mr.Cat  
Дата: 25.01.10 12:12
Оценка:
Здравствуйте, yumi, Вы писали:
Y>Здесь.
Кстати, а нужен ли в итоге лиспосинтаксис? Я вот не очень знаком с nemerle и boo, но там есть макросы и без него.
Re[2]: Amplifying C
От: A13x США  
Дата: 25.01.10 13:10
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

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

Y>>Здесь.
MC>Кстати, а нужен ли в итоге лиспосинтаксис? Я вот не очень знаком с nemerle и boo, но там есть макросы и без него.

Безусловно.
Чтобы иметь удобную возможность оперировать с кодом из lisp, опять же lisp-синтаксис (лично мне) кажется очень стройным и логичным.
S-выражения достаточны для описанной задачи, а так же универсальны и однотипны.

+ Очень легка реализация такого вот DSL на generic-ах + destructuring-bind, типа такой:

;; описываем как парсить объявления типов
(defgeneric parse-type-decl (context type-id args))

;; объявления структур
(defmethod parse-type-decl (context (type-id (eql :struct)) args)
 (destructuring-bind (name members) args
   ;; further impl...
   ))

;; typedef объявления
(defmethod parse-type-decl (context (type-id (eql :typedef)) args)
 (destructuring-bind (source-name aliased-name) args
   ;; further impl...
   ))

;; и т.д.


в точке разбора выражений типа вызываем parse-type-decl "и имеем уважение"(с)
Re: Amplifying C
От: A13x США  
Дата: 25.01.10 13:15
Оценка: 8 (1)
Здравствуйте, yumi, Вы писали:

Y>Здесь.




еще ссылка по теме для интересующихся: Google DSL
не совсем "amplifying C", но решает сходные задачи кодогенерации.
Re[2]: Amplifying C
От: yumi  
Дата: 25.01.10 13:22
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>Кстати, а нужен ли в итоге лиспосинтаксис? Я вот не очень знаком с nemerle и boo, но там есть макросы и без него.


Нужен или нет, каждый сам для себя решает
Лиспосинтаксис aka s-expressions проще, в том смысле, что ими проще манипулировать, трансформировать, ведь это и есть по сути AST. В немерле уже сложнее, в основном видимо из-за наличия синтаксиса, многостадийности компиляции и нескольких AST на разных стадиях компиляции. Например, точно не помню, очень примерно, на этапе лексического анализа используется PreParse tree, далее, ParseTree, потом TypedTree, как-то так. Т.е. внутри макроса, мы должны знать, на каком этапе мы и какое дерево нам доступно.

Можно сравнить на простых примерах.

Макрос when на Nemerle:
  macro whenmacro (cond, body)
  syntax ("when", "(", cond, ")", body) 
  {
    def res1 = match (cond)
    {
      | <[ $subCond is $pattren ]> with guard = null
      | <[ $subCond is $pattren when $guard ]> =>
        def res2 = match (pattren)
        {
          | PT.PExpr.Call when guard != null => 
            <[ match ($subCond) { | $pattren when $guard => $body : void | _ => () } ]>
          | PT.PExpr.Call => 
            <[ match ($subCond) { | $pattren => $body : void | _ => () } ]>
          | _ => <[ match ($cond) { | true => $body : void | _ => () } ]>
        }
        res2
      | _ => <[ match ($cond) { | true => $body : void | _ => () } ]>
    }
    res1
  }

(c) nemerle\macros\core.n

Макрос when на Lisp'e:
(defmacro when (condition &rest body)
  `(if ,condition (progn ,@body)))

(c) Practical Common Lisp by Peter Seibel

Макрос while на Nemerle:
  macro @while (cond, body)
  syntax ("while", "(", cond, ")", body) 
  {
    def loop = Nemerle.Macros.Symbol (Util.tmpname ("while_"));

    <[ 
      $("_N_break" : global) : {
        def $(loop : name) () : void {
          when ($cond) {
            $("_N_continue" : global) : {
              $body 
            } 
            $(loop : name) ()
          }
        } 
        $(loop : name) (); 
      }
    ]>
  }

(c) nemerle\macros\core.n

Макрос while на Lisp'e:
(defun while-function (predicate block)
  (if (not (funcall predicate)) (return))
  (funcall block)
  (while-function predicate block))  

(defmacro while (expression &body body)
  `(while-function (lambda () ,expression)
     (lambda () ,@body)))

(c) Pascal Constanza

или

более простой макрос, но более эффективный while на Lisp'e:
(defmacro while (expression &body body)
  `(tagbody
     start (if (not ,expression) (go end))
           ,@body
           (go start)
     end))

(c) Pascal Constanza
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org
Re[2]: Amplifying C
От: yumi  
Дата: 25.01.10 13:37
Оценка:
Здравствуйте, A13x, Вы писали:

A>еще ссылка по теме для интересующихся: Google DSL

A>не совсем "amplifying C", но решает сходные задачи кодогенерации.

Сижу тихонько просматриваю исходники, и вижу:
     (method :my-method (return-type :string (doc "Return value.")) (public)
      (doc "This method does strange things.")


А если серьезно, то это некое тестовое определение метода.

ЗЫ: документации жаль никакой нет
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org
Re[3]: Amplifying C
От: A13x США  
Дата: 25.01.10 13:55
Оценка:
Здравствуйте, yumi, Вы писали:

Y>...

Y>ЗЫ: документации жаль никакой нет

Это да.

Если серьезно — в прошлом году меня посещали схожие мысли, что и автора "Amplifying C".
В первую голову смотрел на cl-dsl, но он мне не очень понравился своей навороченностью, отсутствием документации и проработанным наборов юнит тестов.
В свободное время пытаюсь сделать нечто подобное, в чем то упростив, в чем то усложнив концепцию обработки DSL-кода.

Благо — это хороший способ изучить лисп вообще
Да и черновые прототипы подобных вещей делаются за буквально за несколько минут на clisp, в отличие от других ЯП.
Re[3]: Amplifying C
От: Mr.Cat  
Дата: 25.01.10 14:16
Оценка:
Здравствуйте, A13x, Вы писали:
A>Чтобы иметь удобную возможность оперировать с кодом из lisp, опять же lisp-синтаксис (лично мне) кажется очень стройным и логичным.
A>S-выражения достаточны для описанной задачи, а так же универсальны и однотипны.
Я тоже люблю s-выражения, но подозрительно отношусь к тому, чтобы насаждать s-выражения там, где их изначально не было.
Суть сабжевого проекта, как я понимаю, заменить неудачную макросистему C (ака #define) на более удачную плюс реализовать дополнительный анализ кода. В качестве примера использования макросистемы приводится реализация некой полезной библиотеки макросов. Соответственно, возникает вопрос: смогу ли я воспользоваться этой библиотекой из своего кода на C (допустим, для этого придется добавить дополнительный шаг в процесс сборки — но и фиг бы с ним) или вынужден буду переписать весь код на Lisp-C? Второй вариант кажется мне достаточно обидным.
Re[4]: Amplifying C
От: A13x США  
Дата: 25.01.10 14:44
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

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

A>>Чтобы иметь удобную возможность оперировать с кодом из lisp, опять же lisp-синтаксис (лично мне) кажется очень стройным и логичным.
A>>S-выражения достаточны для описанной задачи, а так же универсальны и однотипны.
MC>Я тоже люблю s-выражения, но подозрительно отношусь к тому, чтобы насаждать s-выражения там, где их изначально не было.
MC>Суть сабжевого проекта, как я понимаю, заменить неудачную макросистему C (ака #define) на более удачную плюс реализовать дополнительный анализ кода. В качестве примера использования макросистемы приводится реализация некой полезной библиотеки макросов. Соответственно, возникает вопрос: смогу ли я воспользоваться этой библиотекой из своего кода на C (допустим, для этого придется добавить дополнительный шаг в процесс сборки — но и фиг бы с ним) или вынужден буду переписать весь код на Lisp-C? Второй вариант кажется мне достаточно обидным.

Не знаю в таких деталях предлагаемого автором синтаксиса, но было бы нелепо лишать пользователей библиотеки возможности подключать свои файлы — не предусмотрев что-то типа (include "mylib.h").

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

Возникает вопрос — как делать проверки на экспортируемые из mylib.h функции и типы?
Тут есть варианты:
— просто игнорировать, для чего после пользователю нужно будет еще описать игнорируемые значения (что есть не очень хорошо, но просто и понятно).
— заставить пользователя описать, что находится в mylib.h (чревато ошибками при изменении структурного содержания экспортируемых сущностей).
— парсить mylib.h и выдирать описания структур и типов (только как быть с дефайнами? вообще можно и тут что то придумать , например, предлагать писать (include "mylib.h" (defines (ARCH "x86") (MY_BLOCK_SIZE 14))))
Re[5]: Amplifying C
От: Mr.Cat  
Дата: 25.01.10 15:03
Оценка:
Здравствуйте, A13x, Вы писали:
A>Не знаю в таких деталях предлагаемого автором синтаксиса, но было бы нелепо лишать пользователей библиотеки возможности подключать свои файлы — не предусмотрев что-то типа (include "mylib.h").
Я про наоборот. Можно ли будет из уже написанного кода на C вызвать макрос, написанный на сабжевом лиспе.
Re[5]: Amplifying C
От: Code Digger Грузия  
Дата: 25.01.10 16:15
Оценка:
Здравствуйте, A13x, Вы писали:

A>Не знаю в таких деталях предлагаемого автором синтаксиса, но было бы нелепо лишать пользователей библиотеки возможности подключать свои файлы — не предусмотрев что-то типа (include "mylib.h").


Автор упоминал про предполагаемую возможность подключения сторонних Си-библиотек. Писал что-то в духе "нужно будет импортировать определения типов данных и функций в персистентное хранилище отдельной утилитой — и в путь: дальше амплифаер без всяких инклудов будет вставлять потребные описания по мере необходимости."
Re[6]: Amplifying C
От: Code Digger Грузия  
Дата: 25.01.10 16:18
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

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

A>>Не знаю в таких деталях предлагаемого автором синтаксиса, но было бы нелепо лишать пользователей библиотеки возможности подключать свои файлы — не предусмотрев что-то типа (include "mylib.h").
MC>Я про наоборот. Можно ли будет из уже написанного кода на C вызвать макрос, написанный на сабжевом лиспе.

Собственно макрос, конечно, не вызвать. Но можно будет вызвать функцию, в которую этот макрос развернётся. Нужно только будет заставить амплифаер генерировать соответствующие заголовочные файлы. Или типа того.
Re: Amplifying C
От: Code Digger Грузия  
Дата: 25.01.10 16:20
Оценка:
Здравствуйте, yumi, Вы писали:

Y>Здесь.


Лично меня интересует вопрос, далеко ли можно уехать на одних только compile-time макросах? Сила лиспа не в одних макросах заключена...
Re[3]: Amplifying C
От: Mr.Cat  
Дата: 25.01.10 18:20
Оценка: +1
Здравствуйте, yumi, Вы писали:
Y>Нужен или нет, каждый сам для себя решает
Я вот пробую принять сторону тех, кто решил, что не нужен.

Y>Лиспосинтаксис aka s-expressions проще, в том смысле, что ими проще манипулировать, трансформировать, ведь это и есть по сути AST. В немерле уже сложнее, в основном видимо из-за наличия синтаксиса, многостадийности компиляции и нескольких AST на разных стадиях компиляции. Например, точно не помню, очень примерно, на этапе лексического анализа используется PreParse tree, далее, ParseTree, потом TypedTree, как-то так. Т.е. внутри макроса, мы должны знать, на каком этапе мы и какое дерево нам доступно.

Ну раз есть макросы, манипулирующие TypedTree — значит макросы знают о статической типизации (которой в cl/scheme/clojure какбы нет) и это в любом случае вызовет сложности. Это все-таки ортогонально представлению кода в s-выражениях.

Y>Можно сравнить на простых примерах.

Я немерле в достаточной мере не знаю, чтобы как-то прокомментировать твои примеры, но видится мне, что немерлейные макросы из примеров имеют больше возможностей. Из while торчат уши break и continue, а when видистя мне чем-то большим, нежели синонимом if (впрочем, он мне в первую очередь видится какой-то неведомой хреновиной).

Я вот пока для себя слабо представляю, почему макросистемы в языках, не онованных на s-exp-ах обяхательно будут сложнее/неудобнее/хуже/...
Вот взять к примеру plot (обсуждения гуглятся по "PLOT: A non-parenthesized, infix Lisp!"). Автор его даже диалектом лиспа называет. А синтаксис у него питоноподобный (вспомнился boo, который еще можно было б приплести, но я его не знаю).
Re[3]: Amplifying C
От: WolfHound  
Дата: 26.01.10 11:12
Оценка:
Здравствуйте, yumi, Вы писали:

Y>Т.е. внутри макроса, мы должны знать, на каком этапе мы и какое дерево нам доступно.

Для большенства вещей ParseTree хватает за глаза.
PreParse tree и TypedTree нужны когда хочется сделать что-то действительно навороченное.
Например грамматику задавать вот таким образом:
  grammar
  {
    any           = ['\u0000' .. '\uFFFF'];
    letter        = ['a' .. 'z'] / ['A' .. 'Z'] / '_';
    digit         = ['0' .. '9'];
    spaces        = ' '*;
    id     : Expr = (letter (digit / letter)*) spaces;
    num    : Expr = digit+ spaces;
    expr'  : Expr = '(' spaces sum ')' spaces;
    expr   : Expr = num / id / expr';
    sum    : Expr = expr ('+' spaces expr)* spaces;
    start  : Expr = spaces sum spaces !any;
  }


Y>Можно сравнить на простых примерах.

Давай только сначала я вырежу из немерловах макросов тут функционал которого нет в макросах лиспа:

Макрос when на Nemerle:
  macro whenmacro (cond, body)
  syntax ("when", "(", cond, ")", body) 
  {
    <[ match ($cond) { | true => $body : void | _ => () } ]>
  }

Y>(c) nemerle\macros\core.n

Y>Макрос when на Lisp'e:

Y>
Y>(defmacro when (condition &rest body)
Y>  `(if ,condition (progn ,@body)))
Y>

Y>(c) Practical Common Lisp by Peter Seibel

Макрос while на Nemerle:
    macro @while (cond, body)
    syntax ("while", "(", cond, ")", body) 
    {
        <[ 
            def loop() : void {
                when ($cond) {
                    $body;
                    loop()
                }
            } 
            loop(); 
        ]>
    }


Y>Макрос while на Lisp'e:

Y>
Y>(defun while-function (predicate block)
Y>  (if (not (funcall predicate)) (return))
Y>  (funcall block)
Y>  (while-function predicate block))  

Y>(defmacro while (expression &body body)
Y>  `(while-function (lambda () ,expression)
Y>     (lambda () ,@body)))
Y>

Y>(c) Pascal Constanza

Y>или


Y>более простой макрос, но более эффективный while на Lisp'e:

Y>
Y>(defmacro while (expression &body body)
Y>  `(tagbody
Y>     start (if (not ,expression) (go end))
Y>           ,@body
Y>           (go start)
Y>     end))
Y>

Y>(c) Pascal Constanza
Ну как немерле все еще сложнее?
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Amplifying C
От: yumi  
Дата: 26.01.10 13:15
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Ну как немерле все еще сложнее?


Теперь все фен-шую А что это за аццкие синтаксические штучки были? Какой функционал они добавляют?
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org
Re[5]: Amplifying C
От: WolfHound  
Дата: 26.01.10 14:48
Оценка: 8 (1)
Здравствуйте, yumi, Вы писали:

Y>Теперь все фен-шую А что это за аццкие синтаксические штучки были? Какой функционал они добавляют?

while который сейчас выглядит так содержит код для того чтобы работали break и continue
  macro @while (cond, body)
  syntax ("while", "(", cond, ")", body) 
  {
    <[ 
      ($("_N_break" : global) : {
        def loop () : void
        {
          when ($cond)
          {
            ($("_N_continue" : global) : {
              $body
            }) : void;
            loop ()
          }
        } 
        
        loop (); 
      }) : void
    ]>
  }

Вот реализация break и continue
  macro Break ()  syntax ("break")
  {
    <[ $("_N_break" : global) () ]>
  }
  
  macro Continue ()  syntax ("continue")
  {
    <[ $("_N_continue" : global) () ]>
  }

Макры по умолчанию гигиеничны так что global нужен чтобы подавить гигиену.

В when накручена поддержка синтаксиса
when (asdasd is SomeType when blah-blah)
{
    ...
}

зачем не знаю
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.01.10 19:19
Оценка: 8 (1) -1
Здравствуйте, yumi, Вы писали:

Y>Лиспосинтаксис aka s-expressions проще, в том смысле, что ими проще манипулировать, трансформировать, ведь это и есть по сути AST. В немерле уже сложнее, в основном видимо из-за наличия синтаксиса, многостадийности компиляции и нескольких AST на разных стадиях компиляции. Например, точно не помню, очень примерно, на этапе лексического анализа используется PreParse tree, далее, ParseTree, потом TypedTree, как-то так. Т.е. внутри макроса, мы должны знать, на каком этапе мы и какое дерево нам доступно.


Трасформация в немерле ведется только на ParseTree. Точнее во время типизации, перед превращением ParseTree в TypedTree. Но TypedTree использовать не обязательно. Он нужен только изредка для анализа типов. Это уже высший пилотаж. Лисп этого не поддерживает. В нем это просто бессмысленно, так как Лисп язык с динамической типизацией.

Y>Можно сравнить на простых примерах.


Y>Макрос when на Nemerle:

Y>
Y>  macro whenmacro (cond, body)
Y>  syntax ("when", "(", cond, ")", body) 
Y>  {
Y>    def res1 = match (cond)
Y>    {
Y>      | <[ $subCond is $pattren ]> with guard = null
Y>      | <[ $subCond is $pattren when $guard ]> =>
Y>        def res2 = match (pattren)
Y>        {
Y>          | PT.PExpr.Call when guard != null => 
Y>            <[ match ($subCond) { | $pattren when $guard => $body : void | _ => () } ]>
Y>          | PT.PExpr.Call => 
Y>            <[ match ($subCond) { | $pattren => $body : void | _ => () } ]>
Y>          | _ => <[ match ($cond) { | true => $body : void | _ => () } ]>
Y>        }
Y>        res2
Y>      | _ => <[ match ($cond) { | true => $body : void | _ => () } ]>
Y>    }
Y>    res1
Y>  }
Y>

Y>(c) nemerle\macros\core.n

Y>Макрос when на Lisp'e:

Y>
Y>(defmacro when (condition &rest body)
Y>  `(if ,condition (progn ,@body)))
Y>

Y>(c) Practical Common Lisp by Peter Seibel

Это не корректное сравнение, так как немерловый when гораздо мощьнее. Он по совместительству является гуардом (защитной конструкцией) и поддерживет паттерн-матчинг. Аналок when из лиспа будет выглядеть так:
public macro When(condition, body)
syntax ("when", "(", condition, ")", body)
{
  <[ match ($condition)
     {
       | true  => $body
       | false => ()
     }
  ]>
}

На мой взгляд система квази-цитирования немерла намного понятнее и читабельнее нежели аналогичная в Комон Лисп.
Краткий курс немерловый макросов для лисперов
Квази-цитирование
Тип                 Comon Lisp             Nemerle

Цитата кода         `( цитируемый код )    <[ цитируемый код ]>

Вставка кода        ,переменная            $переменная
из переменной
(unquote)

Вставка кода        ,@переменная           ..$переменная
из списка 
(unquote списка)


Очевидна, что разницы практически нет. Кроме того, что в немерле применяется полноценный синтаксис, а не безликие списки.

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


Y>Макрос while на Nemerle:

Y>
Y>  macro @while (cond, body)
Y>  syntax ("while", "(", cond, ")", body) 
Y>  {
Y>    def loop = Nemerle.Macros.Symbol (Util.tmpname ("while_"));

Y>    <[ 
Y>      $("_N_break" : global) : {
Y>        def $(loop : name) () : void {
Y>          when ($cond) {
Y>            $("_N_continue" : global) : {
Y>              $body 
Y>            } 
Y>            $(loop : name) ()
Y>          }
Y>        } 
Y>        $(loop : name) (); 
Y>      }
Y>    ]>
Y>  }
Y>

Y>(c) nemerle\macros\core.n

Y>Макрос while на Lisp'e:

Y>
Y>(defun while-function (predicate block)
Y>  (if (not (funcall predicate)) (return))
Y>  (funcall block)
Y>  (while-function predicate block))  

Y>(defmacro while (expression &body body)
Y>  `(while-function (lambda () ,expression)
Y>     (lambda () ,@body)))
Y>

Y>(c) Pascal Constanza

Ну, вот уже близко по объему. Если учесть, что немерловый цикл поддерживает break и continue, так вообще все становится на свои места.
Кроме того это очень старая версия которую то ли писали с бодуна, то ли еще во времена когда гигиены не было. Вот так она выглядит сегодня:
  macro @while (cond, body)
  syntax ("while", "(", cond, ")", body) 
  {
    <[ 
      ($("_N_break" : global) : {
        def loop () : void
        {
          when ($cond)
          {
            ($("_N_continue" : global) : {
              $body
            }) : void;
            loop ()
          }
        } 
        
        loop (); 
      }) : void
    ]>
  }



Y>более простой макрос, но более эффективный while на Lisp'e:

Y>
Y>(defmacro while (expression &body body)
Y>  `(tagbody
Y>     start (if (not ,expression) (go end))
Y>           ,@body
Y>           (go start)
Y>     end))
Y>

Y>(c) Pascal Constanza

Если он более эффективный, то это говорит о плохом качестве реализации лисп-машины. Ну, а то, что он проще, так в нем вообще не поддерживается прерывание цикла. Аналог на немерле:
  macro @while (cond, body)
  syntax ("while", "(", cond, ")", body) 
  {
    <[ 
        def loop() 
        {
          when ($cond)
            $body

          loop();
        } 
        
        loop();
      }
    ]>
  }


После компиляции он будет переписан компиляторов в аналог сишного while-а, с соответствующей эффективности.

Так что, уважаемый, ты тут распространяешь неверные слухи.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.01.10 19:28
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>В when накручена поддержка синтаксиса

WH>
WH>when (asdasd is SomeType when blah-blah)
WH>{
WH>    ...
WH>}
WH>

WH>зачем не знаю

Затем же зачем в лиспе есть when при наличии if который может не иметь "else"-части — чтобы можно было не создавать match c пустым "! _ =>" и чтобы можно было делать нечто что в обероне называется type guard. Скажем так:
def o : option[strint] = Some("строка");

when (o is Some(value))
  doStaf(value);

В value оказывается значение из Some, если "o" содержит Some.
Если в "o" оказывается None(), то управление не передается в when.
Аналогичный код с использованием match-а будет выглядеть так:

def o : option[strint] = Some("строка");

match (o)
{
  | Some(value) => doStaf(value);
  | _ => () // ничего не делаем!
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.01.10 19:32
Оценка:
Здравствуйте, Code Digger, Вы писали:

CD>Лично меня интересует вопрос, далеко ли можно уехать на одних только compile-time макросах? Сила лиспа не в одних макросах заключена...


А можно перечислить то, что есть в Лиспе и нет, скажем в Немерле? Ну, кроме динамически компилируемых макросов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.