LINUX.ORG.RU

Вышла Scala 2.10

 


1

3

Объявлено о выходе новой версии языка программирования Scala 2.10.

Основные нововведения:

  • классы-значения (value classes) — новый механизм, позволяющий уменьшить расходы на выделение памяти;
  • неявные модификаторы (implicit classes) теперь относятся к определению классов и призваны упростить расширения для других типов;
  • интерполяция строк (string interpolation) — новый механизм создания строк;
  • Futures и Promises призваны упростить создание многопоточного кода;
  • библиотека Akka Actors теперь является частью языка;
  • наконец-то в состав языка добавлена поддержка макросов.

Текущая стабильная версия языка программирования Scala может быть получена на странице загрузки проекта; исходные коды распространяются на условиях лицензии BSD.

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

★★★★★

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

Ответ на: комментарий от Ritmik

Например, если говорить про макросы Clojure - в чём преимущество sql-as-s-expression против сырых строк с SQL или функций генерирующих SQL код в рантйме?


В том, что sql-dsl позволяет использовать запросы в других выражениях (т.е. сразу что-то делать с результатом).

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

Как такой код тестировать? Все слои слеплены, так какой тут 'divide and conquer', 'separation of concerns'?

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

Вы же говорили о экономических основаниях?

Экономические обоснования обычно сводятся к мировозрению ключевых лиц. Потому что исходные данные вполне могут оказаться маркетинговым булшитом. Есть немало компаний, где юзают маргинальщину. И что-то не слышно особых криков. А вообще дырявое все, даже java. Пониятие «проверенная технология» - зыбкое. Все равно ты будешь использовать технологию в немного других кейсах, чем технологию проверяли. У меня на памяти несколько случаев, когда патчили hotspot своими силами. И драйверы доступа к БД патчили (казалось бы, что может быть провереннее? ан нет), и питон тоже патчили.

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

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

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

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

Верно, но есть вещи которые уже тысячи раз проверили. А остальные не проверили, и не означает что они хуже

А вообще дырявое все, даже java

О, java отлично дырява. Но все работает. В отличии от таких платформ, на которых некоторые вещи даже не заведутся, или проработают три дня

Пониятие «проверенная технология» - зыбкое

Правильно. Есть более, а есть менее. А есть почти совсем не проверенная. Код, который я с утра написал, вообще не проверен пока

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

нет, мок один. на входе будет запрос SQL, на выходе список. но тестировать скорее всего придется НТМL, ну или сразу с сокета читать...

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

£71k - это где о таком можно прочитать?

К примеру: http://www.theitjobboard.co.uk/IT-Job/Lead-Principle-Java-Developer-Java-Agil...

Сравнивал цены в Tesco который как я понял - недорогая сеть

Да, Tesco дешев. Насчет изменения цен летом / зимой фигня какая-то, они стабильны. Хз, по мне еда копейки, особенно сравнивая с Украиной (это без учета того, что рынок еще дешевле, чем супермаркет)

Смотрите в Торонто или Монреале.

В Торонто нет интересующей меня работы вообще, в Монреале практически нет (VFX). Ванкувер сейчас рулит. Ну пока что разницы в цене особой нет. Никакого «приехал в Канаду, получил в 2 раза прирост доходов» нет. Хорошо если прирост 1.2 раза Это как с Сингапуром. Там налог около 15%, можно получать лондонскую зарплату, получается вроде бы неплохо. Но аренда и прочее приводят к тому, что денег остается 1 к 1, только в Сингапуре жара и работы почти нет :)

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

Lead Principle Java Developer

Это синоним слова Архитект или мэнеджер в зависимости от повёрнутости HR в придумывании названия.

Платят естественно больше.

grim ★★☆☆
()

Хех, весёлая ветка, ничего не смысля в программировании, читая сообщения анонимных java-активистов понимаю почему мне приходится постоянно обновлять свой компьютерный парк (оказывается в ворде можно в гоночки погонять, зачем, кто-то предвидел такую потребность у клиента?). В тоже время, читая апологетов lisp`а, понимаю, почему некоторые люди считают, что простые вещи в их интерпретации на голову лучше всех прочих (а потому и дороже)- только потому, что они не ширпотреб.

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

Это синоним слова Архитект или мэнеджер в зависимости от повёрнутости HR в придумывании названия.

Да, пример не очень удачный, но в целом гугл дает зарплаты до уровня 65К даже не для синиоров. Я Знаю народ, кто получает 90К + 35K бонусов без напрягов (это в фунтах, написание андроидных приложений).

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

Читая анонимного апологета самого себя, понимаю, что он дрочер.

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

А в зеркало глянуть слабо?

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

Пока что хамовитость прилагается к vertexua.

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

В чем отличие от первого-второго вариантов?

ок, пойдём от обратного - в чём сходство, на твой взгляд

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

Знаешь значение слова «венчурный»?

ага, от venture - рискованное предприятие, этот факт как то должен был повлиять на моё мировоззрение?

Это означает, что добрый дядя в любой момент может отозвать своё бабло.

добрый дядя умеет «просратые» деньги назад саммонить? крутой дядя, я таких не знаю

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

В чем отличие от первого-второго вариантов?

ок, пойдём от обратного - в чём сходство, на твой взгляд

Так не пойдет :) Кто сказал, что альтернатив «гораздо больше», но не привел ни одной? Ему и доказывать, что предложенный вариант - альтернатива. А не разновидность. Следующий вопрос будет о «гораздо больше» :)

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

Кто сказал, что альтернатив «гораздо больше», но не привел ни одной? Ему и доказывать, что предложенный вариант - альтернатива.

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

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

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

Всего два момента: 1) это не альтернатива, но разновидность 1-го или 2-го варианта 2) гораздо больше - ты так и не продемонстрировал.

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

1) это не альтернатива, но разновидность 1-го или 2-го варианта

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

2) гораздо больше - ты так и не продемонстрировал.

давай сначала с (1) разберёмся

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

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

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

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

Просто Play! действительно плохой фреймворк. Не просто с недостатками, а в целом не годный

в двух словах: что с ним не так?

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

Плагины не в виде jar файлов с какого-то Nexus/Central, а костыли в виде zip файлов вроде даже с их сервера, дорисовывание методов посткомпиляцией, статики. УГ документация. Как следствие того что описано выше - зависимость на «поддержку IDE». Если нет , то считай у тебя не IDE, а текстовый редактор. Это уже пошло, любой вменяемый фреймворк работает без поддержки IDE, максимум надо чтобы свои форматы разукрашивало и поддержка Maven.

Play - пример того, как не надо делать

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

Именно аналог.

А аналог и нужен. То есть невозможность воспроизвести with* и foreach _в точности_ как в clojure не существенна, так как они воспроизводятся _с точностью до_ незначительных отличий.

В clojure они работают за счёт примитивных конструкций языка и макросов (compile-time/stage функций над кодом как данными и прочими данными). В других языках они будут работать за счёт примитивных конструкций языка и (runtime над обычными данными) функций (конструкторов, etc).

Например, при переписывании кода с такого рода простыми макросами ты не упрёшься в какие-то принципиальные ограничения. А вот если взять какой-нибудь навороченный макрос define-some-configuration на CL который генерирует класс и методы CLOS и потом ещё набор макросов которые будут генерировать другие методы этому классу и всё это будет загружаться по load в образ во время выполнения - вот тут уже наличие и свойства макросистемы окажутся существенны - на CL это просто и естественно, на «более других» языках могут быть варианты.

with-* дает новую абстракцию, а как там внутри уже не должно волновать пользователя конструкции.

С RAII классами точно так же - они дают абстракцию и скрывают детали получения и освобождения ресурсов.

Ты с этим не согласен, насколько я понял и в лиспе не используешь with-open*/with-*?

Почему? Согласен. В лиспе ты пишешь with* и foreach, где-то ещё ты пишешь RAII/try-finally и, хм, for_each/foreach. В чём разница?

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

Эм, потому что макросы есть - потому и используют :) То есть через макросы.

А вообще, ты в курсе, к чему был пример с foreach?

К тому что это compile-time функция с типом [A, Seq <: Traversable[A]](name: Name[A] /* хотя Scala не умеет в зависимые типы */, Exp[Seq], Exp[Unit] /* и тут нужно как-то указать анафоричность по name */), ну или как-то так. Естественно, «с помощью фвп не сделать», но при этом лаг между макросом foreach и тем что можно написать функцией/методом map/foreach так мал, что их даже неохота различать.

В контексте какого разговора?

Такого - «функции стадии компиляции над кодом и данными и функции стадии выполнения над простыми данными - разные вещи, так что вторые нельзя использовать для того что умеют первые (и наоборот)». И что? Зачем нам эти функции над кодом стадии компиляции? Явно же не для foreach - так мы приходим к вопросу о нужности и выразительности макросов.

Синтаксис запроса, актуальность наименований полей и таблиц проверятся на этапе компиляции.

То есть во время раскрытия макроса? В макросе with-db реализована какая-то проверка SQL и она общается с другими частями использующими with-db с помощью каких-то глобальных контекстов?

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

Я привел две категории, ты заявил альтернативу - ты и скажи, по каким признакам альтернатива альтернативная.

ты привёл следующие варианты, цитирую:

те кто в основном «носятся с баблом и не знают куда вложить» на самом деле либо (1) носятся с копейками, до 200К (обычно последними или с проданных хат), либо (2) ищет высокорисковые проекты с потенциально огромной прибылью (венчурное инвестирование),альтернативы

теперь вариант, который привёл я:

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

очевидно, что (1) отбрасываем сразу ибо суммы не те, вариант (2) тоже не совсем то, ибо человек зарабатывает на другом, а это для него, если хотите, расширение бизнеса, проба новых областей (но мягкая, не агрессивная, как в случае венчурных крокодилов)

чувствуешь разницу?

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

А аналог и нужен. То есть невозможность воспроизвести with* и foreach _в точности_ как в clojure не существенна, так как они воспроизводятся _с точностью до_ незначительных отличий.

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

В clojure они работают за счёт примитивных конструкций языка и макросов (compile-time/stage функций над кодом как данными и прочими данными). В других языках они будут работать за счёт примитивных конструкций языка и (runtime над обычными данными) функций (конструкторов, etc).

В clojure макросы разворачиваются по тому же лисповому механизму, что и cl или схеме.

Например, при переписывании кода с такого рода простыми макросами ты не упрёшься в какие-то принципиальные ограничения. А вот если взять какой-нибудь навороченный макрос define-some-configuration на CL который генерирует класс и методы CLOS и потом ещё набор макросов которые будут генерировать другие методы этому классу и всё это будет загружаться по load в образ во время выполнения - вот тут уже наличие и свойства макросистемы окажутся существенны - на CL это просто и естественно, на «более других» языках могут быть варианты.

Про это речь и идет.

С RAII классами точно так же - они дают абстракцию и скрывают детали получения и освобождения ресурсов.

Теплое и мягкое. RAII выполняет лишь часть работы (для чего собственно оно и придумано), связанную с автоматическим освобождение ресурсов. В то время как with-open помимо генерации кода, ответственным за освобождением, создает абстракцию, которая на этапе компиляции разворачивается в базовые конструкции языка. Вообще некорректно эти два механизма сравнивать словами «точно также» - они ортогональны.

А вообще, ты в курсе, к чему был пример с foreach?

К тому что это compile-time функция с типом [A, Seq <: Traversable[A]](name: Name[A] /* хотя Scala не умеет в зависимые типы */, Exp[Seq], Exp[Unit] /* и тут нужно как-то указать анафоричность по name */), ну или как-то так.

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

Естественно, «с помощью фвп не сделать», но при этом лаг между макросом foreach и тем что можно написать функцией/методом map/foreach так мал, что их даже неохота различать.

Вот тебе тест. Если «лаг» так мал, то не используй «мелкие макры» типа with-*, dolist и пр. - всех, кто каким либо образом использует связывание переменных и использование их в своем теле. Потом сам посмеешься про «лаг».

Почему? Согласен. В лиспе ты пишешь with* и foreach, где-то ещё ты пишешь RAII/try-finally и, хм, for_each/foreach. В чём разница?

В том, что в лиспе ты можешь сам увеличивать набор таких конструкций, а в языке без макров с только RAII/try-finally ты будешь писать аналогичный громозкий код с try-finally и прочими базовыми конструкциями, завернутыми, если надо, в функции, в то время как в лиспе этот код генерировался автоматически макросом с более высокой абстракцией.

В контексте какого разговора?

Такого - «функции стадии компиляции над кодом и данными и функции стадии выполнения над простыми данными - разные вещи, так что вторые нельзя использовать для того что умеют первые (и наоборот)». И что? Зачем нам эти функции над кодом стадии компиляции? Явно же не для foreach - так мы приходим к вопросу о нужности и выразительности макросов.

Использовать макросы без разницы для для чего, для foreach или для другой конструкции. Есть тип задач (http://dunsmor.com/lisp/onlisp/onlisp_12.html#SEC64) когда макросы нужны. А маленькие это задачи или большие - побоку.

Синтаксис запроса, актуальность наименований полей и таблиц проверятся на этапе компиляции.

То есть во время раскрытия макроса? В макросе with-db реализована какая-то проверка SQL и она общается с другими частями использующими with-db с помощью каких-то глобальных контекстов?

Не в макросе with-db. Ты все перепутал. Выражение типа select использует в качестве параметров имен таблиц и полей переменные с именами, связанными с именами этих таблиц и полей. Вот эти имена генерируются соответствующим макросом во время компиляции, благодаря чему при компиляции самого запроса уже созданы и скомпилированы соответствующие переменные с именами. Что ведет к тому, если в бд поменялись наименования, то создадутся переменные с другим наименованием и код с запросом не скомпилится.

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

Ок.

Я так и не понял чем foreach лучше map и чем макросы вокруг foreach лучше обычных функциональных композиций вокруг map. А «анафорические протоколы» когда забинденный анафорой символ попадает в тело откуда-то извне это есть плохо и моветон (такое ИМХО).

Хотя вот дальше:

В том, что в лиспе ты можешь сам увеличивать набор таких конструкций, а в языке без макров с только RAII/try-finally ты будешь писать аналогичный громозкий код с try-finally и прочими базовыми конструкциями, завернутыми, если надо, в функции, в то время как в лиспе этот код генерировался автоматически макросом с более высокой абстракцией.

Про «громоздкий», фатальность «код не генерировался, а функция RT» и «более высокой абстракцией» можно поспорить, но вообще понятно.

В clojure макросы разворачиваются по тому же лисповому механизму, что и cl или схеме.

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

RAII выполняет лишь часть работы

«RAII класс» обычно имеет как минимум набор конструкторов и деструктор, так что он выполняет именно всю работу - по скрытию инициализации в конструкторах (им передаются разные декларативные параметры, enumы и т.п.), освобождению в деструкторе, ну и гарантирует это освобождение. Телом будет весь блок типа

    {
        fileRAII::withOpenFile file(path, fileRAII:append, fileRAII::create, ...);
        file << ...;
        ...
    }

Вообще некорректно эти два механизма сравнивать словами «точно также» - они ортогональны.

Они ортогональны, но один может обесценить другой в случае конкретных with* макросов. Пример с Using я привёл - выглядит и выполняет роль точно такую же что и макрос типа with-lock, но суть - обычный RAII класс. И withOpenFile выше - так же.

Не так.

Контрпример оно именно потому что макрос это вот такая вот хрень, если начать его анализировать, то есть функция над синтаксисом отрабатывающая во время компиляции, после этого отождествление с обычными функциями времени выполнения уже будет выглядеть неправильным. При этом с точки зрения решения задач макро-преобразования вполне вносятся обратно в рантайм как обычные функции над данными, так что компилируемые и интерпретируемые eDSLи можно отождествлять modulo «эта [под]задача решена».

не используй «мелкие макры» типа with-*, dolist

Так как я на CL уже довольно давно ничего не пишу - я их и не использую. Каких-то особых неудобств не испытываю (C++, Haskell, Scala). «Большие макры» при этом есть - разные формы deriving в хаскеле, DSL велосипеды в C++.

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

Ок.

Я так и не понял чем foreach лучше map и чем макросы вокруг foreach лучше обычных функциональных композиций вокруг map. А «анафорические протоколы» когда забинденный анафорой символ попадает в тело откуда-то извне это есть плохо и моветон (такое ИМХО).

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

В том, что в лиспе ты можешь сам увеличивать набор таких конструкций, а в языке без макров с только RAII/try-finally ты будешь писать аналогичный громозкий код с try-finally и прочими базовыми конструкциями, завернутыми, если надо, в функции, в то время как в лиспе этот код генерировался автоматически макросом с более высокой абстракцией.

Про «громоздкий», фатальность «код не генерировался, а функция RT» и «более высокой абстракцией» можно поспорить, но вообще понятно.

Если есть возможность затачивать язык под задачу, получая при этом синтаксис в котором задача решается кратко, наглядно и в терминах задачи, чтобы за тебя яп сам развернул выражения, а не ты их вручную писал (пресловутые «аналогии»), то это хорошо. Если ЯП такого не позволяет, то плохо.

В clojure макросы разворачиваются по тому же лисповому механизму, что и cl или схеме.

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

То-то и оно - тривиально. А какой код сгенерируется оптимальный, заинлайненный по самое нихочу, императивный или функциональный и пр. - это совсем другая задача. Но самое главное, что пользователь макры видит лаконичную заточенную на конкретную абстракцию конструкцию, и не видит «грязный» код и его количество. Это хорошо. Или ты этого не понимаешь или уперся из принципа.

RAII выполняет лишь часть работы

«RAII класс» обычно имеет как минимум набор конструкторов и деструктор, так что он выполняет именно всю работу - по скрытию инициализации в конструкторах (им передаются разные декларативные параметры, enumы и т.п.), освобождению в деструкторе, ну и гарантирует это освобождение. Телом будет весь блок типа

Вообще некорректно эти два механизма сравнивать словами «точно также» - они ортогональны.

Они ортогональны, но один может обесценить другой в случае конкретных with* макросов. Пример с Using я привёл - выглядит и выполняет роль точно такую же что и макрос типа with-lock, но суть - обычный RAII класс. И withOpenFile выше - так же.

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

Не так.

Контрпример оно именно потому что макрос это вот такая вот хрень, если начать его анализировать, то есть функция над синтаксисом отрабатывающая во время компиляции, после этого отождествление с обычными функциями времени выполнения уже будет выглядеть неправильным. При этом с точки зрения решения задач макро-преобразования вполне вносятся обратно в рантайм как обычные функции над данными, так что компилируемые и интерпретируемые eDSLи можно отождествлять modulo «эта [под]задача решена».

Судя по твоим рассуждениям, складывается такое ощущение, что ты прочитал про макры на вики и теперь теоретизируешь. Ты много макр реализовал в своих проектах на лиспе? А то что-то не то.

не используй «мелкие макры» типа with-*, dolist

Так как я на CL уже довольно давно ничего не пишу - я их и не использую.

Заметно.

Каких-то особых неудобств не испытываю (C++, Haskell, Scala).

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

«Большие макры» при этом есть - разные формы deriving в хаскеле,

Не то.

DSL велосипеды в C++.

Спасибо, насмешил. Скинь ка пример небольшого вилосипеда DSL на C++. Если не стыдно.

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

такие выражения и используется повсеместно.

«забинденный анафорой символ попадает в тело откуда-то извне»? Это вот так:

(foreach [x seq]
  (some-macro тут "x" нет)
  ;; раскрывается в код с "x"
  )

или так

#define MACRO1(...) \
    ... define magic__ variable ...

#define MACRO2(...) \
    ... using magic__ variable ...

... fun(...)
{
    MACRO1(...)
    MACRO2(...)
}

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

то это хорошо

То это ЛNСП :)

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

Это тоже хорошо, но ты преувеличиваешь значение макросов, классы-методы или ADT-функции тоже позволяют скрыть `«грязный» код` оставив лаконичное API заточенное на нечто конкретное с нужным уровнем абстракции. Первый попавшийся пример в котором этот подход вполне по DSLю - http://sebfisch.github.com/haskell-regexp/regexp-play.pdf.

Ты опять мимо

Я же написал: «может обесценить другой в случае конкретных with* макросов», а ты зачем-то рассказываешь про «вообще».

Ты много макр реализовал в своих проектах на лиспе?

Десяток-другой - как синтаксическая абстракция и аспектная ориентация было очень удобно. Но это как спрашивать сколько колбеков one насоздавал на Node.js, принято там так писать. Обычно всё сводится к 1) тривиальным синтаксическим абстракциям вроде with*, кастомных условий, циклов и т.п.; 2) к трансляциям dsl-s-expr -> code-doing-stuff которые заменяются функциями dslADT -> just-do-stuff (статья выше); 3) к формам кодогенерации top-level определений - никогда не было проблемой.

Итого, ещё раз, для сложных применений 2) и 3) макросы не витальны (за исключением случаев обеспечения type safety или производительности), только для синтаксических абстракций 1) они - нечто основополагающее.

Не то.

Почему Template Haskell - не то?

пример небольшого вилосипеда DSL на C++.

Это любой транслятор DSL -> C++.

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

3) к формам кодогенерации top-level определений - никогда не было проблемой.

Так все интересные макросы как раз вводят новые определения (top-level или локальные - тут не важно). И это ни через рефлексию ни через ADT не сделать.

Почему Template Haskell - не то?

Как в TH сделать макрос, раскрывающийся в определение другого макроса? А это основополагающий прием (см. выше про генерацию определений).

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

top-level или локальные - тут не важно

Это важно, например foo-using-bar-dsl.cc, bar-using-foo-cc.dsl - если *.dsl транслируется в *.cc, то есть в top-level формы, то мы тут легко получаем интерпортабельность просто на уровне символов линковки, вся сложность только в парсере, чекере (если нужен) и принтере. Поэтому кодогенерация top-level форм «никогда не была проблемой» - cpp, m4, свои велосипеды-трансляторы.

И это ни через рефлексию ни через ADT не сделать

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

Как в TH сделать макрос, раскрывающийся в определение другого макроса?

А в чём проблема? Пишется как обычно в Q Dec.

Но я «формы deriving в хаскеле» привёл как примеры полезной кодогенерации которые там видел - Derive* расширения, derive пакеты. Ещё можно вспомнить разные DSL для routes, css, js, html в yesod (тут уже и top-level c TH/QQ для Dec, и просто QQ для Exp).

Вот, кстати, в Scala/Play! тоже в своё время перешли к таким type-safe DSLям для маршрутов и темплейтов, но там оно ещё без макросов, а * -> *.scala и с вырвиглазными парсерами, чекерами и принтерами :)

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

Это важно, например foo-using-bar-dsl.cc, bar-using-foo-cc.dsl - если *.dsl транслируется в *.cc, то есть в top-level формы, то мы тут легко получаем интерпортабельность просто на уровне символов линковки, вся сложность только в парсере, чекере (если нужен) и принтере. Поэтому кодогенерация top-level форм «никогда не была проблемой» - cpp, m4, свои велосипеды-трансляторы.

А, вот ты про что. Я думал подразумевалась генерация дефайнов. Ну велосипеды трансляторы, естественно, ни в какой ипостаси не могут заменить макросы (особенно в качестве как ты называешь «генерации топ-левел форм») т.к. не имеют доступа к рантайму. Тут даже сравнивать смешно.

А в чём проблема? Пишется как обычно в Q Dec.

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

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

т.к. не имеют доступа к рантайму

Эм, к какому? :) DSL может спокойно использовать функции и переменные из *.cc, потому что всё равно всё в итоге транслируется туда же. А другого рантайма (который может существовать во время очередной стадии компиляции в лиспе, например) в C++ и нет. Non-staged - тупо сгенерировал, собрал, запустил, [хотя - сгенерировал, собрал, подгрузил].

И как же будут квазицитаты внутри других квазицитат?

На TH можно без квазицитат писать в монаде Q.

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

Эм, к какому? :)

Ну например сгенерировать макросом некую ф-ю а потом ее использовать при генерации кода в другом макросе.

На TH можно без квазицитат писать в монаде Q.

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

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

Ну например сгенерировать макросом некую ф-ю а потом ее использовать при генерации кода в другом макросе.

Например, транслятор генерирует по описанию типа класс и методы для сериализации/десериализации в/из бинарного представления. Зачем полученный функционал другому транслятору? То есть macro -> function -> for macro это может быть средство, но не самоцель, в остальном надо плясать от задачи.

Ну понятно - то есть теоретически можно, а практически - нельзя

Ну если посмотреть на любой реальный пример использования, то там как раз больше ручное составление AST в Q, а цитирования - меньше, просто как сахар (например - http://github.com/yesodweb/yesod/tree/master/yesod-routes/Yesod/Routes/TH).

Но я все равно посмотрел бы как макрос генерит определение другого макроса, который, допустим, определяет какой-нибудь тип и функцию.

Вместо

genMacro :: ... -> Q [Dec]
genMacro ... = [d|

  -- macro
  $... :: ... -> Q [Dec]
  $... ... = [d|

    -- top-levels
      $...

    |]

  |]

пишется

genMacro :: ... -> Q [Dec]
genMacro ... = [d|

  macro :: ... -> Q [Dec]
  macro ... = do

    let genFunBody ... = do
      $...
      return exp ...
    ...
    funBody <- genBody ...

    etc...

    return [ FunD funName [Clause [...] (NormalB funBody) []]
           , etc...
           ]

  |]

или

genMacro :: ... -> Q [Dec]
genMacro ... = do

  let genFun ... = [|
        do
          let genBody x = do
                $...
                return exp ...
          ...
          body <- genBody ...
          return [FunD funName [Clause [...] (NormalB body) []]]
        |]
  ...
  fun <- genFun ...

  etc...

  return [ FunD macroName [Clause [...] (NormalB fun) []]
         , etc
         ]

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

genMacro 'foo ...

и в третьем он генерирует что-то

foo ...

-- use it here

Только макрос генерирующий макрос генерирующий top-levels это слишком крутой наворот - зачем?

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

Ну если посмотреть на любой реальный пример использования, то там как раз больше ручное составление AST в Q, а цитирования - меньше, просто как сахар (например - http://github.com/yesodweb/yesod/tree/master/yesod-routes/Yesod/Routes/TH).

Причина в изначальном убожестве TH. Он сломан фундаментально, а потому практически неюзабелен. Естественно, никакие квазицитаты в этом случае не спасут.

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

В каком таком другом модуле? Нам ведь здесь же надо, возможно в текущем локальном контексте (то есть внутри where/let/определения функции).

То есть macro -> function -> for macro это может быть средство, но не самоцель, в остальном надо плясать от задачи.

Так как раз за счет наличия средств проблемы из теоретически решаемых становятся практически решаемыми. Вот в TH нихрена нету средств - он и не нужен никому.

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

Только макрос генерирующий макрос генерирующий top-levels это слишком крутой наворот - зачем?

Гм. Ну это стандартный паттерн, он применяется практически в любом макросе длиннее пары строк.

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

В каком таком другом модуле?

«GHC stage restriction» же - оно не умеет использовать макросы определённые в том же модуле.

quasimoto ★★★★
()

Жизненный цикл любой новости о ЯП на ЛОРе.

  • Публикуется новость о языке программирования;
  • (1 стр.) Набегают анонимусы, охотники за шкворцом, неосиляторы и просто мимокрокодилы с криками «нинужно», «а зачем X, когда есть Y», «чем это лучше Z» и т.п.;
  • (2-4 стр.) Просыпаются компетентные в теме ЛОРовцы и обсуждают тему;­
  • (5-10 стр.) Набегают ёбн­­у­тые лиспофанбои и скатывают тему в лиспосрач;
  • (10-15 стр.) Лиспофаги озалуплены, общими усилиями адекватных регистрантов и анонимусов;
  • (15- стр.) Просыпается quasimoto и начинает обсуждать сам с собой монады, коммутативные диаграммы, стрелки, 2-стрелки, 3-стрелки, декартово замкнутые категории, аппликативные функторы, анаморфизмы, катаморфизмы, эпиморфизмы, параморфизмы, моноиды, полугруппы, когомологии и топосы Гротендика.
anonymous
()
Ответ на: комментарий от quasimoto

«GHC stage restriction» же - оно не умеет использовать макросы определённые в том же модуле.

А, ну так и говорить о макросах раскрывающихся в макросы тогда смысла нет - стандартный юзкейз же в том, что мы к этому макросу обращаемся из того же макроса, который в него раскрывается. Ну или из макроса который с ним семантически связан - и это все обычно в пределах одного лексического контекста (внутри одной ф-и или let'a, не говоря уж о модуле). Если такого делать нельзя то юзкейз macro-generated macro весьма ограничен, ясное дело.

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

Только макрос генерирующий макрос генерирующий top-levels это слишком крутой наворот - зачем?

Как зачем? eDSL. Почему какашкелисты все упорно считают, что eDSL могут быть только на уровне expressions?

Ну а самый смак - eDSL, который используется для описания других eDSL (то есть, должен раскрываться в определения макросов). Какашкелистам не понять.

anonymous
()
Ответ на: комментарий от quasimoto
(foreach [x seq]
  (some-macro тут "x" нет)
  ;; раскрывается в код с "x"
  )

Тут каша. Ты понял, что написал?

или так

#define MACRO1(...) \
    ... define magic__ variable ...

#define MACRO2(...) \
    ... using magic__ variable ...

... fun(...)
{
    MACRO1(...)
    MACRO2(...)
}
Довольно сомнительная практика и редко нужно так делать.

Это просто пипец. Не пиши больше такое в публичных местах.

то это хорошо

То это ЛNСП :)

Следовательно, лисп это хорошо. ЧТД. О чем споришь тогда?

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

Это тоже хорошо, но ты преувеличиваешь значение макросов, классы-методы или ADT-функции тоже позволяют скрыть `«грязный» код` оставив лаконичное API

Это все равно что сказать что с++/java/etc как замена программированию на асемблере или кодинге машинными коммандами это всего лишь попытка скрыть «грязный год». Молодец. Если что, главная задача макросов как и введение других высокоуровневых вещей (языков, конструкций, механизмов и т.д) это борьба со сложностью путем предоставлению инженеру инструментов с другим уровнем абстракции для создания более сложных вещей.

Ты опять мимо

Я же написал: «может обесценить другой в случае конкретных with* макросов», а ты зачем-то рассказываешь про «вообще».

Ты ходишь по кругу. Не тупи.

Ты много макр реализовал в своих проектах на лиспе?

Десяток-другой - как синтаксическая абстракция и аспектная ориентация было очень удобно. Но это как спрашивать сколько колбеков one насоздавал на Node.js, принято там так писать. Обычно всё сводится к 1) тривиальным синтаксическим абстракциям вроде with*, кастомных условий, циклов и т.п.;

Странное применение. Точно ничего не путаешь? Сможешь привести примеры?

2) к трансляциям dsl-s-expr -> code-doing-stuff которые заменяются функциями dslADT -> just-do-stuff

Что значит «заменяются»? «just-do-stuff» нихрена не dsl. Если ты делаешь dsl просто через фвп, то он должен иметь means of elements, means of combinations и means of abstractions. А то что у тебя просто что-то делается, это, все равно что засунуть мусор под ковер.

(статья выше);

Там авторы Sebastian Fischer, Frank Huch и Thomas Wilke. Ты кто из них?

3) к формам кодогенерации top-level определений - никогда не было проблемой.

Я тебя не про проблемы спрашивал. Ок, 3-й пример создания тобой макров выкидываем. Получается, примеров нет, а просто фантазии на тему. Хорошо.

Итого, ещё раз, для сложных применений 2) и 3) макросы не витальны (за исключением случаев обеспечения type safety или производительности), только для синтаксических абстракций

Перефразирую. «я пишу нечто, что делает что-то, и мне там макры не нужны». Тебе кто говорит, что макры нужно сувать везде? Тебе говорят (с примерами), что есть случаи, в которых нельзя обойтись без макросов. Ты понимаешь, какие это случаи?Почитай хотя бы On Lisp что ли.

1) они - нечто основополагающее.

Сам придумал - сам споришь. Молодец. Перечитай тред, к чему был приведен пример с foreach.

Не то.

Почему Template Haskell - не то?

Потому что в лисп обладает свойством homoiconicity. Макрос генерирует коллекцию с символами и self-evaluated объектами, который становиться кодом. Разницу в мощности кодогенерации чуешь?

пример небольшого вилосипеда DSL на C++.

Это любой транслятор DSL -> C++.

Вот твое полное утверждение

Так как я на CL уже довольно давно ничего не пишу - я их и не использую. Каких-то особых неудобств не испытываю (C++, Haskell, Scala). «Большие макры» при этом есть - разные формы deriving в хаскеле, DSL велосипеды в C++.

Я просил привести пример твоего «DSL велосипеда в С++». Твой ответ «Это любой транслятор DSL -> C++.». Т.е. ты намеряно ответил не в тему. Ясно.

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

Только макрос генерирующий макрос генерирующий top-levels это слишком крутой наворот - зачем?

Теперь все вполне ясно с тобой. Твой вопрос про «зачем» выдает в тебе блаб-эффект. Тебе неуд и пересдача через год. Пока дам подсказку: макросу не важно, является ли в конкретном месте генерируемого им кода символ именем функции или именем макроса. Используемый им макрос развернется позже. Если используемый макрос именно вычисляется в теле, то он конечно развернется перед выполнением основного макра.

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

Ты понял, что написал?

Это тот же «пипец» что и ниже код на си. Если ты согласен, что это не есть гуд, и в той твоей сентенции про макросы («А с помощью макроса можно просто описать...») имелись в виду только связи вида

(defmacro macro (var &body body)
  `(let ((,var ...))
    ,@body))

(macro it
  ;; body uses `it'
  )

то тут всё ок, это общепринято в лиспах с макросами и я тебя неправильно понял.

Следовательно, лисп это хорошо.

Нет, просто в гомоиконичном лиспе это воспринимается хорошо, а вне лиспа? То есть, есть ли полноценные макросы вне лиспа и как это сказывается на практике?

Это все равно что сказать ...

Тут что-то не так с логикой. Я говорю, что есть разные средства декомпозиции, борьбы со сложностью и определения абстракций - модульность, ООП, ФП, система типов, индуктивные данные и соответствующие «теории», «паттерны» и т.п. Они используются в разных языках и их хватает в большинстве случаев (для проведения декомпозиции и далее по тексту). Дальше, есть такая вещь как макросы, _при условии что_ у нас есть всё вышеперечисленное - когда этого всего не хватает и макросы находят непосредственное применение? Я своё текущее видение озвучил - 1) производные синтаксические формы - удобно, без макросов тут хреново, но это не принципиально, то есть, хорошо если бы это было и когерентно с другими синтаксическими фичами языка, но где оно в распространённых языках? 2) eDSL - делается как интерпретация ADT, или через ограниченные формы compile-time metaprogramming, 3) кодогенерация уровня top-level определений - опять формы «compile-time metaprogramming» (начиная от препроцессора, шаблонов и до staged систем), если получится, либо внешние DSL.

Точно ничего не путаешь? Сможешь привести примеры?

Примеры макросов которые суть тривиальные синтаксические абстракции ты уже сам приводил - with* и foreach. И таких макросов большинство. Например, в drakmа и hunchentoot только такие, в asdf, cffi, iolib и quicklisp-client есть 3) когда более сложным образом генерируются сразу функции и т.п. top-level определения, в sbcl уже есть 2), в виде vop-ов, например, и выглядит оно там страшненько, честно говоря.

Что значит «заменяются»? «just-do-stuff» нихрена не dsl.

Там eDSL это dslADT, по аналогии с dsl-s-expr, а just-do-stuff это эффекты и результаты от его интерпретации в runtime, минуя стадию генерации code-doing-stuff в compile-time который должен будет произвести эти результаты и эффекты в runtime. Что такое «eDSL на ФВП» я не знаю, по мне так это просто ФП (category theory patterns in programming как сказал один чувак из typesafe).

means of elements, means of combinations и means of abstractions

Ты цитируешь SICP? Забавно, что там нет макросов, а есть как раз обычное ФП. С нормальной типизацией и индуктивными данными всё что там пишут становится ещё очевидней, разумеется.

Там авторы Sebastian Fischer, Frank Huch и Thomas Wilke. Ты кто из них?

Это пример на тему small languages/dslADT -> just-do-stuff (effects + results). Ещё можно Functional Pearls, The Monad Reader, The Haskell School of Expression и прочие материалы про хаскель почитать - там много разных примеров. Или вот про сабж - http://biblion.epfl.ch/EPFL/theses/2011/5007/EPFL_TH5007.pdf. Да и из того же SICP должно быть понятно про что речь.

Насчёт «моих примеров» и т.п. - не вполне пойму чего ты хочешь, то как я провожу декомпозицию в ОО или ФП языке не отличается от того как это делают другие, мои макросы не отличаются от других макросов в проектах на CL и книжках типа PCL или On Lisp - your-vcs clone, cd, grep -rn «defmacro» * и вперёд. Просто у меня есть (меняющееся) мнение о программировании на ЯП в целом. Например, нужность правильно спроектированных структур данных, алгоритмов, интерфейсов, компонентов и их связей очевидна (надеюсь). Всё что я прошу - обосновать нужность макросов, то есть, по идее, это не я должен приводить примеры.

Тебе говорят (с примерами), что есть случаи, в которых нельзя обойтись без макросов.

Тебе говорят, что foreach это ерунда, а не пример.

Ты понимаешь, какие это случаи?

Вот не очень. Нагенерировать бойлерплейта? Запилить foreach с БиШ? Зафигачить «аспектную ориентацию», «метапрограммирование» и прочее, когда не хватает фантазии на нормальный дизайн?

Разницу в мощности кодогенерации чуешь?

Значит, то как в TH пишутся Q Exp/Dec это не то. А макросы скалы - тоже всё ещё не то? Макросы rustа? MetaOCaml?

Я просил привести пример твоего «DSL велосипеда в С++»

Классы для AST, flex, bison, минимальный чекер, принтер C++ кода, раздельная компиляция - что непонятно? Домен - сериализация данных в бинарное представление и обратно, по типу protobuf или derive-binary в хаскеле + эффективные выборки из таких данных. Просто это очевидно, когда речь заходит про не embedded DSL (не будем про шаблонные извращения, ок, хотя есть «статья выше» :)) в С++ - кто угодно так делает.

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

Твой вопрос про «зачем» выдает в тебе блаб-эффект.

Технически - я знаю, что

(defmacro define-something (...)
  ;; тут используем функции и макросы
  `(progn
    (defclass ...
      , и тут
      )
    (defmethod ...
      ...
      )
    (defun ...
      ...
      )
    (defmacro ...
      ...
      )
  )

использует функции и макросы во время генерации кода, также генерирует код с функциями и макросами (defclass, ...). Вот в quicklisp есть такой макрос, например, или в iolib. Но это особенности работы макросистемы - опять средство, а не самоцель.

И там скорее речь была про

(defmacro define-over-define (...)
  `(progn ,@(mapcar ... `(define-something ...) ...)))

внезапно, в лиспе я даже писал себе что-то вроде

(define-constants
  +раз+ ...
  +два+ ...)

которое так и работает, чтобы «нагенерировать бойлерплейта».

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

Ну и

(defmacro define-bulk-definer ...
  )

(define-bulk-definer define-constants defconstant)

тоже можно.

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

Ты понял, что написал?

Это тот же «пипец» что и ниже код на си.

Не увиливай. Вот твой код

(foreach [x seq]
  (some-macro тут "x" нет)
  ;; раскрывается в код с "x"
  )
Повторю вопрос еще раз. Что это за каша? Ты понял, что написал?

Если ты согласен, что это не есть гуд,

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

и в той твоей сентенции про макросы («А с помощью макроса можно просто описать...»)

Ты глухой и слепой. И долбишь одну и ту же мантру, которую сам же и придумал. «А с помощью макроса можно просто описать...» - это твои фантазии. Была конкретика, которую ты теперь пытаешься затуманить.

Следовательно, лисп это хорошо.

Нет, просто в гомоиконичном лиспе это воспринимается хорошо,

Что значит «воспринимается хорошо»? Т.е. в действительности не есть хорошо? И конечно же уровень аргументации зашкаливает.

а вне лиспа? То есть, есть ли полноценные макросы вне лиспа и как это сказывается на практике?

Ты сам себя спрашиваешь?

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

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

Точно ничего не путаешь? Сможешь привести примеры?

Примеры макросов которые суть тривиальные синтаксические абстракции ты уже сам приводил - with* и foreach. И таких макросов большинство. Например, в drakmа и hunchentoot только такие, в asdf, cffi, iolib и quicklisp-client есть 3) когда более сложным образом генерируются сразу функции и т.п. top-level определения, в sbcl уже есть 2), в виде vop-ов, например, и выглядит оно там страшненько, честно говоря.

Опять спрыгиваешь со своих слов. Я тебя не прошу написать примеры в чужих проектов. Вот что я написал

Ты много макр реализовал в своих проектах на лиспе?

Ты ответил

Десяток-другой - как синтаксическая абстракция и аспектная ориентация было очень удобно. Но это как спрашивать сколько колбеков one насоздавал на Node.js, принято там так писать. Обычно всё сводится к 1) тривиальным синтаксическим абстракциям вроде with*, кастомных условий, циклов и т.п.;

Я попросил примеров. Ты начал перечислять чужие проекты. А как же «десяток-другой» макров, которые ты написал?

Что такое «eDSL на ФВП» я не знаю, по мне так это просто ФП (category theory patterns in programming как сказал один чувак из typesafe).

Теперь расскажи, почему «category theory patterns in programming» это для тебя просто ФП. Или опять тему сменишь?

means of elements, means of combinations и means of abstractions

Ты цитируешь SICP? Забавно, что там нет макросов, а есть как раз обычное ФП.

Ты вырвал и процитировал часть. Вот был мой текст

Что значит «заменяются»? «just-do-stuff» нихрена не dsl. Если ты делаешь dsl просто через фвп, то он должен иметь means of elements, means of combinations и means of abstractions. А то что у тебя просто что-то делается, это, все равно что засунуть мусор под ковер.

И ты отвечаешь на него фразой

Ты цитируешь SICP? Забавно, что там нет макросов, а есть как раз обычное ФП.

Там речь шла про dsl через фвп. Где тут речь про макросы? Не можешь привести ни один аргумент, ссылаешься на абстрактные определения, придумываешь за меня тезисы, а потом на них отвечаешь. Теперь вот это. Молодцом. Ты показал себя тупым троллем.

Там авторы Sebastian Fischer, Frank Huch и Thomas Wilke. Ты кто из них?

Это пример на тему small languages/dslADT -> just-do-stuff (effects + results).

Т.е. я твоих собственных жемчужн создания dsl не дождусь? Все на других ссылаешься? Ок. Давай теперь means of elements, means of combinations и means of abstractions этого чужого dsl-а. Или ты это тоже не можешь показать?

Насчёт «моих примеров» и т.п. - не вполне пойму чего ты хочешь,

Ясное дело, что ты не понимаешь. Так всегда бывает, когда не можешь предъявить примеры из своих «десятков-других» макров.

Просто у меня есть (меняющееся) мнение о программировании на ЯП в целом.

Ну это-то понятно. У каждого дебила-кодера на пэхэпэ есть мнение о программировании на ЯП в целом.

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

Общие вещи. Это твое «меняющееся мнение о программировании»? Уау!

Всё что я прошу - обосновать нужность макросов, то есть, по идее, это не я должен приводить примеры.

Был пример того, чего нельзя реализовать без макров. Ты влез со своим бредом. Теперь ты требуешь обоснование нужности макров, не смотря на то, что нужность попунктно перечислена сто лет назад в том же On Lisp-е и тебе привели пример, чего нельзя сделать без макров. Что тебе еще нужно доказать, болезный?

Тебе говорят, что foreach это ерунда, а не пример.

Ага, ерунда, а сделать на фвп ниасилил. Вот собственно такой простой пример уже доказывает ложность утверждения одного конкретного оппонента, которому и предназначался изначально пример. Ты тут влез и начал бредить про то, что в хаскеле все хорошо, что в лисп это только «воспринимается хорошо» и что не понимаешь необходимости макров, фигача дебильными фразами типа «классы-методы или ADT-функции тоже позволяют скрыть `«грязный» код` оставив лаконичное API заточенное на нечто конкретное» потом спрыгиваешь с темы.

Ты понимаешь, какие это случаи?

Вот не очень. Нагенерировать бойлерплейта? Запилить foreach с БиШ? Зафигачить «аспектную ориентацию», «метапрограммирование» и прочее, когда не хватает фантазии на нормальный дизайн?

Вот ты опять в лужу пернул, академик ты наш. Макры всем этим вещам ортогональны. Твои рассуждения на тему «пчелы против меда». Ты пытаешься противопоставить макры уже не первый пост ортогональным им вещам.

Разницу в мощности кодогенерации чуешь?

Значит, то как в TH пишутся Q Exp/Dec это не то. А макросы скалы - тоже всё ещё не то? Макросы rustа? MetaOCaml?

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

Я просил привести пример твоего «DSL велосипеда в С++»

Классы для AST, flex, bison, минимальный чекер, принтер C++ кода, раздельная компиляция - что непонятно?

Понятно, что примера ты не привел, попутно видимо путая edsl c не edsl-ами. Один раз ты пукнул вот этим примером

#define MACRO1(...) \
    ... define magic__ variable ...

#define MACRO2(...) \
    ... using magic__ variable ...

... fun(...)
{
    MACRO1(...)
    MACRO2(...)
}

Вот это позор. После лажанул с

(foreach [x seq]
  (some-macro тут "x" нет)
  ;; раскрывается в код с "x"
  )

Что ты еще можешь после этого сказать? Вот именно, делать хорошую мину при плохой игре.

просто это очевидно, когда речь заходит про не embedded DSL

Дурачок, речь шла именно про embedded dsl. Ну давай, сделай удивленное лицо и спрыгивай по привычки с темы.

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

Твой вопрос про «зачем» выдает в тебе блаб-эффект.

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

Что значит «технически знаю»?

также генерирует код с функциями и макросами (defclass, ...). Вот в quicklisp есть такой макрос, например, или в iolib. Но это особенности работы макросистемы - опять средство, а не самоцель.

Это и ежу понятно, что макросы - средство. Что сказать то хотел?

внезапно, в лиспе я даже писал себе что-то вроде

(define-constants
  +раз+ ...
  +два+ ...)

Приведи код макра.

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

Ты понял, что написал?

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

Например, в С++ есть this : ClassType*, но нет Self == ClassType как в Scala, так что можно писать в некоторых классах typedef ClassType Self и потом делать, например, boost::bind(&Self::some_method, this), то есть более унифицировано - с макросами напрашивается сделать автоматическую генерацию Self и синоним self_bind(some_method) для boost::bind(&Self::some_method, this), но именно в С++ это, конечно, костыль вместо нормального Self. С Super та же история (при том, что и уникального Super тоже нет).

Или (опять сишные) макросы для дебага - они могут делать goto error, throw InitializationFailed, или вовсе вызывать деструктор класса (и тогда, опять, должны как-то узнать как называется класс - нужен Self / Super).

В том примере у меня было (macro1 (x ...) (macro2)) - macro2 должен раскрыться в код с x, то есть в реализации macro2 должен быть захардкожен именно x. Второй вариант - анафора (macro1 ... (using it)), тут обратная ситуация - в macro1 захардкожен it и уже внутренний using его использует. Наконец, третий случай это (macro1 ... (macro2)), предполагая, что macro1 что-то неявно вводит в скоп, а macro2 - неявно это использует. Пример с Self это явно третий случай, с простыми debug макросами - первый. Разные анафорические макросы - второй. Всё это примеры негигиенических макросов.

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

Я тоже. Точнее, это было не вполне в тему.

это твои фантазии.

Нет ты

А с помощью макроса можно просто описать, состоящем из выражений (для пользователя не функций а именно выражений тела) в теле с использованием этих самый забайденных переменных с областью видимости по всему телу. Да, действительно, несущественное отличие в используемый пользователем библиотеки абстракций.

(foreach [x seq] (print x))

forM_ seq $ \x -> print x == forM_ seq print == mapM_ print seq == thisMapper seq where thisMapper = mapM_ print

seq foreach { x => print(x) } == seq foreach print

FTW?

Ага, ерунда, а сделать на фвп ниасилил.

ап хеар. Тебе уже говорили, что map тут достаточно, с сахаром для блоков - ещё лучше.

Что значит «воспринимается хорошо»? Т.е. в действительности не есть хорошо?

Внеязыковой «действительности» как таковой тут нет, есть разные языки с разной культурой написания кода. Что значит - пока что макросы как они есть в лиспе это локальное (лисповое) явление. А так я _тебя_ спрашивал - что думаешь по этому поводу? То есть «полноценные» макросы в статических и не гомоиконных языках это как бы проблема (то есть проблема в их удобной реализации, люди вон тезисы на эту тему пишут).

Ты сам себя спрашиваешь?

Да так, говорю разные вещи, привожу ссылки и озвучиваю вопросы. Но ITT на полезную отдачу уже не рассчитываю, увы (можно же узнать что-то полезное на ЛОРе?).

Тебе я уже объяснял про ортогональность макросов к остальным возможностям языка.

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

А как же «десяток-другой» макров, которые ты написал?

Если что, то вопрос «сколько макросов ты написал» я понял как сколько макросов в реальном коде который я писал и который использовался, не экзерсисов, он не open source вообще и я его приводить не собираюсь, но на твой вопрос «сколько» - ответил. А что касается примеров и эксзерсисов - это common sence если ты интересуешься, тогда давай начни выпрашивать «примеры функций которые я написал». Странный какой-то разговор получается.

Интересно другое - зачем ты спрашиваешь? Ты никогда макросов не видел? Видел же. Значит, пытаешься выяснить осилил я их или нет? С этим сразу в сад. Ты бы лучше не о том кто тролль, а кто нет, и не о парадоксах блаба волновался, а что-нибудь интересное рассказал, то есть обсуждал технические вопросы. Пока что я вижу только forech, SQL в s-выражениях и пересказы проповедей Хикки про то какое негодное классическое ООП, как хороши мультиметоды «позволяющие описывать произвольные таксономии» и как хороши pesistent shared контейнеры (нормальные небоксированные мутабельные структуры данных с in-place обновлением и кастомными механизмами inter task синхронизации не нужны, как я понимаю).

почему «category theory patterns in programming» это для тебя просто ФП

Опять что-то с логикой - в другую сторону импликация. ФП можно так понимать - типы как объекты, каррированные функции как стрелки, HOFs как экспоненциалы, чистота, ссылочная прозрачность, аппликативность и свободные (при совпадении доменов-кодоменов) композиции, equational theory settings / reasoning как следствие, в терминах ТК, в том числе, начальные алгебры / финальные ко-алгебры как фреймворк для описания индуктивных рекурсивных данных (как выход - результаты, значения) и ко-индуктивных ко-рекурсивных потоков данных (как вход); функторы, монады, Kleisli категории - многие индуктивные [возможно] рекурсивные типы данных которые функторы (начиная с Identity, Maybe и List), также, обычные суммы, произведения и степени, то есть кортежи/записи, объединения/варианты и функции - writer, error и reader/environment, для функций более специального вида - prompt, parser, state и cont, par/conc/async как cont для fork/join/io/done языка; функторы, ко-монады, coKleisli категории - ко-индуктивные ко-рекурсивные типы данных которые функторы (простейшие потоки и деревья, например), те же произведения и степени (суммы?), указатели и изменяемые подструктуры (линзы, как функции в), зипперы; свободные монады вокруг типов данных которые функторы - iteratees (которые сами по себе потоки, то есть финальные коалгебры для соответвующих (строго-позитивных таки) функторов), разные языки (eDSL на ADT) и их интерпретаторы; ко-свободные ко-монады для типов данных которые функторы - ?; (под)категории и стрелки - линзы (категория, тензор, но не вполне стрелка), обычные функции, Kleisli стрелки, coKleisli стрелки, стрелки biKleisli категорий, функции ограниченные типом - списки-в-списки, потоки-в-потоки, деревья-в-деревья, сигналы-в-сигналы и поведения-в-поведения (как оно применяется в FRP) и т.п., автоматы, симуляции, преобразователи, некоторые языки-eDSL-на-ADT, опять же; монадические трансформеры как определённого вида натуральные трансформации для определённого вида функторов над разными монадами - WriterT, ErrorT, ReaderT, StateT, ContT, MaybeT, ListT и т.д., например, ReaderT (ConstEnvironment, MutableScope, Resources) IO - эффекты, injectable read-only / write окружение, список ресурсов пополняемый их захватами по мере выполнения и автоматически освобождаемый в конце; полугруппы, моноиды, сворачиваемые и обходимые типы и т.п. категорные и алгебраические типы и классы как «паттерны» и средства декомпозиции. Кто так делает? Haskell и Scalaz, как минимум. F# в меньшей степени.

А можно не принимать такой номенклатуры, ограничиваясь look ma, lambdas, closures and HOFs!

Обратно говорить неправильно - элементы теории категорий в применении к ЯП могут быть чем угодно, не обязательно что-то связанное с ФП, они могут быть введены при изучении семантики конкурентных программ, семантики эффектов, [W]FSM, например.

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

Там речь шла про dsl через фвп.

[eDSL через ФВП]

Тогда понятно. Но это всё равно забавно в контексте всего разговора.

Насчёт eDSL и ФВП - тут просто грань между «eDSL» и библиотечным кодом слишком неясная. Класс с интерфейсом это может быть eDSL? Построение SQL удобными функциями скрывающими обычный string builder? HTML на комбинаторах вокруг writer monad?

Все на других ссылаешься?

Да, я за образование. Чтобы не обсуждать очевидных вещей, как вот мы.

means of elements, means of combinations и means of abstractions

И чего ты прицепился к абсолютно произвольным словам абсолютно произвольной книжки? Мутно же. Если elements = термы (алгебраических, индуктивных, логических, в зависимости от степени общности) типов, combinations = функции правильного языка их строящие, abstractions = функции интерпретации, правила типизации и денотационная семантика, то ещё ничего. Но тогда вопрос - сам уже ответ.

Или ты это тоже не можешь показать?

Нет. Опять же, это очевидно - объяснять что такое индуктивные типы, какие есть варианты типизированного лямбда исчисления, как они типизируются и как доказывается что семантика получается правильной? Выучи какой-нибудь ML/Haskell, почитай TAPL, ATTAPL, Practical Foundations for Programming Languages, Software Foundations (also - http://alexott.net/ru/fp/books). Это если ближе к практике и ЯП, а не к теории.

Общие вещи

Для меня они вполне конкретные, но это нужно разбираться, да.

Макры всем этим вещам ортогональны.

Ты не знаешь что такое макросы, выходит. То есть они не для того чтобы генерировать top-levels, определять свои специальные формы и аспектную ориентацию в виде кодогенерации из абсолютно предметно-специфичного eDSL в конструкции языка во время компиляции? Я в очередной раз перечислил эти три пункта - у меня макросы с ними ассоциируются. Эти применения - прямое следствие того что макросы это средства для введения новых синтаксических абстракций, и, наоборот, то что они такие средства предполагает именно такие применения.

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

Ну то есть нормально с тобой поговорить нельзя? Вопрос задать, например? Уже после третьего-четвёртого звена в цепочке уже вон как колотит, но не понятно с чего. А конкретные примеры есть по ссылкам, да и вообще, «У каждого дебила-кодера на пэхэпэ есть мнение о программировании на ЯП в целом» - то есть всё и так должно быть известно чтобы можно было высказать это самое мнение.

путая edsl c не edsl-ами

Тут везде в моих постах у eDSL есть e, у DSL - нет, не мои проблемы.

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

Что значит «технически знаю»?

То и значит - вот так вот оно работает. Раскручивается в экспандере за сколь угодно большое количество стадий.

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

Я сказал средства - особенности работы макросистемы. А цель в данном примере - нагенерировать бойлерплейта из некоего его описания. Как в quicklisp - define-implementation-package - пакет + класс, definterface - добавили generic, набор методов (макрос принимает произвольный код на CL) и функцию ему, defimplementation - добавили ещё метод (и тут тоже). Но рассматривание кода подсказывает, что бойлерплейт тут минимальный, то есть если его написать руками применяя обычную раздельную компиляцию - разницы не заметишь (кроме того что исчезнут три сущности).

Приведи код макра.

Но зачем? Представь себе этот макрос - вот тебе и код.

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

Вот, кстати, в scalaz есть positive cofree™ corecursion®, но примеров не видно :)

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

Дальше, есть такая вещь как макросы, _при условии что_ у нас есть всё вышеперечисленное - когда этого всего не хватает и макросы находят непосредственное применение?

Вопрос надо задавать не так. «_при условии что_ у нас есть макросы - когда их не хватает и все вышеперечисленное находит применение?»

Никто не спорит, что одну и ту же задачу можно решить разными способами. Можно макросами, можно типами/адт, можно еще как-то. Но почему макросам следует предпочесть альтернативные пути?

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