LINUX.ORG.RU

Выход mocl

 , ,


7

8

mocl — набор инструментов для разработки на Common Lisp под мобильные платформы iOS и Android. По заверениям разработчиков получаемый код (используется LLVM) по производительности значительно превосходит аналогичный на Java/Dalvik.

В основе mocl лежит идея, заключающаяся в том, что логика приложения должна быть полностью описана на Лиспе, а пользовательский интерфейс — быть «родным» для платформы. Авторы проводят аналогию с Вэбом, когда логика серверного приложения описана на одном языке (например, на Лиспе), а представление — на другом (HTML + JavaScript).

Цена лицензии варьируется от $1299 для серьёзных компаний до $199 для индивидуальных разработчиков. Также предусмотрена «Source code license» для особых энтузиастов, доступ к которой, по-видимому, дают после обращения в службу поддержки.

Пример приложения на Github.

>>> Подробности

★★★★★

Проверено: mono ()
Последнее исправление: Dendy (всего исправлений: 4)

Ответ на: комментарий от ados
(macrolet ((matching (obj &body decls)
	     `(match ,obj
		,@(mapcar (lambda (decl)
			    (destructuring-bind (regexp
						 binds
						 &optional positions)
				decl
			      `((ppcre ,regexp
				       ,@binds)
				(list (list ,@(or positions
						  binds))))))
			  decls))))
  (matching a
	    (+day+ (m d))
	    (+date+ (d m y))
	    (+time+ (h m s))))

fix

ados ★★★★★
()
Ответ на: комментарий от ados

Если лень символы для описания биндингов придумывать можно вообще сделать так:

(macrolet ((matching (obj &body decls)
	     `(match ,obj
		,@(mapcar (lambda (decl)
			    (destructuring-bind (regexp
						 binds
						 &optional positions)
				decl
			      (multiple-value-bind (binds pos)
				  (if (listp binds)
				      (values binds
					      (or positions
						  binds))
				      (let ((s (loop :repeat binds
						     :collect (gensym))))
					(values s s)))
				`((ppcre ,regexp
					 ,@binds)
				  (list (list ,@pos))))))
			  decls))))
  (matching a
	    (+day+ 2)
	    (+date+ 3)
	    (+time+ (h m s))))

Конечно это будет выглядеть практичнее если описаний матчинга 100-500 а не 3 с половиной.

ЗЫ код не тестировал если что

ados ★★★★★
()
Ответ на: комментарий от wota

тоже мне большое колдунство:

regex_search( s, m, day  ) ? [](){ cout << "day"; } :
regex_search( s, m, date ) ? [](){ cout << "date"; } :
regex_search( s, m, time ) ? [](){ cout << "time"; } :
throw "error!!!";

Ого. В ход пошла «тяжёлая артиллерия» С++11. Но мы то знаем, что это не тяжёлая артиллерия, а так, пукалка детская. И вот почему:

  • В лямбдах C++ нужно явно замыкать идентификаторы внешнего скоупа, а для решения проблемы нужно замыкать `m'. В решении же на Lisp копипастить не надо - otima сама внесёт в скоуп описанные символы. А ещё можно круто сделать обосратушки замкнув `m' по ссылке и вернув лямбду ;)
  • даже если замкнуть `m', то нужно руками доставать сматченые фрагменты, тогда как optima.ppcre делает это сама - всё описывается декларативно.
  • каскад тернарных операторов возвращает лямбду, а не выполняет код в ней. Следовательно нужно определить объемлющую функцию, да и ещё подолбиться с описанием типа лямбды. Или же нафигачить круглых скобок — вызовов после определения какжой из лямбд.

И я уверен, что эти проблемы — вершина айсберга. Фактически ты привёл пример совершенно не работающего лисапеда. И даже в этом совершенно псевдокод-виде выглядит ужасно из-за «прекрасного» синтаксиса лямбд в C++. Я уже не говорю про то, что твой код ни разу не pm. Кривой, совершенно частный и не работающий случай для регекспов. Набросать тебе как в действительности будет выглядеть код на C++ опирающийся на твой псевдокод? Или сам догадаешься? Cовершенно безобидная копипаста "(list (list" покажется просто лалкой.

практически твой код, хотя я забыл - у тебя же фобия к данному оператору ;)

Нет никакой фобии. Ты совершенно ничего не понял. Как раз таки, в приведенном коде, каскад тернарных операторов возвращает лямбду. В этом случае всё ok.

BooBoo
()
Ответ на: комментарий от BooBoo

В решении же на Lisp копипастить не надо

да, мы это уже обсудили ;) и кстати больше, выше ados привел «красивый» пример использования макроса для избежания копипасты, которой «не надо», а теперь смотрим как с этим справится убогий (и я не спорю с этим) препроцессор:

#define MATCH( x, y ) regex_search( s, m, x  ) ? [&](){ y; } ():
MATCH( day, cout << "day" )
MATCH( date, cout << "date" )
MATCH( time, cout << "time" )
throw "error!!!";

Или же нафигачить круглых скобок

кот бы говорил ;)

И я уверен, что эти проблемы — вершина айсберга. Фактически ты привёл пример совершенно не работающего лисапеда.

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

Кривой, совершенно частный и не работающий случай для регекспов

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

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

Или же нафигачить круглых скобок

кот бы говорил ;)

ну да:

(lambda () ...)
куда непонятнее, чем:
[](){}
Тебе самому-то не смешно?

BooBoo
()
Ответ на: комментарий от wota

реальный код на С++ всегда проще и расширяемее твоего для конкретной задачи

Фантазии. Влажные. Ты ещё не написал ни одного готового решения для задачи с pm, тогда как на CL готовое рабочее решение.

и я повторюсь - я не убегаю от их решения,

Бежишь, как крыса с тонущего корабля. Уже в который раз приводишь не рабочие куски явного говнокода.

наоборот - именно практика показывает ненужность и вредность лиспа для этих задач

Ты Lisp не знаешь. Следовательно у тебя нет никакой практики. Один глухой butthurt. Такие дела.

BooBoo
()
Ответ на: комментарий от BooBoo

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

а) первая задача

http://www.spoj.com/ranks/HOMO/

мой вариант на сайте в >20 раз быстрее, на ЛОР - в три раза проще, вариант на лиспе медленнее во всех случаях, заодно длиннее и с копипастой

б) вторая задача

мой вариант короче, не требует изменений при добавлении данных, вариант на лиспе - копипаста и требует постоянных правок, попытка (частично) уйти от копипаста родила «это»:

Выход mocl (комментарий)

nuff said, на сим диалог объявляется закрытым, т.к. собеседнику надоело притворяться адекватным

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

Спасибо за очередную (и так предсказуемо закончившуюся демонстрацию) _commercial software developer_ vs. лиспо-невменяемый.

CSD: вот вам пример кода коллега, как видите он решает поставленную задачу, можете как-то прокомментировать?
Л-Н: ааа!! все сосут... говнокод... влажные фантазии... ты лиспа не знаешь... крысы с butthurt-ом бегут с корабля... я один на белом слоне!!
CSD: спасибо коллега, у вас как всегда очень убедительные аргументы.

anonymous
()
Ответ на: комментарий от anonymous

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

BooBoo
()
Ответ на: комментарий от wota

мой вариант короче, не требует изменений при добавлении данных, вариант на лиспе - копипаста и требует постоянных правок, попытка (частично) уйти от копипаста родила «это» ...

Ты внимательно прочитал замечания которые я тебе написал? Ты вообще читать умеешь? Там всё написано по делу и конкретно, почему твоё решение полная лажа.

BooBoo
()
Ответ на: комментарий от wota
#define MATCH( x, y ) regex_search( s, m, x  ) ? [&](){ y; } ():
MATCH( day, cout << "day" )
MATCH( date, cout << "date" )
MATCH( time, cout << "time" )
throw "error!!!";

Это залёт, сестра. Понимаешь ли ты что это просто кусок говна с фатальными проблемами. Тебе снова всё разжевать почему это так? За такое даже крестьянин с опытом отмудохал бы тебя не раздумывая. Я люблю крестодебилов за их упорство не невменяемость. Конкретно этот крестодебил даже кресты не осилил.

BooBoo
()
Ответ на: комментарий от wota

ах да, забыл, третья задача: http://www.spoj.com/problems/NPRIME/ лиспер просто слился

Ты это серьёзно? Это задача на столько дебильна. Даже HOMO куда круче, чем этот примитивизм. Это тупая решетка Эратосфена с анальным ограничением на сорец в 256 байт. Как раз задача для сишный байтодрочеров, где можно экономить на бесполезных спичках.

BooBoo
()
Ответ на: комментарий от BooBoo

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

anonymous
()
Ответ на: комментарий от BooBoo

Буба, ты бы хоть свою совесть поимел бы, а? Твоя аргументация создаёт негативный образ лиспу, который ты, по-видимому, всё-таки любишь. wota довольно корректно вёл переговоры, и оставить камня на камне от его MATCH приличному лисперу труда не составило бы, а ты вместе этого на говно изошёлся. Стыдись, а то по твоему поведению складывается впечатление, что ты ещё не видел свою семнадцатую весну.

Луговский, кстати, прежде чем унижать собеседника, убеждался, что его действительно следует унижать. Пока тот не показывал откровенной тупости, он общался агументированно и адекватно. Да и ругался он потом просто виртуозно...

anonymous
()

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

Я не зря предложил эту задачу. И если мы пройдем по ссылке, то увидим на первых местах руби, увидим в топе хаскель и питон, ЯП, которые ну никак не назовешь ЯП для «байтодрочеров», более того - в задаче вообще нет «байтодрочерства». Так почему же BooBoo так болезненно отреагировал и написал откровенную чушь? Все очень просто - у лиспа «нет синтаксиса», в результате приходится писать много кода (вспоминаем «if(stack++) ++homos;» vs «лапша на лиспе»). Именно потому в среде лисперов так популярны темы DSL и макросов - не из-за гибкости лиспа, а из-за желания писать меньше лапши, а точнее заметать ее под коврик, чтоб глаза не мозолила. И в данном топике, кстати, наглядно показали как это выглядит:

Выход mocl (комментарий)

wota ★★
()
Ответ на: комментарий от anonymous

и оставить камня на камне от его MATCH приличному лисперу труда не составило бы

я не предлагал MATCH как решение оригинальной задачи и понимаю всю убогость препроцессора (что сразу же написал), не использую его на практике (для таких целей), но мне таки интересно:

#include <iostream>
#include <string>
using namespace std;

int main( int argc, char* argv[] )
{
	if( argc < 2 ) exit(-1);

	#define MATCH( x, y ) string(#x) == argv[1] ? [&](){ y; } ():
	MATCH( day, cout << "Tuesday 5" )
	MATCH( date, cout << "01/01/2001" )
	MATCH( time, cout << "00:00" )
	throw "error!!!";
}

что в данном примере не так? надо чтоб оно работало или удовлетворяло каким-то требованиям, не связанным с именно работой кода?

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

Извини я немного не понимаю твой код, но он что-то делает кроме как выводит лямбду которая печатает константные выражения?

ados ★★★★★
()
Ответ на: комментарий от ados

нет, но лямбда ес-но может вернуть произвольный список - то что хотел BooBoo

wota ★★
()
Ответ на: комментарий от wota

Вообще-то, в примере с optima идея была в том, что переменные связываются с частями строки, удовлетворяющими регулярному выражению --- соответственно, минуты, часы, номера дней, месяцев, года, день недели --- после чего выполнялся _произвольный_ код, в примере --- данные собирались в список. В примере выполнялось одно и то же действие во всех трёх случаях, и этой симметрией задачи ты и воспользовался, расписав всё в виде двух циклов. Если бы этой симметрии не было, если бы задача стояла так, что тебе было бы действительно удобнее сначала связать значения с переменными, и лишь потом с ними работать, в C++ пришлось бы писать бойлерплейт типа

auto r = regex_search(s, m, date);
if (r) {
    int day   = r[0];
    int month = r[1];
    int year  = r[2];
    ...
}
В лиспе же это всё прячется в одно S-выражение, после чего код становится гораздо нагляднее. В этом и есть основное преимущество лиспа над другими языками: можно вводить сколь угодно сложные абстракции в виде максимально удобных для использования конструкций.

Сранивать приведённый мною код для HOMO с C++ некорректно, и я выше уже писал, почему, но добавлю ещё пару слов. Во-первых, я его совершенно не оптимизировал. Если важна скорость, как минимум там следует вписать (declare (optimize speed)) в начале функции. Можно также расставить ряд деклараций по коду, это должно его ускорить, но я не знаю ассемблер, а без этого тяжело понять, где находятся узкие места. Я не позиционирую лисп как быстрый язык, но я считаю, что он даёт хороший компромисс между скоростью разработки программы и скоростью её работы. Да и, во всяком случае, SBCL должен быть быстрее скриптовых языков и, я думаю, Java. Во-вторых, да, в малых объёмах кода лисп скорее всего будет многословнее, чем, скажем, C++. Потому что макросам в этом случае негде развернуться. Макросами скрывают повторяющиеся части кода, если повторяющегося кода нет, то и скрывать нечего, разве что для наглядности и читаемости. Поэтому на малых объёмах C++ будет выигрывать за счёт синтаксического сахара. А вот на больших всё будет гораздо интереснее.

Если кто-то хочет поспорить, хочу предупредить, что я вряд ли буду ввязываться. Я с интересом отслеживаю лиспосрачи, когда-то давно я в них почерпнул немало полезной информации, и сейчас время от времени вслывают новые идеи, но мне лениво кого-то переубеждать. Рекомендую просто взять лисп, прочесть книгу типа PCL и попробовать на каком-нибудь своём проекте, а потом уже выступать с аргументацией.

anonymous
()
Ответ на: комментарий от anonymous

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

потому я и требую конкретные задачи, а не попытку изобразить что-то бесполезное само по себе, т.к. во втором случае начинаются многочисленные «если бы» и претензии

в C++ пришлось бы писать бойлерплейт типа
В лиспе же это всё прячется в одно S-выражение, после чего код становится гораздо нагляднее.

template<class T, class U> inline
void bind_variables( T it, U& head ) {
    head = *it++;
}

template<class T, class U, class... Args> inline
void bind_variables( T it, U& head, Args... tail ) {
    head = *it;
    bind_variables( it++, tail... );
}

#define BIND( c, ... ) \
    decltype(c.begin())::value_type __VA_ARGS__; bind_variables( c.begin(), __VA_ARGS__ );

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

wota ★★
()
Последнее исправление: wota (всего исправлений: 4)
Ответ на: комментарий от anonymous

В этом и есть основное преимущество лиспа над другими языками:
можно вводить сколь угодно сложные абстракции в виде максимально удобных для использования конструкций.

Гомогенный AST - максимально удобная конструкция разве что для парсера. Достаточно посмотреть на LOOP макрос - примерно так выглядит большинство не игрушечных лисповых eDSL-ей - месиво из префиксных и постфиксных конструкций. Примеры из «Common Lisp the Language by Guy L. Steele»:

http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node248.html#SECTION00301000000...

А реализация этой далеко не самой сложной абстракции в SBCL (вероятно самая популярная реализация CommonLisp на сегодняшний день),

https://github.com/sbcl/sbcl/blob/master/src/code/loop.lisp

даёт очень хорошее представление об усилиях необходимых для разработки и отладки лисп еDSL-ей. Очень сомнительное преимущество над другими языками.

Рекомендую просто взять лисп, прочесть книгу типа PCL и попробовать на каком-нибудь своём проекте, а потом уже выступать с аргументацией.

На чем основано убеждение лисперов о незнании лиспа теми кто его не использует его в своих проектах? Большинство разработчиков знакомы и/или имеют опыт использования лиспа, но _сознательно_ делают выбор в пользу других языков именно потому, что недостатки лиспа перевешивают его достоинства. А PCL - это лисп туториал с игрушечными примерами и постоянными вставками о невероятном могуществе кодеров постигших нирвану лиспа, могут произвести впечатление и еще сильнее раздуть ЧСВ только у эмоционально неустойчивых личностей типа БуБу.

anonymous
()
Ответ на: комментарий от anonymous

Гомогенный AST - максимально удобная конструкция разве что для парсера. Достаточно посмотреть на LOOP макрос - примерно так выглядит большинство не игрушечных лисповых eDSL-ей

Нет. Loop не удачный пример eDSL на Lisp. Его целиком и полностью заменяет куда более адекватная вещь — iterate. И корявость loop'а никоем образом не опровергает удобство гомоиконности в МП. Это типичная подмена понятий: «коль уж loop коряв, то и sexprs и макросы неудобная штука».

А реализация этой далеко не самой сложной абстракции в SBCL (вероятно самая популярная реализация CommonLisp на сегодняшний день), https://github.com/sbcl/sbcl/blob/master/src/code/loop.lisp даёт очень хорошее представление об усилиях необходимых для разработки и отладки лисп еDSL-ей. Очень сомнительное преимущество над другими языками.

В действительности же loop не самая тривиальная вещь. Да и вообще МП не самое простое занятие. Lisp же делает МП настолько простым, насколько это вообще возможно на сегодняшний день. Более того ты судишь по сложности отладки только лишь на основании исходника, совершенно не учитывая, что при правильном подходе (используя хорошие IDE) отлаживать Lisp макросы если и не просто, то весьма эффективно.

Очень сомнительное преимущество над другими языками.

Над какми _другими_, сестрёнка? Нет таких языков, где бы МП хоть чуточку приблизился к Lisp'овому. Ближе всего подобрался Nemerle. Но и в случае с Nemerle пропасть огромна. Больше нет ничего.

Большинство разработчиков знакомы и/или имеют опыт использования лиспа, но _сознательно_ делают выбор в пользу других языков

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

что недостатки лиспа перевешивают его достоинства.

Перечисли недостатки. По пунктам и с объяснениеми.

А PCL - это лисп туториал с игрушечными примерами

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

эмоционально неустойчивых личностей типа БуБу

Для начала я прокрадусь к тебе в дом и убью твою собаку.

BooBoo
()
Ответ на: комментарий от wota

Все очень просто - у лиспа «нет синтаксиса»

Какая глупость.

в результате приходится писать много кода (вспоминаем «if(stack++) ++homos;» vs «лапша на лиспе»)

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

(when (> (incf stack) 1)
  (incf homos))
Сишный вариант короче за счёт того, что int неявно приводится к bool'у. Стоит ли говорить, что это не более чем частная, исторически сложившаяся вещь, ввиду отстутствия bool'а в ANSI C.

BooBoo
()
Ответ на: комментарий от BooBoo

(when (> (incf stack) 1)

лоропарсер съел часть выражения:

if(stack[i]++) ++homos;

да ты и сам должен был помнить, что имелось в виду

wota ★★
()
Ответ на: комментарий от anonymous

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

Да, чёрт возьми, анон. Ты прав. Сработал рефлекс — «в интернете кто-то не прав» :) Плохой день у меня вчера был.

Пока тот не показывал откровенной тупости

Согласен. Но тупость присутствует, хоть и не откровенная.

BooBoo
()
Ответ на: комментарий от wota

лоропарсер съел часть выражения:

if(stack[i]++) ++homos;

Да, точно.

(when (> (incf (gethash i stack 0)) 1)
  (incf homos))
(gethash <key> <ht> &optional <default>)
эквивалентен:
ht[<key>]
за тем лишь исключением, что gethash позволяет контроллировать дефолтное значение. Ну и представляет собой обычную lisp форму без какого либо сахара.

BooBoo
()
Ответ на: комментарий от wota

вам стоит подучить С++

Согласен. C++11 я щупал, но десятое правило Гринспуна на нём воплощать ещё не приходилось.

я так и не услышал ни одной реальной задачи, где вообще это было бы надо

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

зато наверняка услышу претензии по поводу данного решения

Разве что гомогенность контейнера. Если не лень, подумайте как сделать вот так:

(require #:iterate)
(require #:cl-ppcre)
(require #:cl-utilities)

(use-package #:iterate)
(use-package #:optima)
(import 'cl-utilities:once-only)

(defmacro coercing-bind ((&rest vars) container &body body)
  (once-only (container)
    `(let ,(iter
             (for var in vars)
             (for i from 0)
             (let ((item `(elt ,container ,i)))
               (collect
                 (match var
                   ((list name converter)
                    `(,name (funcall ,converter ,item)))
                   ((list* name () body)
                    `(,name (let ((,name ,item)) ,@body)))
                   (name
                    `(,name ,item))))))
       ,@body)))

(coercing-bind (a
                (b #'read-from-string)
                (c #'string-upcase)
                (d () (sin (read-from-string d))))
               (cl-ppcre:split " " "hello 42 world 3.14")
  ; a = "hello"
  ; b = 42
  ; c = "WORLD"
  ; d = 0.00159
  ...)
Идея в том, чтобы не только связать переменную с содержимым контейнера, но и преобразовать на лету --- так, чтобы преобразующий код лежал рядом с идентификатором. В C++ можно использовать перегруженные преобразования типов, хотя и не для всех случаев это разумно. Я сразу предвижу вопрос «зачем это нужно?» и отвечу: не знаю. Я просто подумал как можно было бы тривиально расширить ваш BIND, например, указав другие типы переменным. Но теперь, когда идея этого макроса пришла мне в голову, я его буду применять, если будут возникать подходящие ситуации. В отличие от некоторых с их BINDом.

anonymous
()
Ответ на: комментарий от BooBoo

Совершенно справедливы утверждения о том что MP в лиспе значительно чаще использует как средство борьбы с его вербозностью и ограниченностью или для частично работающей эмуляции удобных конструкций из других языков, чем для неких абстракций, но на деле получается кошмар типа LOOP. Именно по этой причине каждый лиспер пишет свою версию iterate, pattern matching, etc - разобраться, пофиксить и расширить написанное ранее другим лиспером без потери части нервных клеток невозможно.

Присутствие MP в языке не делает его _автоматически_ лучше и удобнее для разраборки (особенно коммерческой) по сравнению с остальными. Ровно также как и отсутствие неких возможностей (к примеру в спецификации CL нет ни TCO ни first class continuations) не делает его _автоматически_ хуже. Если посмотреть на историю развития языков в CS и на выводы тех кто в ней непосредственно участвовал (и продолжает активно участвовать), то можно проследить как эволюцию их взглядов так и прагматичное отношение к фичам - полное отсутствие фанатизма и признание некоторых, некогда считавшихся революционных возможностей неудобными для (особенно коммерческого) использования.

Один из достаточно свежих примеров - пост Олега Киселева о неудачной реализации continuations в Scheme.

Oleg: An argument against call/cc - http://okmij.org/ftp/continuations/against-callcc.html

Ключевая фраза в тексте:

...The primitive call/cc is a bad abstraction...
...Both the _users_ and the _implementors_ are *better served* with a set of _well-chosen control primitives_ of various degrees of generality with well thought-out interactions...

Как тут не вспомнить армию лиспо-воинов рассуждающих о ущербности других языков по причине отсутствия в них continuations-ов. Фактически повторяется ситуацию с MP - каждый может написать и пишет свой личный глючный try/catch, generator и walker.

От книги и не требуется этого. Нет ни одной технической книги по языкам с не игрушечными примерами.

Хорошый, не замусоренный детским фанатизмом туториал по лиспу ровно один - PAIP от Norvig-a. Остальные авторы страдают известным недугом Грема - последний пример LetOverLambda - все что ни лисп, есть унылый блаб для серых посредственностей, но взгляните на мою анафорическую макру.

-- На этом все, удаляюсь; Удачи тебе в твоих проектах, на чем бы они не были написаны...

anonymous
()
Ответ на: комментарий от anonymous

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

Нет. Эти утверждения совершенно не справедливы. Даже весьма старенькая стандартная библиотека CL гораздо лучше, чем стандартные библиотеки многих мейнстримных языков. Я уже не говорю о Clojure. В сущности же масимум, что могут дать языки со сложным синтаксисом — это сократить чуток символов при печати. При этом семантика конструкций относительно эквивалентных Lisp форм остаётся таже, а вот читаемость может только уходшиться. И примеры всем известны. Посмотреть хотя бы на Ruby (при всём уважении к языку). Фактически сахар вообще ничего не даёт, а сложный синтаксис отбирает возможность простого МП.

но на деле получается кошмар типа LOOP

Нет. И, в целом, ничего уж фатально кошмарного в loop нет. Просто плохой дизайн. Никакого отношения плохой дизайн loop'а к МП не имеет. Это просто вопрос, собственно, дизайна.

Именно по этой причине каждый лиспер пишет свою версию iterate, pattern matching, etc - разобраться, пофиксить и расширить написанное ранее другим лиспером без потери части нервных клеток невозможно.

Это не правда. Lisp к велосипедостроению относится точно также как и любой другой язык. На каком угодно языке ты можешь взять и начать писать велосипед, игнорируя существующие решения. Если же говорить о loop и PM, то давно уже есть устоявшиеся решения: iterate и optima соответственно. Если уж писать свой loop, то только в целях самообучения или с целью качественного определения новой функциональности.

BooBoo
()
Ответ на: комментарий от anonymous

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

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

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

template<class T, class U, class V> inline
void bind( T it, U& var, V func ) {
    var = func( *it++ );
}

template<class T, class U, class V, class... Args> inline
void bind( T it, U& var, V func, Args&&... tail ) {
    var = func( *it++ );
    bind( it, end, tail... );
}

template<class T, class U, class V, class... Args> inline
void bind( T& c, U& var, V f, Args&&... tail ) {
    bind( c.begin(), var, f, tail... );
}

int main() {
    int a;
    float b;
    bool c;
    std::list<int> l = { -1, 10, 'a' };

    bind(
        l,
        a, abs,
        b, []( int n ) { return cos( n ) * 10; },
        c, isdigit );
}

пожалуйста - и разные типы и инициализация, без макроса на самом деле даже лучше, не зря он мне глаза мозолил

предвижу вопрос «зачем это нужно?» и отвечу: не знаю.

я его предвидел ;)

я его буду применять, если будут возникать подходящие ситуации

чтоб не повторять 20 раз, обозначим - вы не знаете зачем оно надо, не видите задач под свой подход, но ратуете, что писать надо именно так, т.к. может быть когда-нибудь понадобится, окай, не буду спорить

В отличие от некоторых с их BINDом.

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

wota ★★
()
Ответ на: комментарий от anonymous

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

Ну да. Присутствие МП всего лишь даёт возможность определить любые нобходимые абстракции для задачи в независимости от того, что есть в базовой поставке. Фактически позволяет решать проблемы так, как это будет максимально удобно относительно задачи. И не надо тут рассказывать сказки о том, что в языке _любой язык_ есть всё что нужно, а то чего нет — не нужно. Мы не в детском саду.

Хорошый, не замусоренный детским фанатизмом туториал по лиспу ровно один - PAIP от Norvig-a. Остальные авторы страдают известным недугом Грема - последний пример LetOverLambda - все что ни лисп, есть унылый блаб для серых посредственностей, но взгляните на мою анафорическую макру.

От восхваления любимого инструмента страдает практически любая книга посвященная любому языку. Книги по Lisp этим не отличаются от другой литературы. Но почему то никто не возмущается этому факту. Если принципиально подойти к сути, то в нахваливании любимого инструмента нет ничего плохого — это заряжает читателя энтузиазмом, делает его открытым к восприятию информации. А также подобные восхваления никоем образом не умаляют ценности значащей информации в таких книгах, как PCL, On Lisp, Let Over Lambda. Взять например SICP — бесспорно полезнейшая вещь, но написана чуть ли не религиозным слогом. Если ты зоостряешь внимание только лишь на подобные восхваления и не видишь ценного, то это твои проблемы. Я вообще не знаю, как с этим можно жить. Это ж надо так — прочитал введение любой книги — выбросил.

BooBoo
()
Ответ на: комментарий от wota

я решил ее двумя циклами - проще некуда, мне говорят, что это фигня, надо макросы, надо усложнять, надо делать что-то еще, спрашивается - а что эти люди хотят?

Если ты следил за дискуссией, то тебе должно быть понятно, что хотелось увидить реализацию с использованием именно PM. Согласен, что условия для использования PM крайне не удачны, и, действительно, можно обойтись двумя отображениями. Всё же ты проигнорировал возможность присутствия None во входной последовательности, почему-то решив наглым образом подбросить вместо None пустую строчку. Я надеялся, что ты воспользуешься чем-нибудь вроде boost::variant. Также в условии было указано, что необходимо сигнализировать ошибку при невозможности сопоставления и ты тоже это проигнорировал, сославшись на то, что мы не рассматриваем обработку ошибок; хотя на самом деле, по условию, — рассматриваем. Также даже в реализации с отображениями, мне совершенно не понятно, почему ты решил использовать foreach, вместо transform. Ведь тут же явное отображение 1 в 1, нафиг тут foreach с push_back'ом, хз.

BooBoo
()
Ответ на: комментарий от wota

На самом же деле, поинт был в том, что в CL нет никакого PM'а. Но он был запрограммирован макросами, в результате получилась optima. Посмотри на возможности библиотеки и на то, какой простой в использовании получился eDSL. optima.ppcre — это маленькая, дополнительная функциональность, не более того. В С++ тоже не никакого PM, но запрограммировать такой же по простоте использования и возможностям PM как optima на C++ не представляется возможным. По крайней мере я не видел ни одной реализации.

Мораль тут не в том, что optima крута, а в том, что Lisp позволяет писать такие вещи, а C++ — нет. А если и позволяет, то кроваво и на выходе получается, как правило, какашка.

BooBoo
()
Ответ на: комментарий от anonymous

Поэтому на малых объёмах C++ будет выигрывать за счёт синтаксического сахара.

Вопрос сколько кода вбухали в реализацию всего этого сахара.

ados ★★★★★
()
Ответ на: комментарий от ados

Нет, это не имеет большого значения.

Значение имеет расширяемость языка для более удобной работы в рамках определеной problem domain.

x4DA ★★★★★
()
Ответ на: комментарий от x4DA

Значение имеет расширяемость языка для более удобной работы в рамках определеной problem domain.

А можно ли логически доказать какой язык в этом плане лучше? Просто в программной лингвистике я ноль, но чувствую что лисп порвёт всех.

ados ★★★★★
()
Ответ на: комментарий от ados

А можно ли логически доказать какой язык в этом плане лучше? Просто в программной лингвистике я ноль, но чувствую что лисп порвёт всех.

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

mv ★★★★★
()
Ответ на: комментарий от ados

Лучше те, в которых более развиты средства для повышения уровня абстрагирования. Некоторые считают, что единственным таким средством является макросистема

x4DA ★★★★★
()
Ответ на: комментарий от ados

А можно ли логически доказать какой язык в этом плане лучше? Просто в программной лингвистике я ноль, но чувствую что лисп порвёт всех.

Лучше для расширяемости? Если под ней подразумевается введение нового синтаксиса - то лучше тот язык, в котором изначально мало синтаксиса.

alienclaster ★★★
()
Ответ на: комментарий от mv

В случае больших DSL движок языка вырождается в классический компилятор.

В случае «больших DSL» нужна как и всегда для построения абстракций - система с хорошей модульностью. CL в данном случае херовый ориентир.

alienclaster ★★★
()
Ответ на: комментарий от ados

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

Было бы с чем сравнивать. Ведь нету ничего. Template Haskell? Скаламакросы? Ох уж. Даже не смешно.

BooBoo
()
Ответ на: комментарий от alienclaster

Лучше для расширяемости? Если под ней подразумевается введение нового синтаксиса

Скорее подразумевается определение _новой_ семантики к sexpr'ам. Это самое главное. А определение какого-нибудь причудливого синтаксиса к этой _новой_ семантике — дело десятое. И обычно до этого даже не доходит, если всех устраивают sexpr'ы.

BooBoo
()
Ответ на: комментарий от mv

Для eDSL общелисп почти идеален.

Я тоже так считаю.

В случае больших DSL движок языка вырождается в классический компилятор.

Тут я не очень понял. Что значит «классический компилятор»?

BooBoo
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.