LINUX.ORG.RU

[ФП][срач] Язык программирования Pure


2

4

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

  • Синтаксис, бликий к Haskell (включая карринг, срезы, лямбды, сопоставление с образцом, list comprehensions и «as» patterns);
  • Поддерживает модель ленивости, основанную на продолжениях и заимствованную из Alice ML;
  • Допускает функции с побочными эффектами, опциональную аннотацию типов, интерфейсные типы
  • Поддержка рациональных, комплексных чисел, встроенный RegEx;
  • Содержит спектр встроенных структур данных, таких как: списки, туплы, векторы, матрицы и ленивые последовательности;
  • Интеграция с GSL;
  • Поддерживает полноценную систему гигиенических макросов;
  • Лёгкий FFI с сишными библиотеками;
  • Реализация под LLVM под GNU/Linux, Mac OS X, FreeBSD и Windows;
  • Из коробки поддержка компиляции в нативный код;
  • В комплекте идёт набор батареек для разнообразных нужд.

Про производительность заявляется следующее:

The Pure interpreter is able to achieve very good performance, offering execution speeds in the same ballpark as good Lisp interpreters. It seems to be one of the fastest implementations of term rewriting as a programming language right now, and is certainly good enough for most programming tasks except maybe the most demanding number crunching applications (and even these can be tackled by interfacing to Fortran or C).

Язык активно развивается, последняя версия документации датирована 8 января, автор постоянно пилит своё детище, активно идёт на контакт и охотно принимает и рассматривает любые предложения.

Ссылка на страницу проекта: http://code.google.com/p/pure-lang/
Ссылка на документацию (pdf): http://docs.pure-lang.googlecode.com/hg/puredoc.pdf
Ссылка на пример полной реализации АВЛ-деревьев: http://pure-lang.googlecode.com/hg/pure/examples/avltree.pure
Репозиторий (лицензия LGPLv3): hg clone https://code.google.com/p/pure-lang/

★★★★★

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

Поддерживает полноценную систему гигиенических макросов;

Это следует читать как «нуждается в макросистеме», т.е., как недостаток, а не как достоинство.

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

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

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

Покажи мне место в доке, которое описывает какие-то возможности Pure, дающие ему шанс на признание.

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

Хотя, кому я объясняю, у тебя-то точно коровья кака вместо мозга. Когда ты там начинал вякать, что «пытаешься освоить ocaml»? И до сих пор ведь «пытаешься». Это надо быть редкостным дебилом, прямо-таки феноменальным, чтобы так тормозить.

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

В макросистеме нуждается, по хорошему, каждый язык. Потому как без переписывания кода невозможно создавать eDSL-ы с существенно другой семантикой (не говорю уж про синтаксис). Да и никакая семантика, пусть даже самая супер-пупер-ленивая-и-чистая не спасает от boilerplate кода, а даже самые тупые макры, да что там, даже самый тупой препроцессор очень даже помогает.

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

Разница та же, как между (let ((id1 expr1) (id2 expr2) ...) body ...) и (let (id1 expr1 id2 expr2 ...) body ...) - формы вроде первой легко генерируются и разбираются в макросах, вторые - сложно.

Можно на примере показать?

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

Про эволюцию правильно сказано. А старые быдлокодеры и тролли вроде tailgunner'а имеют малый кругозор и понимают только «здесь и сейчас».

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

Быстрое прототипирование же, в особенности математики и всей, что с ней связано.

а explicit type universes поддерживаются?

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

Да, почитал у него на сайте, может я и напраслину возвел, признаю. Но тогда остается вопрос «Why Pure?»

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

некто писал, что сделал биржевую систему с временем обработки транзации в 200нс именно на Q

Именно на этом Q?

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

Какая разница как писать: "(complex 3 4)" или «3 <: 4»

[..] формы вроде первой легко генерируются и разбираются в макросах, вторые - сложно.

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

По-этому для ЯП, в котором последние формы встречаются достаточно часто, макросы неприменимы принципиально.

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

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

Покажи мне место в доке, которое описывает какие-то возможности Pure, дающие ему шанс на признание.

Слышь, ничтожество, ты бы сначала объяснил, на кой языкам нужен «шанс на признание»?

Ты почему-то подумал, что это нужно языку? Это нужно людям.

Так может ты покажешь место в доке? :)

для эволюции совершенно не обязательно широкое распространение какого либо из видов

А Pure уже стал целым видом? За вид «динамически типизированные быдлоязычки» я как раз спокоен - он будет жить %)

я объясняю

То, что ты написал - это не объяснение, а мутный поток непонятно чем обиженного сознания %)

Когда ты там начинал вякать, что «пытаешься освоить ocaml»? И до сих пор ведь «пытаешься»

Нет, текучка заедает. Но книга лежит на диске, так что не теряй надежды %)

tailgunner ★★★★★
()

[...] as good Lisp interpreters.

Какие например? Для CL я знаю только о clisp.

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

Ты почему-то подумал, что это нужно языку? Это нужно людям.

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

И тебя уже спрашивали - Mathematica «не нужна», да? Отвечай, ламерье.

А Pure уже стал целым видом?

Ты, лошара, явно в таксономии плаваешь.

За вид «динамически типизированные быдлоязычки» я как раз спокоен - он будет жить %)

Это, сявка, не «вид», это как минимум класс или даже подцарство.

Нет, текучка заедает.

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

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

И тебя уже спрашивали - Mathematica «не нужна», да? Отвечай, ламерье.

А я спрашивал ссылок на документацию. Внезапно, нет ответа.

сявка

лошара

Ламер, тупица

%)

ты никто и ничто, и звать тебя «ноль без палочки».

От анонимуса это слышать особенно прикольно %)

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

Кто осмелился вызывать меня?!?

Гхм. А по теме мне сказать нечего. Я использовал «q», а это «Q». Почувствуйте разницу.

«q» - закрытый язык (см. http://kx.com ), «Q» - GPL (см. http://q-lang.sourceforge.net/ ), и общего между ними немного.

alt-x ★★★★★
()
Ответ на: комментарий от mix_mix

Какие задачи этот язык решает лучше, чем другие существующие языки?

Быстрое прототипирование же, в особенности математики и всей, что с ней связано.

Жаль только для «general-purpose programming language» (хотя-бы в качестве ещё одного «убицы питона» :)ь ему не хватает поддержки threads

yyk ★★★★★
()

Господа модераторы, как там насчёт 5.1 и 5.2? Может, имеет смысл забанить товарища по IP за всё хорошее? В принципе, персональные наезды на оппонента - дело хорошее и понятное, но вовлекать его родителей, возможно, не стоит?

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

Неужели ты думаешь, что в таких явных нарушениях генетика не виновата? Все на воспитание валить будешь, да?

anonymous
()

<<Синтаксис близкий>>

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

вот только sicp дочитаю...

Драгонбук тоже, а то мёртворожденных буратин и так хватает.

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

Ещё один ЯП для высчитывания факториалов? Не нужно.

PolarFox **** (12.01.2012 16:52:13)

Вот ты как 4 звезды набрал...

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

Вот ты как 4 звезды набрал...

т.е. ему можно, а мне нельзя? :)

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

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

Зато их можно собирать и разбирать на уровне AST:

genLet :: [(String, Integer)] -> Q Exp
genLet bindings = do
  let (names, vals) = unzip bindings
  namesE <- mapM newName names
  valsE <- mapM (\n -> [| n |]) vals
  plus <- [| (+) |]
  zero <- [| 0 |]
  let decs = zipWith (\x n -> ValD (VarP x) (NormalB n) []) namesE valsE
      expr = foldr (\x xs -> InfixE (Just (VarE x)) plus (Just xs)) zero namesE
  return $ LetE decs expr

-- > runQ $ genLet [("x", 1), ("y", 2)]
-- LetE [ValD (VarP x_0) (NormalB (LitE (IntegerL 1))) [],ValD (VarP y_1) (NormalB (LitE (IntegerL 2))) []] (InfixE (Just (VarE x_0)) (VarE GHC.Num.+) (Just (InfixE (Just (VarE y_1)) (VarE GHC.Num.+) (Just (LitE (IntegerL 0))))))

Если нескобочному коду (с инфиксами и другими специальными синтаксическими формами) однозначно соответствует скобочная, а точнее AST-форма (как Exp из примера выше в TH) и язык позволяет свободно обращаться с этой формой (quote, splice, собирать и разбирать), то такой язык, с одной стороны, будет иметь конкретный синтаксис, и, с другой стороны, позволять макро-вычисления (TH в этом смысле ограничен).

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

однозначно соответствует

т.е. если мы видим

let ... = ...; ... = ...; ... in ...

то после цитирования получается:

LetE :: [Dec] -> Exp -> Exp

которую уже легко разбирать и собирать.

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

Ну и ещё:

> (car (+ 1 2 3))
The value 6 is not of type LIST.
> (car '(+ 1 2 3))
+

добавление конкретного синтаксиса ничего не меняет:

> (car [1 + 2 + 3])
The value 6 is not of type LIST.
> (car '[1 + 2 + 3])
+

главное чтобы quote и splice работали правильно. И ещё есть момент в том _какую_ структуру данных возвращает quote - если в языке можно переопределить всё и вся, любые специальные формы, как в лиспе, то брать что-то большее s-expressions нет смысла, если же в языке имеется более широкий набор неизменяемых специальных форм в абстрактном синтаксисе, как в хаскеле (lambda, let, if и т.п.), т.е. ядро языка является более строгим, то quote должен возвращать элементы ADT которое отображает структуру этого неизменяемого ядра (как Exp, Dec и прочие из TH).

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

1. никакой разницы особой (так чтобы прям сильно заметно было) при разборе подобных выражений нет

Если писать в десять раз больше кода/использовать в десять раз более навороченное апи к парсеру - это «особой разницы нет», то ок, конечно.

2. про макросы можно поподробнее? в частности интересует - почему сложности возникают и с какого это лешего макросы стали критерием для применения той или иной формы записи

Ну речь изначально о макросах шла, потому и в контексте макросов.

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

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

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

Зато их можно собирать и разбирать на уровне AST:

О чем и речь. Разобрать то _можно_ но какой ценой? И кому нужны такие вот макросы, как в приведенном тобой примере? Да никому не нужны.

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

Позволять - будет. Но использовать их будет нельзя по той же причине, по которой нельзя использовать брейнфак. То есть в сферической теории - конечно, можно, но вот на практике. ну вот серьезно, есть у тебя кусок вот такого вот говна:

-- LetE [ValD (VarP x_0) (NormalB (LitE (IntegerL 1))) [],ValD (VarP y_1) (NormalB (LitE (IntegerL 2))) []] (InfixE (Just (VarE x_0)) (VarE GHC.Num.+) (Just (InfixE (Just (VarE y_1)) (VarE GHC.Num.+) (Just (LitE (IntegerL 0))))))

И что это? Ты можешь с первого взгляда определить что это вообще за хрень, что делает и как работает? Как это разбирать? Как генерить? Как отлаживать - я уж даже и не спрашиваю, понятно, что никак. Так что остается только засунуть себе в жопу и улыбаться. Макросы вообще - это такая область, которая может быть максимально декларативна, то есть при идеальной макросистеме ты просто говоришь какая форма в какую форму должна раскрываться - и ты вообще не должен думать о том, как эту форму разбирать и как собирать результат (то есть должна быть просто атрибутная грамматика). Если ты где-то применяешь какие-то функции для ручного петушения АСТ типа всяких map/zip/fold/loop - это признак того, что макросистема непродуманное говно. И ее надо выкинуть нахуй.

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

которую уже легко разбирать и собирать.

Ну в том и проблема, что нельзя. Легко нельзя.

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

добавление конкретного синтаксиса ничего не меняет:

Очень даже меняет. Опиши грамматику (+ 1 2 3), а потом грамматику [1 + 2 + 3] и сравни сложность обеих.

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

т.е. ядро языка является более строгим, то quote должен возвращать элементы ADT которое отображает структуру этого неизменяемого ядра (как Exp, Dec и прочие из TH).

Ну quote в любом случае возвращает ADT что в хаскеле, что в лиспе, просто чем проще ADT, тем проще его парсить и генерировать, вот и все.

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

Макросы вообще - это такая область, которая может быть максимально декларативна, то есть при идеальной макросистеме ты просто говоришь какая форма в какую форму должна раскрываться - и ты вообще не должен думать о том, как эту форму разбирать и как собирать результат (то есть должна быть просто атрибутная грамматика). Если ты где-то применяешь какие-то функции для ручного петушения АСТ типа всяких map/zip/fold/loop - это признак того, что макросистема непродуманное говно. И ее надо выкинуть нахуй.

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

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

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

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

(define-syntax-rule (my-let ((id expr) ...) body ...)
  (let ((id expr) ...) body ...))

А если у нас let кривой, то придется либо пидорасить АСТ руками (и прощай декларативность) или усложнить pattern-language ну как-нибудь вот так:

(define-syntax-rule (my-let (~seq (id expr) ...) body ...)
  (let (~seq (id expr) ...) body ...))
или использовать при генерации какой-нибудь work around типа такого:
(define-syntax-rule (my-let (~seq (id expr) ...) body ...)
  #:with ((x ...) ...) #'((id expr) ...)
  (let (x ... ...) body ...))
по-этому есть просто два правила - любая семантическая единица должна быть взята в скобки, разные по смыслу единицы не должны чередоваться. Если эти правила нарушаются - получается всякое убожество типа loop из CL с кодеволкерами на несколько тысяч строк.

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

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

Естественно, это вещи не связанные. Но то, как язык выглядит, определяет _применимость_ этой макросистемы. Например, у вас есть оператор op и список аргументов args, как вы сгенерируете форму в префиксной нотации? (op args ...) или там `(,op ,@args) - ну коротко и ясно все. А как вы будете генерить ее в инфиксной нотации? Ну не получится у вас декларативно, либо получится сложно - потому что вы должны описать грамматику результата. И чем проще эта грамматика - тем лучше. А грамматика результата - это под-грамматика хост-языка, в некотором смысле. И сложность первой завязана на сложность последней.

Ведь так?

Ну я выше объяснил, что не так - если порождаемое выражение грамматически сложнее, то сложнее и декларативное описание. И макрос становится сложнее - для всего сложнее, для написания, для чтения, для отладки.

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

Опиши грамматику (+ 1 2 3), а потом грамматику [1 + 2 + 3] и сравни сложность обеих.

И то и другое это просто (App (Var «+») (Lit 1) (Lit 2) (Lit 3)) (ну или App дважды с левой стороны во втором случае), с которым уже можно работать. Сами по себе s-выражения это простенький ADT, который при этом не представляет AST никакого конкретного языка программирования - в s-выражении можно хранить как данные, так и код, причём коду тому можно дать произвольную семантику. Да, весь поинт гомоиконичности в этом.

ADT представляющее AST конкретного языка это, например, термы LC или его расширения:

data Expr
  ...
  | App Expr [Expr]
  ...
  | Quote Expr
  ...

весь поинт ML-ей и пост-ML-ей, в свою очередь в том, чтобы отделять разные языки путём отделения представляющих их AST ADT. Нужно дать метауровень - добавляем в ADT основного языка (пусть, Lang) конструктор Quote, нужно определить DSL - определяем нужный ADT и свёртки для него (печать, чтение, интерпретация), нужен компилируемый в основной язык DSL - определяем отображение DSL's ADT -> Lang на метауровне.

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

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

И то и другое это просто (App (Var «+») (Lit 1) (Lit 2) (Lit 3))

Я задам вопрос по-другому. мне хочется сгенерировать выражение [1 + 2 + 3] - как это сделать при помощи квазицитирования (мы же не хотим руками АСТ собирать)?

Нужно дать метауровень - добавляем в ADT основного языка (пусть, Lang) конструктор Quote, нужно определить DSL - определяем нужный ADT и свёртки для него (печать, чтение, интерпретация), нужен компилируемый в основной язык DSL - определяем отображение DSL's ADT -> Lang на метауровне.

Да это все не важно. Важна простота грамматики. Если мне надо разбирать/генерить кашу из app/lit/var/etc - то это плохо, потому что это каша и read-only, это ручная сборка АСТ. А квазицитирование завязано на вид самого языка. Ну и еще один ньюанс - все же, удобнее работать с АСТ, когда это АСТ напрямую соответствует коду.

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

А как вы будете генерить ее в инфиксной нотации?

Я за desugaring, так чтобы на мета-уровне работать с AST который, с одной стороны, не голые s-выражения, но, с другой стороны, не переусложнён как TH.Exp. По крайней мере, он должен отражать семантику языка, те формы на которые навешаны семантические атрибуты - lambda, let и т.п. должны быть конструкторами данного ADT (а не только nil и cons).

На самом деле, desugaring может быть и в s-выражения, с которым производятся мета-вычисления, при этом перед parse может быть сколько угодно сахара, а после pretty-print весь этот сахар может возвращаться обратно.

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

Нет, ну ты сделай, а мы посмотрим.

foldr1 (++) (flatten-1 в лиспах) в одну сторону и такая же фигулина в другую, что тут делать?

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

foldr1 (++)

Это что? Ты полное решение приводи, как я привел. Есть оператор в переменной op, есть список аргументов в списке args, напиши как получить arg1 op qrg2 op ... op argn.

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

Ну да, desugaring, мета-уровень АТД хуе-мое и все такое - это очень круто, а теперь при помощи квазицитирования сгенерируй мне [1 + 2 + 3].

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

А, я понял. Как обычно - это задача тянет на тему для Ph.D.

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