Re[7]: Amplifying C
От: A13x США  
Дата: 28.01.10 13:39
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>...

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

Я не спец в lisp-е, но лично мне очевидны следующие преимущества:
1) Концепция "код как данные". Возможность конструировать программу буквально на лету (подход на макросах или для собственных DSL — через read/eval). В таком виде как у lisp нет нигде, насколько я знаю.
2) Универсальный, очень простой и очень мощный синтаксис, в котором все представляется атомами и s-выражениями (элементы типа ' или #' не в счет, это синтаксический сахар к (quote X), (function X)).
3) Очень мощная и расширяемая объектная система CLOS. C# второй и третей версии, например, не поддерживает мультиметодов. В общем, можно сказать что он и близко не стоял с CLOS.
4) Удобный REPL (есть во многих ФП, но не везде, например, насколько я знаю, в C# нету).
5) Можно использовать преимущества как динамической, так и статической типизации.
...

На эту тему написано довольно много — google "why lisp". Хотя бы это или вот это.

P.S. макросы в Common Lisp не предназначены для анализа типов. Образно говоря они работают до интерпретации/компиляции программы.
И это скорее хорошо, чем плохо — т.к. выражения, которые они генерируют могут быть использованы для самых разных целей. Если очень хочется то можно вставить и возможность определения типов типизацию, в зависимости от целей.
defmethod/defgeneric — это макросы, однако defmethod вносит возможность определять мультиметоды. В этом смысле можно считать, что анализ типа можно ввести и в lisp.
Причем ввести таким образом, как это будет нужно разработчику программы, а не lisp-компилятора.
Re[10]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 13:53
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

VD>>ОК. Опиши что там большее. Лучше с примерами.

MC>Навскидку различие в том, что в немерле (насколько я понял) выбирается набор определенных структур данных (те, что используются для формирования ast), чье внешнее представление нарекается корректным кодом.
MC>В лиспе немного наоборот — внешнее представление любой струткуры данных потенциально является корректным кодом (с учетом немногочисленных ограничений имплементации и макросистемы). Как-то так.

Это набор заблуждений.
Начнем с того, что в Лиспе не всякая структура данных может быть представлен как код. Вот пример такого списка — ("text" 1 2).

Вся разница между немерлом и лиспом по существу заключается в том, что в лиспе убогий синтаксис, что облегчает представление кода в виде данных. Но и там, и там для представления кода в виде данных используется один и тот же механизм — квази-цитирование. Этот механизм позволяет взять код в "ковычки" (в лисе это `( ... ), а в немерле <[ ... ]>) и получить на выходе структуру данных описывающую код. Кавычки могут иметь места-заполнители в которых может находиться код формирующих части формируемой структуры (для лиспа это ,( ... ), для немерла $( ... )).
Так что все практически идентично. И Лисп и Немерле позволяют представлять код в виде данных и манипулирвоать им.

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

В любом случае для обработки кода представленного в виде данных можно использовать всю мощь языка (функции работы со списками, замыкания, другие макросы, ...).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 13:58
Оценка:
Здравствуйте, Code Digger, Вы писали:

CD>Лично мне интереснее в этой области поговорить про Template Haskell — монада там не для красного словца используется.


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

CD>Благодарю. На Вы мне общаться как-то привычнее, а то вспылил в прошлом комменте, за что прошу прощения.


Что поделаешь? Как говорится — "В чужой монастырь со своим уставом со своим уставом ...".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 14:05
Оценка:
Здравствуйте, Code Digger, Вы писали:

CD>Вообще-то, вопрос не ко мне. Я не настолько хорошо знаю Лисп, и не знаю Немерле, про который был вопрос.

CD>Не могу сказать, в фичах ли языка тут дело, или в манере программирования, точнее, том, что на Лиспе изобретались и обкатывались самые разные парадигмы программирования, но если сравнить, например, CLOS и MOP с любой другой объектной системой, то становится немного странно от того, насколько легко и тонко можно расширять CLOS. И даже без макросов.

Я не заметил в MOP и созданном на его основе CLOS что-то действительно ценное. Более того я так и не нашел ни одного проекта где бы CLOS использовался на практике. Несомненно они есть, то похоже использование лиспа без CLOS намного более распространенное явление.

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

Единственное что есть в CLOS интересного — это мультиметоды. Но у них есть не мало своих проблем. Они тоже решение динамическое и плохо совместимое с компонентной природой дотнета (и вообще, современных систем). В то же время семантически паттерн-матчинг прекрасно заменяет мультиметоды. Кроме того их можно создать просто на базе динамических свойств дотнета.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 14:27
Оценка:
Здравствуйте, A13x, Вы писали:

A>вы плохо осведомлены о Common Lisp-е.


Я не скажу, что я знаток Комон Лиспа, но все же кое что в нем понимаю.

A>1) чтобы "случайно" не захватывать контекст придуман gensym, что то вроде такого:


A>
A>(defmacro do-primes ((var start end) &body body)
A>  (let ((ending-value-name (gensym)))
A>    `(do ((,var (next-prime ,start) (next-prime (1+ ,var)))
A>          (,ending-value-name ,end))
A>         ((> ,var ,ending-value-name))
A>       ,@body)))
A>


A>проверять это можно элементарно в REPL развертывая макрос через macroexpand-1, macroexpand и проч.


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

A>SBCL — компилирует в машинный код, причем по скорости он будет сравним с C.


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

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

A>В функциях можно задавать типы аргументов (через declare).


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

A>Функции (в их defmethod ипостаси) могут быть описаны с указанием возможных типов и даже возможных значений:


A>
A>(defmethod print-c ((statement p-qualified-type) stream) ... )

A>(defmethod parse-type-decl (context (id (eql 'struct)) args) ... )
A>


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

A>А по поводу неудобства и "безликости" списков — это ваше личное мнение.


Это мнение 99% программистов, которые не выбирают лисп просто из-за скобок. Вот недавно его высказывали в форуме "Образование":
http://rsdn.ru/forum/education/3668807.1.aspx
Автор: VladD2
Дата: 14.01.10

Почитай. Весьма любопытно. За одно можешь убедиться, что как раз я то отношусь к лиспу очень с уважением и без предвзятости .

A>Лично мне Lisp видится намного более логичным и элегантным, чем Nemerle.


Ну, естественно. Если одно знаешь, а второе даже в глаза не видел, то по другому и быть не может.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 14:28
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

VD>>В Схеме гигиена есть, но она во много раз менее удобна.

MC>Чем же?

Там обратная проблема. Чтобы ее преодалеть нужно раком встать. А иногда это нужно. В немерле же все просто. Есть набор идентификаторов позволяющих объяснить компилятору как интерпретировать символ.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Amplifying C
От: Mr.Cat  
Дата: 28.01.10 14:42
Оценка: -1
Здравствуйте, VladD2, Вы писали:
VD>Начнем с того, что в Лиспе не всякая структура данных может быть представлен как код.
Таки всякая.

VD>Вот пример такого списка — ("text" 1 2).

Это код. Честное слово код. Причем валидный. И я это чуть ниже продемонстрирую.
Как я говорил, это зависит от потрохов имплементации. По стандарту схемы получается что, да, валидные топлевелные выражения должны быть списками, у которых car — это символ. Т.е. по стандарту
("text" 1 2)

Это код, просто невалидный от рождения. Его вычисление валится с ошибкой.
А вот с тем, что вот это вполне вероятно валидный код — никто спорить не будет. Потому что семантика любых кододанных определяется самим программистом с небольшими ограничениями со стороны имплементации.
(f ("text" 1 2))

Идем дальше. Всеми любимая plt-scheme позволяет определять семантику любых структур данных. Например, я хочу, чтобы
("строка" символы ...)

вычислялось как форматирование символов строкой. Нет ничего проще. Берем и переопределяем в одном модуле форму #%app:
;sapp.scm
#lang scheme
(provide (except-out (all-from-out scheme) #%app)
         (rename-out [app #%app]))
(define-syntax-rule (app f x ...)
  ;; note that applications in the resulting pattern use our own
  ;; `#%app' implicitly
  (begin (if (string? f)
             (with-output-to-string (lambda () (printf f x ...)))
             (f x ...))))

А в другом — используем
;test.scm
#lang s-exp "sapp.scm"
("~s + ~s = ~s" 1 2 3) ;-> "1 + 2 = 3"

Вот так. Я, кстати, давал линк на статейку про это — но всем почему-то было как обычно.

VD>Кроме того в немерле в данных представляющих код (AST) имеется дополнительная информация.

Это опять же детали реализации, в scheme некоторые макросистемы (например, syntax-case) оперируют обертками над кододанными, какие-то — передают дополнительную информацию отдельно.

Насчет цитирования и по сабжу в целом:, как бы мне сделать, чтобы вот это стало валидной программой на немерле?
[f, 1, 2, 3]
Re[6]: Amplifying C
От: Mr.Cat  
Дата: 28.01.10 14:45
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Там обратная проблема. Чтобы ее преодалеть нужно раком встать. А иногда это нужно. В немерле же все просто. Есть набор идентификаторов позволяющих объяснить компилятору как интерпретировать символ.
Сорри, я ход твоих мыслей не уловил. Можно на примере (ну типа макры немерле против одной из макросистем схемы)?
Re[6]: Amplifying C
От: A13x США  
Дата: 28.01.10 14:56
Оценка:
Здравствуйте, VladD2, Вы писали:

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


A>>вы плохо осведомлены о Common Lisp-е.


VD>Я не скажу, что я знаток Комон Лиспа, но все же кое что в нем понимаю.


A>>1) чтобы "случайно" не захватывать контекст придуман gensym, что то вроде такого:


A>>
A>>(defmacro do-primes ((var start end) &body body)
A>>  (let ((ending-value-name (gensym)))
A>>    `(do ((,var (next-prime ,start) (next-prime (1+ ,var)))
A>>          (,ending-value-name ,end))
A>>         ((> ,var ,ending-value-name))
A>>       ,@body)))
A>>


A>>проверять это можно элементарно в REPL развертывая макрос через macroexpand-1, macroexpand и проч.


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


gensym — это функция, а не макрос. По поводу обращения к внешнему контексту — это спорно. Гигиена обеспечена? Обеспечена с помощью gensym. Остальное — лирика.

A>>SBCL — компилирует в машинный код, причем по скорости он будет сравним с C.


VD>Ну, начнем с того, что по крайней мере под Windows SBCL практически не существует. Сколько я его не смотрел он постоянно находится в состоянии альфа-версии и безбожно глючит.


Не SBCL-ом единым... Есть еще LispWorks, AllegroCL, CMUCL, CLISP...
Я, кстати, работаю с SBCL не на windows, так что для меня это не аргумент. На windows SBCL работает сносно уже несколько лет, несмотря на статус. Disclaimer оговаривает с чем могут возникнуть проблемы.

VD>Рассказы про то, что любой код переписывается в оптимальный маш.код и "будет сравним с C" — это не более чем миф.

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

A>>В функциях можно задавать типы аргументов (через declare).


VD>Вот именно. И после этого лисп уже становится не лиспом а жалкой породией на него. И это на фоне вывода типов и полной статической типизации того же немерла.

VD>Сравненные явно не в пользу лиспа, не находишь? ...

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

defmethod как раз таки используется довольно часто именно в форме с указанием типов, в противном случае нет особого смысла его использовать и можно обойтись defun.
Re[8]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 15:02
Оценка:
Здравствуйте, A13x, Вы писали:

A>Я не спец в lisp-е, но лично мне очевидны следующие преимущества:

A>1) Концепция "код как данные". Возможность конструировать программу буквально на лету (подход на макросах или для собственных DSL — через read/eval). В таком виде как у lisp нет нигде, насколько я знаю.

Ну, полноте ерунду то говорить. Концепция "код как данные" есть не в одном лиспе, а то что "буквально на лету", так это ни какое вовсе не преимущество. Если лисп компилируется, то все макры при этом так же раскрываются. Так что нет никакой разницы между скомпилированным динамически модулем немерла или липса. Ну, разве что сделать это в лиспе несколько проще.
Дык за эту простоту приходится собственной крышей платить. А потребность в динамических макросах крайне редка.

A>2) Универсальный, очень простой и очень мощный синтаксис, в котором все представляется атомами и s-выражениями


Полное отсутствие синтаксиса в угоду упрощения манипуляции кодом. Вот так будет проще.

A>(элементы типа ' или #' не в счет, это синтаксический сахар к (quote X), (function X)).


Да какая разница как цитаты называть? Хотя конечно никому в голову не придет quote использовать в реальном коде. Ну, а function и #' — это просто продолжение убогости синтаксис. В языках с синтаксисом такой маразм и не снился. В них любое имя функции уже ссылка на нее. А лямбда может передаваться в контекст где ожидается функция без всяких префиксов. Так что полноте убогость рекламировать.

A>3) Очень мощная и расширяемая объектная система CLOS. C# второй и третей версии, например, не поддерживает мультиметодов. В общем, можно сказать что он и близко не стоял с CLOS.


Опять сказка выдаваемая за действительность. Интерпретируемая, редко используемая, очень не похожая на привычный людям ООП. ООП нонче есть почти везде.

A>4) Удобный REPL (есть во многих ФП, но не везде, например, насколько я знаю, в C# нету).


О! Это тоже у нас преимущество лиспа?
А я его видел в хаскеле, F#-е, Скале, Немерле... Скоро будет в C#.

A>5) Можно использовать преимущества как динамической, так и статической типизации.

A>...

Не. Можно с серьезной болью в заднице использовать статическую типизацию. Вывода типов нет. Система типов CLOS является настройкой. В основной системе типов нет рефлексии и других полезных и современных вкосностей.

A>На эту тему написано довольно много — google "why lisp". Хотя бы это или вот это.


Да кто бы сомневался. 50 лет — это срок за который можно многое написать. Но люди его как-то не принимают.

A>P.S. макросы в Common Lisp не предназначены для анализа типов. Образно говоря они работают до интерпретации/компиляции программы.


Это преимущество?

A>И это скорее хорошо, чем плохо — т.к. выражения, которые они генерируют могут быть использованы для самых разных целей. Если очень хочется то можно вставить и возможность определения типов типизацию, в зависимости от целей.


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

A>defmethod/defgeneric — это макросы, однако defmethod вносит возможность определять мультиметоды. В этом смысле можно считать, что анализ типа можно ввести и в lisp.


Не. Мультиметоды — это совершенно динамическая фича. И потому весьма не эффективная.

A>Причем ввести таким образом, как это будет нужно разработчику программы, а не lisp-компилятора.


Ну, так в чем же это мифическое приемущество Лиспа? А CLOS? Дык он на макросах написан. В динамике? Дык а причем тут эффективность? Да и динамики у нас хоть пруд пруди. Руби и Питон очень динамичны. Причем они тоже компилируются (гы-гы).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 15:25
Оценка: -1
Здравствуйте, Mr.Cat, Вы писали:

VD>>Вот пример такого списка — ("text" 1 2).

MC>Это код. Честное слово код. Причем валидный. И я это чуть ниже продемонстрирую.

Не. Это структур данных которая кодом не является по определению. В лиспе есть понятия "форм лиспа". И данный список не подпадает под него, так как начинается не символа.

MC>Как я говорил, это зависит от потрохов имплементации.


Не. Это оговаривается стандартом Комон Лисп.

По стандарту схемы получается что, да, валидные топлевелные выражения должны быть списками, у которых car — это символ. Т.е. по стандарту
MC>
MC>;("text" 1 2)
MC>;

MC>Это код, просто невалидный от рождения. Его вычисление валится с ошибкой.
MC>А вот с тем, что вот это вполне вероятно валидный код — никто спорить не будет. Потому что семантика любых кододанных определяется самим программистом с небольшими ограничениями со стороны имплементации.
MC>
MC>;(f ("text" 1 2))
MC>;


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

MC>...Это опять же детали реализации, в scheme некоторые макросистемы (например, syntax-case) оперируют обертками над кододанными, какие-то — передают дополнительную информацию отдельно.


А кому нужен язык зависящий от деталей реализации? Тогда не надо говорить о Лиспе как о языке. Говори о конеретных компиляторах/интерпретаторах конкретных диалектов. Когда мне говорят Лисп, я понимаю это как Комон Лисп. У него конечно есть разные реализации, но они все подчиняются стандарту. И это замечательно!

MC>Насчет цитирования и по сабжу в целом:, как бы мне сделать, чтобы вот это стало валидной программой на немерле?

MC>
MC>[f, 1, 2, 3]
MC>

Если понимать "валидной программой" как это ты понимаешь, то ничего делать и не надо. Это и так допустимый код.

В любом конетесте он конечно не допустим, но не проблема сделать так, чтобы он был допустим где-то. Например, в Немерле поддерживает так называемый list comprehension. Вот, например, как реализована стандартная функция Filter в типе list[T]:
public Filter[T](this seq : SCG.IEnumerable[T], predicate : T -> bool) : list[T]
{
  $[ x | x in seq, predicate (x) ]
}


$[ x | x in seq, predicate (x) ] — list comprehension.
Конструкция практически аналогичная хаскелевской, за тем исключением, что это макрос реализованный в стандартной библиотеке макросов:
http://nemerle.googlecode.com/svn/nemerle/trunk/macros/Util.n
  macro ExpandListComprehension (params exprs : list [PExpr])
  {
    def adder =
      <[
         def cell = $(exprs.Head) :: [];
         if (head == null) {
           head = cell;
           tail = cell;
         } else {
           _N_skip_write_check (tail.tl) = cell;
           tail = cell;
         }
       ]>;
       
    def loops =
      exprs.Tail.Rev ().FoldLeft (adder,
        fun (e, acc) {
          match (ListComprehensionHelper.ExpandRange (e, acc)) {
            | Some (expr) => expr
               
            | None =>
              match (e) {
                | <[ $e1 in $e2 ]> =>
                  <[ foreach ($e1 in $e2) $acc ]>
                | cond =>
                  <[ when ($cond) $acc ]>
              }
          }
        });

    match (exprs) {
      | [<[ $second .. $last ]>] =>
        <[ $[ x | x in [$second .. $last]] ]>

      | [<[ $first ]>, <[ $second .. $last ]>] =>
        <[ $[ x | x in [$first, $second .. $last]] ]>
        
      | _ =>
        <[
            mutable head = null;
            mutable tail = null;
            $loops;
            if (head == null)
              []
            else
              head
        ]>
    }
  } 

  public module ListComprehensionHelper
  {
    [Nemerle.Macros.Hygienic]
    public ExpandRange (inrange : PExpr, acc : PExpr) : option [PExpr]
    {
      match (inrange) {
        | <[ $pat in $[$first, $second .. $last] ]>
        | <[ $pat in [$first, $second .. $last] ]> =>
          Some (<[
             mutable i = $first;
             mutable delta = $second - i;
             def last = $last;
             mutable cond = if (delta < 0) i >= last else i <= last;             
             def pre_last = unchecked (last - delta);
             
             when (delta < 0 && pre_last < last || delta > 0 && pre_last > last) // we overflowed
               delta = -delta;
               
             while (cond) {
               def $pat = i;
               if (delta < 0) 
                 cond = i >= pre_last;
               else 
                 cond = i <= pre_last;
               unchecked (i += delta);
               $acc;
             }
          ]>)
           
        | <[ $pat in $[$first .. $last] ]>
        | <[ $pat in [$first .. $last] ]> =>
          Some (<[
             mutable i = $first;
             def last = $last;
             mutable cond = i <= last;
             mutable pre_last = last;
             unchecked (pre_last--); // can't use (last - 1) since 1 might change/widen type
             def overflowed = pre_last > last;
             while (cond) {
               def $pat = i;
               if (overflowed)
                 cond = i >= pre_last;
               else
                 cond = i <= pre_last;
               unchecked (i++);
               $acc;
             }
          ]>)

        | _ => None ()
      }
    }
  }


Не проблема создать скажем @[ ... ] синтаксис который будет вести себя как-то иначе.

Кроме того в контексте другого макроса код может интерпретироваться вообще как угодно. Вольфхаунд уже приводил в этой теме пример EBNF синтаксиса реализованного на безе макросов немерла:
http://rsdn.ru/forum/decl/3681785.1.aspx
Автор: WolfHound
Дата: 26.01.10

Весь смысл в том, что макрос данных применяется внутри другого макроса. Вот как выглядит это в реальном коде:
  [PegGrammar(sum, 
  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;
  })]
  class TestSum
  {
    // обработчики вызываемые при разборе текста
  }


Макрос grammar предоставляет измененный синтаксис соответствующий PEG-натации (нечто вроде EBNF). Он применяется внутри так называемого мета-атрибута (PegGrammar в данном случае). Мета-атрибут — это нечто похожее на кастом-атрибуты в C#, но вместо того чтобы превращаться в метаинформацию закладываемую в сборку, в немерле они рассматриваются как макросы раскрывающиеся во время компиляции и позволяющие изменить код компилируемого модуля.

Вполне возможно было бы использовать его и в коде. Например, так:
def g = DefineGramar(  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;
  });

def result = g.Parse("1 + 2");


Так что никаких принципиальных проблем нет. И при этом нет нужды жить в спартанских условиях (писать код без синтаксиса).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 15:32
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

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

VD>>Там обратная проблема. Чтобы ее преодалеть нужно раком встать. А иногда это нужно. В немерле же все просто. Есть набор идентификаторов позволяющих объяснить компилятору как интерпретировать символ.
MC>Сорри, я ход твоих мыслей не уловил. Можно на примере (ну типа макры немерле против одной из макросистем схемы)?

Скажем у нас есть имена "a", "b" и "c". Мы хотим чтобы "a" рассматривалось как глобальный символ (сопоставлялось бы только с символами из глобальных пространств имен), "b" находило бы символ динамически (т.е. брало сивол из любой области видимости доступный в момент раскрытия макроса), а "с" было был доступно только внутри макроса и не перекрывалось бы ни с какими именами. Тогда мы может написать цитату:
<[ $("a" : global) ...; $("b" : dyn) ....; c ...; /* или */ $("c" : name)]>

и компилятор сам все сделает. Да, "b" — это просто строка.
Кроме того есть API функции которые позволяют задать нужный контекст. Скажем если задать контекст используемый в компилируемом методе, то можно просто преодолеть гигиету и ссылаться на символы внутри контекста (т.е. как в Комон Лисп).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.01.10 15:56
Оценка:
Здравствуйте, A13x, Вы писали:

A>gensym — это функция, а не макрос. По поводу обращения к внешнему контексту — это спорно. Гигиена обеспечена? Обеспечена с помощью gensym. Остальное — лирика.


Ага. Функция. Только на Комон Лиспе никто так не пишет. Это отличный путь получить дырявую макру.
Введение ending-value-name — это закат солнца в ручную. Нормальный программист напишет with-gensyms (как в той книжке откуда взять твой пример) и будет жить спокойно.
Если же вводить переименования вручную, то дыр в твоем коде будет столько, что он будет способен только на то, чтобы служить примером того как не надо писать код.

Собственно все эти приседания и делают Комон Лисп сложным для использования средним программистом.

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


A>Не SBCL-ом единым... Есть еще LispWorks, AllegroCL, CMUCL, CLISP...


Ага. Только когда заходит речь о компиляции, то SBCL — это единственно что можно привести в качестве примера. Остальные до него не дотягивают.

A>Я, кстати, работаю с SBCL не на windows, так что для меня это не аргумент. На windows SBCL работает сносно уже несколько лет, несмотря на статус. Disclaimer оговаривает с чем могут возникнуть проблемы.


Тогда поверь. Под виндой он глючит страшно. Я раза три пробовал его использовать (с большими промежутками). Каждый раз получал кучу проблем.

A>Это уже спор о том, что лучше — динамическая типизация или статическая. Смысла нет обсуждать еще раз.


Дык к вопросу скорости выполнения кода — это имеет прямое отношение. Динамика имеет свои недостатки. И попытка совместить вкусности из двух миров сравни попытки сидеть на двух стульях одновременно.

A>Кстати, никто не заставляет пихать списки куда не лень. Лисп может использовать вектор, хэш-таблицу, что угодно.


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

A>declare имеет смысл использовать в критических местах кода, в остальных проверка типа в рантайме не замедлит ощутимо работу программы.


Дык если у тебя 99% кода написано не эффективным образом, то появляется эффект интерпретатора. Многие задачи при том уже становятся недоступными. А если лепить типы везде, то становится неудобно. На мой взгляд язык с выводом типов и возможно возможностью перейти на динамику по желанию — это намного лучше.

A>Нужно обоснование на базе вывода профайлера.


Ну, вот мы и получаем в результате, что весь код который пишут на лиспе со временем переписывают на С. Почему тот же Emacs написан на С, и толко макросистема в нем на Лиспе?

A>defmethod как раз таки используется довольно часто именно в форме с указанием типов, в противном случае нет особого смысла его использовать и можно обойтись defun.


Ну, дык вот в Немерле и пошли дальше. В нем любые методы (т.е. глобальные функции и методы) обязаны быть обявлены с полным указанием типов или параметрами инициализированными константами, а внутри в кода методов поддерживается автоматический вывод типов. При этом гарантируется, что типы будут или полностью выведены, или будет выдана ошибка. Таким образом с одной стороны как и в лиспе в немерле не нужно всюду писать типы, но в отличии от лиспа в немерле всегда получается весьма эффективный код. От того на немерле можно писать те же редакторы кода целиком, а не только использовать его в качестве макросистемы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Amplifying C
От: A13x США  
Дата: 28.01.10 22:35
Оценка:
Здравствуйте, VladD2, Вы писали:

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


A>>gensym — это функция, а не макрос. По поводу обращения к внешнему контексту — это спорно. Гигиена обеспечена? Обеспечена с помощью gensym. Остальное — лирика.


VD>Ага. Функция. Только на Комон Лиспе никто так не пишет. Это отличный путь получить дырявую макру.

VD>Введение ending-value-name — это закат солнца в ручную. Нормальный программист напишет with-gensyms (как в той книжке откуда взять твой пример) и будет жить спокойно.
VD>Если же вводить переименования вручную, то дыр в твоем коде будет столько, что он будет способен только на то, чтобы служить примером того как не надо писать код.

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

VD>Собственно все эти приседания и делают Комон Лисп сложным для использования средним программистом.


На работе я пишу на С++. И я бы не назвал С++ значительно более простым языком, чем Common Lisp.

Вдобавок, есть еще и личные предпочтения.
Мне вот так и не удалось осилить Python, просто не понравился синтаксис и как то забросил его. Perl осилил на уровне простых скриптов, чем временами пользуюсь, но без восторга. Впрочем всем оным я занимался, как и Lisp-ом, в свободное время, так что...

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


Ну так программистом вообще говоря быть не просто. Для всего есть порог вхождения...
Уровень coding monkey доступен многим, но многим ли нужен такой работник? Вообще говоря, судя по требованиям, в некоторые русские компании ждут по меньшей мере второго Саттера или Страуструпа

A>>Не SBCL-ом единым... Есть еще LispWorks, AllegroCL, CMUCL, CLISP...


VD>Ага. Только когда заходит речь о компиляции, то SBCL — это единственно что можно привести в качестве примера. Остальные до него не дотягивают.


ну как минимум AllegroCL и CMUCL дотягивают.

Пример для Allegro из сети:
CL-USER> (declaim  (optimize speed
                             (safety 0)
                             (space 0)
                             (debug 0)))
T
CL-USER> (defun my-func (x)
           (declare (fixnum x))
           (the fixnum (1+ x)))
MY-FUNC
CL-USER> (compile 'my-func)
MY-FUNC
NIL
NIL
CL-USER> (disassemble 'my-func)
;; disassembly of #<Function MY-FUNC>
;; formals:

;; code start: #x2083517c:
   0: 83 c0 04    addl    eax,$4
   3: f8          clc
   4: 8b 75 fc    movl    esi,[ebp-4]
   7: c3          ret


SBCL генерирует почти такой же код (проверял у себя на x86-64 linux):

cl-user> (disassemble 'my-func)
; disassembly for my-func
; 034511BF:       4883C208         add rdx, 8
;       C3:       488BE5           mov rsp, rbp
;       C6:       F8               clc
;       C7:       5D               pop rbp
;       C8:       C3               ret


Что то сложное измышлять уже лень — ибо спать пора.

A>>Я, кстати, работаю с SBCL не на windows, так что для меня это не аргумент. На windows SBCL работает сносно уже несколько лет, несмотря на статус. Disclaimer оговаривает с чем могут возникнуть проблемы.


VD>Тогда поверь. Под виндой он глючит страшно. Я раза три пробовал его использовать (с большими промежутками). Каждый раз получал кучу проблем.


OK. LispWorks, AllegroCL? Для них есть техподдержка...

A>>...


A>>Кстати, никто не заставляет пихать списки куда не лень. Лисп может использовать вектор, хэш-таблицу, что угодно.


VD>Ага. Только на практике везде списки. Скажем, список параметров переменной длинны — это автоматом список и не типизированный...


Почему? Согласен, что списки используются не очень редко, но при необходимости нет никаких проблем использовать vector или hash-table.
Не вижу препятствий.

Кстати, а чем плохи списки?

A>>declare имеет смысл использовать в критических местах кода, в остальных проверка типа в рантайме не замедлит ощутимо работу программы.


VD>Дык если у тебя 99% кода написано не эффективным образом, то появляется эффект интерпретатора. Многие задачи при том уже становятся недоступными. А если лепить типы везде, то становится неудобно. На мой взгляд язык с выводом типов и возможно возможностью перейти на динамику по желанию — это намного лучше.


A>>Нужно обоснование на базе вывода профайлера.


VD>Ну, вот мы и получаем в результате, что весь код который пишут на лиспе со временем переписывают на С. Почему тот же Emacs написан на С, и толко макросистема в нем на Лиспе?


Как бы не 90% emacs написано на лисп (если сравнивать директории lisp и src в исходниках).

Не совсем понимаю тут термин "макросистема".
C помощью elisp emacs можно расширять очень и очень серьезно. Как пример можно взять тот же slime.
elisp не компилирует в машинный код (во всяком случае точно не в emacs), какие-то базовые части, понятно, надо было реализовывать на С. Не забываем, что emacs был написан довольно давно и требования по памяти и ресурсам были не в пример жестче чем сейчас.
На современном оборудовании абсолютно никаких тормозов я не замечал (средненький ноутбук — DELL двухгодовой давности), чего не сказать про 2008 студию даже со всеми отключенными плагинами на значительно более мощной машине.


A>>defmethod как раз таки используется довольно часто именно в форме с указанием типов, в противном случае нет особого смысла его использовать и можно обойтись defun.


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


OK, довод понятен.

В общем, если вопрос об эффективности встал ребром, почему бы не написать критические части на С? Сомневаюсь, что на Nemerle (и на Lisp, наверное, тоже) кто-нибудь написал x.264 кодек для промышленного использования или драйвер уровня ядра.
Если важна стратегия оптимального использования памяти — позволяет ли хоть какой-нибудь ФП реализовывать аллокатор для своих нужд?
В то, что таких ситуаций не бывает, уж простите, не поверю.

На уровне прикладных CRUD-style приложений выигрыш будет просто мизерным.

Вот и получается, что Nemerle вроде бы и в чем то эффективней Lisp, но как это использовать — непонятно.

И еще: известен ли вам проект, написанный на Lisp и переписанный на Nemerle, поработав с которым можно было бы сказать — "так, вот этот подонок тормозит, все срочно идем на Nemerle (Assembler, C, РЯП, нужное подчеркнуть)"?
Есть ли математическое обоснование того, что Nemerle будет, например в 2-4 раза эффективнее для такого-то класса задач на таких-то машинах чем какая-либо популярная реализация Common Lisp (или что-то другое)?
Re[8]: Amplifying C
От: Mr.Cat  
Дата: 29.01.10 10:26
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Скажем у нас есть имена "a", "b" и "c". Мы хотим чтобы "a" рассматривалось как глобальный символ (сопоставлялось бы только с символами из глобальных пространств имен), "b" находило бы символ динамически (т.е. брало сивол из любой области видимости доступный в момент раскрытия макроса), а "с" было был доступно только внутри макроса и не перекрывалось бы ни с какими именами. Тогда мы может написать цитату:
VD>
VD><[ $("a" : global) ...; $("b" : dyn) ....; c ...; /* или */ $("c" : name)]>
VD>

VD>и компилятор сам все сделает. Да, "b" — это просто строка.

Ну это примерно то же самое, что и в syntax-case: по умолчанию создаваемые макросом символы не перекрываются ни с какими именами, а используемые ссылки относятся к области видимости в месте объявления макроса. По необходимости это ломается, благодаря параметру у datum->syntax, указывающему, откуда для вводимого символа унаследовать "контекст".
Вот классическая копипаста из r6rs (макрос создает внутри блока кода неявный биндинг):
(define-syntax loop
  (lambda (x)
    (syntax-case x ()
      [(k e ...)
       (with-syntax
          ([break (datum->;syntax #’k ’break)]) ;Прошу прощения за вставленный форматтером коммент после стрелки, там его быть не должно
          #’(call-with-current-continuation
              (lambda (break)
                (let f () e ... (f)))))])))

(let ((n 3) (ls ’()))
  (loop
  (if (= n 0) (break ls))
  (set! ls (cons ’a ls))
  (set! n (- n 1))))


В данном случае, кстати, видно, что цитирование в немерле — это аналог не лиспового цитирования, а создания синтаксических объектов в схемском syntax-case: syntax-quote (ака #'), datum->syntax и т.п.
Re[6]: Amplifying C
От: yumi  
Дата: 29.01.10 10:59
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Под Моно все не очень радостно. Сборки компилятора вроде бы работают если их просто скопировать. Но собрать сам компилятор под Моно похоже нельзя из-за ошибок в самом Моно. Их обещали поправить, но похоже так этого и не сделали.


Жаль. Как раз, один мой проект, кастомер просит перевести под Моно. Значит не судьба, ну это и к лучшему, перепишу на Питоне, так будет гораздо быстрее.

VD>Ну, и конечно под Линуксом единственное что можно получить — это редактор с подсветкой синтаксиса.


Моно, это не только Линукс, это "Линукс в том числе".
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org
Re[13]: Amplifying C
От: Mr.Cat  
Дата: 29.01.10 11:21
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Гы. Ты продемонстрировал, что данные и код в лиспе все таки тличаются.
Хз, я уже показал, как в plt управлять семантикой выражений. Что еще тебе нужно — я не знаю.

VD>Не. Это структур данных которая кодом не является по определению. В лиспе есть понятия "форм лиспа". И данный список не подпадает под него, так как начинается не символа.

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

VD>$[ x | x in seq, predicate (x) ] — list comprehension.

VD>Конструкция практически аналогичная хаскелевской, за тем исключением, что это макрос реализованный в стандартной библиотеке макросов:
VD>Не проблема создать скажем @[ ... ] синтаксис который будет вести себя как-то иначе.
VD>Кроме того в контексте другого макроса код может интерпретироваться вообще как угодно.
Ага, т.е. в немерле можно прямо посреди текста программы писать код на произвольном, определенном разработчиком языке, типа
basic(
  10 SIN
  20 GOTO HELL)

Соответственно, возникают вопросы:
1. Как в случае компрехеншена компилятор понимает, каким макросом его обрабатывать?
2. Как компилятор понимает, что внутри использования некоего макроса нужно переключиться на другую грамматику (а потом и переключиться обратно)? Он ведь в процессе разбора текста должен как-то понять, что basic — это использование макроса и переключиться на другую грамматику.

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

Это не спартанские условия. Просто некоторые тут страдают скобкофобией разной степени тяжести.
Re[9]: Amplifying C
От: Mr.Cat  
Дата: 29.01.10 11:57
Оценка:
Здравствуйте, A13x, Вы писали:
A>На современном оборудовании абсолютно никаких тормозов я не замечал (средненький ноутбук — DELL двухгодовой давности), чего не сказать про 2008 студию даже со всеми отключенными плагинами на значительно более мощной машине.
Это потому что оборудование современное и в целом за перфомансом в емаксе вроде следят. Одно время в 23-й ветке (когда она еще не была релизом) были заметные тормоза при скроллинге, особенно при уменьшенной частоте процессора (сейчас 800MHz обычно минимальная).

A>В общем, если вопрос об эффективности встал ребром, почему бы не написать критические части на С? Сомневаюсь, что на Nemerle (и на Lisp, наверное, тоже) кто-нибудь написал x.264 кодек для промышленного использования или драйвер уровня ядра.

Так об этом и ветка. Amplifying, блин, C. Потому что C — плохой, неудобный язык — и в рамках отдельно взятого проекта (мои впечатления от ядра линукса) рано или поздно превращается в страшнолисп с абьюзом #define, замыканиями (нестандартная фича gcc), связными списками и т.п. Вот и возникает у людей идея о лиспоси — как лисп, только си, ну или как си, только лисп. Как-то так.
Re[9]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.10 15:39
Оценка:
Здравствуйте, A13x, Вы писали:

A>Bопрос вкуса. Лично для меня более удобным является именно такой стиль написания. Да и необходимость в таких конструкциях не часто возникает. Однажды, когда мне нужно было написать довольно нетривиальный макрос, мне пришлось использовать форму с flet.


Это вопрос надежности программы, а не вкуса.

VD>>Собственно все эти приседания и делают Комон Лисп сложным для использования средним программистом.


A>На работе я пишу на С++. И я бы не назвал С++ значительно более простым языком, чем Common Lisp.


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

A>Вдобавок, есть еще и личные предпочтения.


Ну, вот они и имею место в твоем случае.
A>ну как минимум AllegroCL и CMUCL дотягивают.

A>Пример для Allegro из сети:

A>
A>CL-USER> (declaim  (optimize speed
A>                             (safety 0)
A>                             (space 0)
A>                             (debug 0)))
A>T
A>CL-USER> (defun my-func (x)
A>           (declare (fixnum x))
A>           (the fixnum (1+ x)))
A>MY-FUNC
A>CL-USER> (compile 'my-func)
A>MY-FUNC
A>NIL
A>NIL
A>CL-USER> (disassemble 'my-func)
A>;; disassembly of #<Function MY-FUNC>
A>;; formals:

A>;; code start: #x2083517c:
A>   0: 83 c0 04    addl    eax,$4
A>   3: f8          clc
A>   4: 8b 75 fc    movl    esi,[ebp-4]
A>   7: c3          ret
A>


О! Супер. Великое достижение человечества. Функция инкремента быал скомпилирована в 4 маш-инструкции. Для сравнения берем аналогичный код на Немерле:
module Program
{
  Inc(x : int) : int { x + 1 }
  
  Main() : void
  {
    WriteLine(Inc(5));
  }
}

Смотрим результат в функции Main:
0000000b  mov         ecx,6 
00000010  call        FFFFFFFFEF5EDD40

Надеюсь ясно почему код приходится смотреть в функции Main?

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

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

A>SBCL генерирует почти такой же код (проверял у себя на x86-64 linux):


A>Почему? Согласен, что списки используются не очень редко, но при необходимости нет никаких проблем использовать vector или hash-table.


Дык даже если использовать vector нужно же специально приседать чтобы получить монотипный массив, а не массив ссылок. А hash-table, как я понимаю, всегда ссылки использует.

A>Не вижу препятствий.


Препятствием являются библиотеки и традиции. Речь же идет о среднем приложении, а не о специализированном тесте. На тестах все будет близко к приличию. А в реальная программа до С будет не дотягивать очень сильно.

A>Кстати, а чем плохи списки?


Не экономным расходом памяти и неравномерным распределением по памяти. К тому же эффективный у них только добавление в начало списка. Добавление в середину или конец (не говоря уже о соединение списков) крайне не эффективны.

A>Как бы не 90% emacs написано на лисп (если сравнивать директории lisp и src в исходниках).


В емаксе на С написан сам код редактора (буферы и их изменение). Остальное уже не требует высокой производительности и эффективного хранения данных.

A>В общем, если вопрос об эффективности встал ребром, почему бы не написать критические части на С?


А зачем мне писать что-то на С? На том же немерле я получаю действительно близкую к С скорость, синтаксические макросы, понятный и удобный синтаксис и огромную библиотеку дотнета.
Зачем мне вместо этого использовать убогий в синтаксическом плане Лисп, да еще в паре с ужасно низкоуровневым С?

Сомневаюсь, что на Nemerle (и на Lisp, наверное, тоже) кто-нибудь написал x.264 кодек для промышленного использования или драйвер уровня ядра.

Драйвер ядра можно, но если сама ОС управляемая. Для винды и линукса конечно проблематично. А для ОС вроде Сингулярити вполне можно. Жаль что она пока не майнстрим.

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

A>Вот и получается, что Nemerle вроде бы и в чем то эффективней Lisp, но как это использовать — непонятно.


Тем кто не использует — конечно не понятно. А тем кто использует очень даже понятно. Мне нет нужды то и дело прибегать к помощи С. Все библиотеки я могу писать на там же языке, что и прикладной код.

A>И еще: известен ли вам проект, написанный на Lisp и переписанный на Nemerle, поработав с которым можно было бы сказать — "так, вот этот подонок тормозит, все срочно идем на Nemerle (Assembler, C, РЯП, нужное подчеркнуть)"?


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

А в истории примеры были. Тот же Яховский интернет-магазин который после Грэхэма был переписан то ли на плюсах, то ли еще на чем-то.

A>Есть ли математическое обоснование того, что Nemerle будет, например в 2-4 раза эффективнее для такого-то класса задач на таких-то машинах чем какая-либо популярная реализация Common Lisp (или что-то другое)?


Ага. Его система типов статическая. И есть не одна работа описывающая почему такие системы типов можно компилировать в эффективный машинный код.

В общем, Немерле это и есть качественный статически типизированный язык с сишным синтаксисом и макросистемой лиспа.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Amplifying C
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.10 17:24
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>Ну это примерно то же самое, что и в syntax-case: по умолчанию создаваемые макросом символы не перекрываются ни с какими именами, а используемые ссылки относятся к области видимости в месте объявления макроса. По необходимости это ломается, благодаря параметру у datum->syntax, указывающему, откуда для вводимого символа унаследовать "контекст".

MC>Вот классическая копипаста из r6rs (макрос создает внутри блока кода неявный биндинг):
MC>
MC>;(define-syntax loop
MC>;  (lambda (x)
MC>;    (syntax-case x ()
MC>;      [(k e ...)
MC>;       (with-syntax
MC>;          ([break (datum->syntax #’k ’break)]) ;Прошу прощения за вставленный форматтером коммент после стрелки, там его быть не должно
MC>;          #’(call-with-current-continuation
MC>;              (lambda (break)
MC>;                (let f () e ... (f)))))])))
MC>;


Ну, и тебе эта каша нравится?

MC>В данном случае, кстати, видно, что цитирование в немерле — это аналог не лиспового цитирования, а создания синтаксических объектов в схемском syntax-case: syntax-quote (ака #'), datum->syntax и т.п.


В немерле цитирование не из CL или Схемы, а "под влиянием". Там еще 2-3 системы рассматривалось. Схема одна из них. Из нее как раз взята идея гигиены. Кроме того много взять из Темлэйт Хаскель. Более подробно об этом можно прочесть в переводе статьи автора макросистемы — Камила Скальски:
http://rsdn.ru/article/nemerle/nemerleMacros.xml
Автор(ы): Kamil Skalski, Michal Moskal и Pawel Olszta
Дата: 23.05.2006
Пример C++ показывает, что индустрии нужны системы метапрограммирования – даже достаточно причудливая система шаблонов широко используется для вычислений во время компиляции. Эта статья является исследованием возможного внедрения техники метапрограммирования в индустриальную среду в более чистой форме. Мы, таким образом, фокусируемся на том, чтобы сделать нашу систему легкой в использовании для программистов, как пишущих, так и использующих макросы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.