LINUX.ORG.RU

Mercury 14.01

 logic programming, , , ,


3

7

Ещё 10 февраля вышла новая версия языка Mercury — 14.01. Мажорные релизы называются по номеру года и месяца запланированного выпуска, предыдущий был 13.05.

Mercury — это логический и функциональный язык программирования, похожий на Prolog, но с поддержкой компиляции в машинный код, чистыми предикатами, со строгой статической типизацией, явным объявлением детерминизма предикатов, с функциями (а не только предикатами), встроенным каррированием и другими новшествами.

В новой версии:

  • Могут повторяться переменные типов в объявлении экземпляров классов типов (type class instances). Например:
    instance foo(list(T), map(T, T)).
  • Ряд улучшений в стандартной библиотеке, особенно связанных с функциями свёртки списков (см. полный список).
  • Исправлены проблемы совместимости с GCC 4.8 (а также с Visual Studio 2013 и Mac OS X 10.9).

Сайт Mercury

Скачать

>>> Примечания к выпуску 14.01

★★★★★

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

Ну а вообще, джва года ждал

Meyer ★★★★★
()

Годнота!

Кстати, а как у него обстоят дела с работой под, простите, оффтопик?

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

Кстати, а как у него обстоят дела с работой под, простите, оффтопик?

Я сам не проверял, но должно работать.

proud_anon ★★★★★
() автор топика

Годнота! Вот бы еще и хаскель платформ релизнулся, эхх :(

anonymous
()

Кто это юзает - тот Stallman-like нерд с густой бородой, широкими сферическими линзами и пузом под толстым свитером :) Не представляю шуструю молодежь на таких платформах :)

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Борщехлебы и юзают - кто еще?

anonymous
()

Прикольная штука. Есть FFI к C, C#, Java, Erlang. Есть явное указание pure/impure для функций.

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

Ну вот. Ссылку эту можно было и добавить в новость.

Не вижу большого смысла. Желающие могут найти её на сайте в разделе «Development».

proud_anon ★★★★★
() автор топика
Ответ на: комментарий от i-rinat

Нечасто на github'е встретишь временную метку «20 лет назад»

В самом деле, это старше, чем сам Github и даже чем сам Git. Судя по всему, у них был CVS, потом они мигрировали на SVN, потом на Git, и всё это без потери истории коммитов.

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

В самом деле, это старше, чем сам Github и даже чем сам Git

Давай поиграем в инженерную археологию :)

На git они перешли только в марте 2013, у них в на сайте в новостях это написано.

Судя по всему, у них был CVS

https://github.com/Mercury-Language/mercury/blob/6ffec8a4afca6a42d820df32eff1...

Похоже, ещё и RCS использовалось.

i-rinat ★★★★★
()
Ответ на: комментарий от ymn

Собирается, работает. Есть C#-grade. Одно время я даже делал периодически свою сборочку.

buddhist ★★★★★
()

По какой причине я могу внезапно начать изучать этот неведомый до этого дня для меня язык?

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

По какой причине я могу внезапно начать изучать этот неведомый до этого дня для меня язык?

+1, симпатию к сабжевому языку вызвать сложнее чем рвоту, всё не перестаю удивляться подобным платформам :)

I-Love-Microsoft ★★★★★
()

И другие новшества.

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

Camel ★★★★★
()
Ответ на: И другие новшества. от Camel

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

Ну вот ты знаешь Пролог или Хаскель?

Мне казалось, что каррирование в языке не может претендовать на новшество.

Для Пролога — новшество.

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

«Mercury requires too many declarations»

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

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

«Mercury requires too many declarations»

Ну, что правда, то правда.

Смотря с чем сравнивать:

Hello world:

Mercury:

:- module hello.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
main(IO!) :-
     io.write_string("Hello, World!\n", IO!).

Си:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello, World\n")
}

На Java ещё больше.

Программа, запрашивающая числа, и выводящая соответствующие числа Фибоначчи

:- module hello.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- func fib(int) = int.
:- implementation.
:- import_module list, string.

fib(N) = ( if N =< 2 then 1 else fib(N - 1) + fib(N - 2) )

main(!IO) :-
  io.read_line_as_string(Result, !IO),
  (
    Result = eof,
    io.format("bye bye...\n", [], !IO)
    ;
    Result = ok(String),
    ( if string.to_int(string.strip(String), N)
      then io.format("fib(%d) = %d\n", [i(N), i(fib(N))], !IO)
      else io.format("that isn’t a number\n", [], !IO)
    ),
    main(!IO)
    ;
    Result = error(ErrorCode),
    io.format("%s\n", [s(io.error_message(ErrorCode))], !IO)
   ).

Можешь прикинуть, сколько займёт вариант на C/C++/Java (обрати внимание на обработку ошибочного ввода).

monk ★★★★★
()

Есть ф-ия с множественным результатом, нужно получить итератор, а потом где-то взять n-ое значение. Mожно через solutions.do_while с явным аккумулятором, но немного муторно.

Возникает вопрос: почему в solutions нет list-like интерфейса / или как идимоматично реализовать итератор?

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

Это уже даже не борщ, это какие-то котлеты из говна.

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

Есть ф-ия с множественным результатом, нужно получить итератор

А зачем тебе нужен итератор? Почему нельзя обойтись обычным backtracking'ом?

а потом где-то взять n-ое значение.

А что такое в общем случае n-е значение? Функции не обязаны выполняться в строго определённом порядке.

Возникает вопрос: почему в solutions нет list-like интерфейса

Как нет? solutions.solutions, solutions.solutions_set, solutions.unsorted_solutions.

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

Но прикинь на Python!

def fib(n):
    if n <= 2:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)

while True:
    try:
        i = int(input('Введите число: '))
        if i <= 0:
            print('Число должно быть больше 0')
        else:
            print('Результат: {}'.format(fib(i)))
            break
    except (KeyboardInterrupt, EOFError):
        print('\nПока-пока!')
        break
    except ValueError:
        print('Это не число или не целое!')
И, заметь, оно будет переспрашивать юзера, пока он не введёт допустимое число.

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

Однако речь ведь шла о лишних декларациях. А когда человек видит это:

:- module hello.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- func fib(int) = int.
:- implementation.
:- import_module list, string.
Вот тут и приходит ему в голову мысль: э... а надо ли оно...

Хотя по идее на Сях раньше хедеры писали вручную, так что...

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

А зачем тебе нужен итератор? Почему нельзя обойтись обычным backtracking'ом?

Модульность кода же: можно писать отдельно итераторы, отдельно комбинаторы над ними, скажем «взять первых 10 решений» для двух различных функций.

А что такое в общем случае n-е значение?

Говорилось о функции вида multidet, у нее решения уже не по порядку?

Как нет?

Потому что это все придется велосипедить, многое из list имело бы смысл в контексте solutions. Если упоминаю do_while, наверное я видел этот модуль?

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

Модульность кода же: можно писать отдельно итераторы, отдельно комбинаторы над ними

А... Хаскелль...
Ты скажи, чего тебе надо в результате сделать?

Говорилось о функции вида multidet, у нее решения уже не по порядку?

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

Что же касается multidet (точнее, multi), то это всего лишь значит, что предикат или функция всегда имеет не менее одного решения.

Потому что это все придется велосипедить, многое из list имело бы смысл в контексте solutions. Если упоминаю do_while, наверное я видел этот модуль?

Не понимаю, что надо. При помощи solutions можно получить list и set. Что может быть более list-like, чем list?

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

Ты скажи, чего тебе надо в результате сделать?

Кода под рукой нет, когда-то пробовал стандартный пример: фибоначчи-multidet: код был заметно короче, чем take_nth_solution реализованный через do_while. Причем, ему пришлось пробрасывать в качестве возвращаемого значения, что maybe(A) (т.е. аккумулятор был pair(int,maybe(A)) ).

Говоря «не по порядку» я имел в виду, что никто не гарантирует, что решения будут находиться в каком-то определённом порядке.

Пример?

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

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

gloomdemon
()
Ответ на: комментарий от I-Love-Microsoft

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

То же самое можно спросить и про любой другой язык. Когдя я искал нечто лучшее чем visual prolog 5.2 (потому что увидев 6ю версию понял что надо завязывать с visual prolog), то основными фишками для меня стали:

1. строгая типизация;

2. компиляция через компиляторы языков C/C#/Java (можно еще добавить Erlang) и соответствующая скорость (http://adventuresinmercury.blogspot.ru/search/label/Benchmarks Game) по сравнению с тем же swi prolog который тогда даже компилироваться нормально не умел;

3. как следствие, удобный foreign language interface:

:- func sin(float) = float. :- pragma foreign_proc(«C», sin(X::in) = (Sin::out), [may_call_mercury], «Sin = sin(X);»).

Если нужно заюзать что-нибудь, то обертка Mercury->C пишется довольно быстро.

4. Автоматическая параллелизация через оператор & (там же в тесте выше на adventures in mercury можно посмотреть как оно работает)

ЗЫ

Можно еще добавить небольшую фишку, в mercury можно имена предикатов и функций писать на utf-8 =)) т.е.:

:- pred 'женщина'(string::out) is multi.

'женщина'(«Елена»).

'женщина'(«Ира»).

и т.д.

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

Говоря «не по порядку» я имел в виду, что никто не гарантирует, что решения будут находиться в каком-то определённом порядке.

Пример?

:- pred get_x(int::out) is multi.

get_x(X) :- X = 2 ; X = 3.

если затем вызывать get_x(X) то в большинстве случаев X вначале будет 2, потом 3, но этого никто не гарантирует, т.к. с логической точки зрения, что X=2;X=3, что X=3;X=2 все одинаково. Тут все зависит от того как скомпилирует это компилятор mercury. У mmc на этот счет есть даже ключики --no-reorder-conj, --no-reorder-disj потому что для оптимизации он может менять порядок выражений.

Если смотреть стандартный модуль solutions то там будет так:

solutions/2 collects all the solutions to a predicate and returns them as a list in sorted order, with duplicates removed.

solutions_set/2 returns them as a set.

unsorted_solutions/2 returns them as an unsorted list with possible duplicates; since there are an infinite number of such lists, this must be called from a context in which only a single solution is required.

Operationally, however, do_while/4 will call the Filter predicate for each solution as it is obtained, rather than first building a list of all the solutions.

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

Замечательно под windows работает, можно использовать mingw или MSVC. Только нет профилирования, часть библиотек из extras только для *nix и есть проблемы с компилированием некоторого кода на уровне asm_fast, лучше использовать hlc или hlc.par тем более разницы в скорости я на собственных тестах не нашел.

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

Но прикинь на Python

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

А пока во всех языках, где сравнимая производительность (C/C++) декларации не меньше (а зачастую и больше)

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

:- func sin(float) = float. :- pragma foreign_proc(«C», sin(X::in) = (Sin::out), [may_call_mercury], «Sin = sin(X);»).

Для синуса лучше [will_not_call_mercury, promise_pure]. Тогда оптимизация лучше.

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

Уже умеет.

http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=spectralnorm

Здесь python3 выдаёт 202 секунды. Си — 2 секунды. Mercury (http://adventuresinmercury.blogspot.ru/search/label/Benchmarks Game) практически как Си.

Можешь показать бинарник на Питоне, который будет хотя бы в 2-3 раза медленнее, чем Си, а не в 100?

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

Можешь показать бинарник на Питоне

ELF? Нет, не могу. Но выше ты говорил просто о «быстром машинном коде» - Python уже давно в него компилируется JIT-компиляторами (со всеми их недостатками вроде warmup time). Если же ты не согласен ни на что, кроме статической компиляции в ELF (или PE), так и говори.

который будет хотя бы в 2-3 раза медленнее, чем Си, а не в 100?

Нет. spectralnorm медленнее в ~20 раз. Но, с другой стороны, ты и сам понимаешь, что небольшая однофайловая программа - идеальный случай для традиционного компилятора.

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

Нет. spectralnorm медленнее в ~20 раз.

Python 3 #5	= 202.54 сек
C gcc #5	= 1.98 сек

Но выше ты говорил просто о «быстром машинном коде»

Я указывал, что сравнивать Mercury c Python некорректно. Разные ниши (один динамический с JIT, другой — с семантикой C/C++).

И ограничения JIT я вполне осознаю. Хотя в той же spectralnorm есть Racket с JIT = 5.41 сек. Всего в 3 раза медленней, чем C.

Но иногда эти 3 раза существенны. И здесь остаются: C, C++, Ada, ATS, Mercury. По объёму необходимых объявлений они сравнимы (у ATS и C++ чуть меньше, у Ada и Mercury чуть больше)

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

Python 3 #5 = 202.54 сек

Python - это язык, у которого несколько реализаций. JIT есть только в PyPy - я думал, это общеизвестно.

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

Тогда уж thread_safe, will_not_modify_trail, does_not_affect_liveness, no_sharing добавить =) Но, велосипед не мой (в смысле синус), это пример из reference manual.

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

Хорошо, спасибо, про коньъюнкцию видел в секции про пролог, но дизъюнкцию не приметил.

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

Thus, to summarize, there are in fact a variety of different operational semantics for Mercury. In one of them, the strict sequential semantics, there is no nondeterminism — the behaviour is always specified exactly. ... All implementations are required to support the strict sequential semantics

unsorted_solutions/2

Ну видел, и что? Как из конткеста понять, что _unsorted_ подразумевает принципиально _unordered_.

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

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

Не знаю кто там что напел, я дал пример и объяснил почему на фразу «что никто не гарантирует, что решения будут находиться в каком-то определённом порядке».

Как из конткеста понять, что _unsorted_ подразумевает принципиально _unordered_.

А при чем тут unordered? Вопросы были:

Говорилось о функции вида multidet, у нее решения уже не по порядку?

Говоря «не по порядку» я имел в виду, что никто не гарантирует, что решения будут находиться в каком-то определённом порядке.

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

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

ЗЫ

Касательно

In one of them, the strict sequential semantics, there is no nondeterminism

то наверное лучше не брать отдельные фразы, а прочитать полностью и до конца:

The default semantics are the strict commutative semantics. Enabling ‘--no-reorder-conj’ and ‘--no-reorder-disj’ gives the strict sequential semantics.

По мне, так разница между «strict commutative semantics» и «strict sequential semantics» вполне ясная. Как и «The default semantics».

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