LINUX.ORG.RU

Вышел язык программирования Racket 7.0

 , ,


4

3

Racket - это язык программирования общего назначения, а также первая в мире экосистема для языко-ориентированного программирования.

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

Ядро версии 7.0 является результатом переработки ядра версии 6.12 более чем на 1/8, и включает новый механизм раскрытия макросов, который осуществляет бутстрэппинг самого себя. Данный механизм покрывает более 40% кода, необходимого для замены ядра Racket на Chez Scheme. Остальные 60% кода, по бОльшей части, также реализованы, но не включены в этот выпуск; мы надеемся и предполагаем, что Racket-на-Chez будет готов для промышленного использования в следующих выпусках ветки 7.x

  • Синтаксис формы (`#'`) поддерживает новые шаблоны подформ: ~@ - для сплайсинга, и ~? - для выбора между подшаблонами, основанного на возможном «отсутствии» значения у переменных образца (например, у образца ~optional в syntax-parse). Библиотека syntax/parse/experimental/template, откуда происходят эти возможности, экспортирует новые формы под старыми именами для совместимости.
  • На Windows флаг --embed-dlls команды raco exe создаёт по-настоящему автономный исполняемый файл ".exe", который содержит в себе разделяемые библиотеки Racket.
  • Опция «Create Executable» интегрированной среды разработки DrRacket для учебных языков (Beginner Student, и т.п.) использует флаг --embed-dlls на Windows.
  • Поддержка prefab («previously fabricated») структур в Typed Racket существенно улучшена, что делает их более полиморфными, исправляя, вместе с тем, существенные ошибки текущей реализации. Программы, которые сейчас используют предикаты для prefab-структур неизвестных данных, могут нуждаться в ревизии, т.к. предыдущие версии Typed Racket позволяли программам с потенциальными ошибками осуществлять проверку типов. Смотрите Typed Racket RFC 1 и prefab-changes для более подробной информации об этом изменении, и о том, как исправить программы, которые подверглись влиянию в связи с этим изменением.
  • Typed Racket поддерживает #:rest-star в конструкторе типов ->*, что позволяет функциональным типам указывать в хвостовом списке аргументов (rest arguments) более сложные образцы типов, такие как функция hash.
  • Интерактивные оверлеи могут быть наложены на графики, созданные с помощью plot-snip. Это позволяет создавать интерактивные графики или отображать дополнительную информацию, когда указатель мыши находится над областью графика. Примеры использования данной возможности можно посмотреть тут.
  • racket/plot предоставляет процедуры для отображения графиков японских свечей (candlestick charts), которые могут быть использованы в финансовом анализе временных рядов.
  • Добавлен contract-equivalent?, который проверяет, что два контракта являются взаимосильными, без экспоненциального замедления, которое имеет место в случае двух вызовов contract-stronger?.
  • Lazy Racket поддерживает функции с именованными аргументами.

>>> Оригинал



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

В следующем семестре тебе может быть даже расскажут как, если ты пересдашь весеннюю сессию осенью.

Одна из вещей которым я наиболее рад в жизни это то что в моем универе С++ закончился не начавшись. Но я понимаю что не всем повезло так же как мне.

Так что я признаю что почти не знаю его, а ты давай покажи как вызвать компилятор в рантайме.

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

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

Запустить при работе парсер и компилятор можно из любого языка. А на стадии компиляции ребол может компилировать другой синтаксис? В примере на Racket программа на brainfuck компилируется в нормальный бинарник.

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

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

Простой вариант: system(«g++ ...»). Ну или любой другой компилятор также.

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

Простой вариант: system(«g++ ...»). Ну или любой другой компилятор также

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

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

А на стадии компиляции ребол может компилировать другой синтаксис?

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

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

Угадай, почему поломается при использовании.

Эм, чему там ломаться? https://ideone.com/6TXtD1

Из-за call-next-mathod — нет, а из-за defmethod очень часто.

Ну это даже не буратинизм, просто невладение инструментом. Если наследуешься и не используешь комбинаторы методов или по-просту не вызываешь родительский метод, то, значит, и не ожидаешь поведения, определенного для объектов класса ‹a›. Ну или нужно было определить порядок значимости аргументов: https://ideone.com/CelIBd

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

Угадай, почему поломается при использовании.

Почему? Потому что aif не часть CL и криво реализован?

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

может внезапно поломаться, так как iter экспортирует next, если lib:foo его использует при раскрытии, то кирдык.

Если это ломается, значит ты фигачишь этот labels в пакете, который юзает iter. Ты используешь iter в пакете, значит ты знаешь зачем тебе iter и что он тебе даёт и ты суёшь next оттуда в labels и после этого ломается ВНЕЗАПНО?

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

Упс. Расширение не работает для объектов b.

(defclass a () ())

(defclass spec () ())

(defgeneric foo (a r))

(defmethod foo ((a a) r)
  (write-line "Hello world!"))

(defmethod foo ((a a) (r spec))
  (write-line "Привет мир!"))


(defclass b (a) ())

(defmethod foo ((b b) r)
  (write-line "Hello world 2!"))
ATEST> (foo (make-instance 'a)
            t)
Hello world!
"Hello world!"
ATEST> (foo (make-instance 'a)
            (make-instance 'spec))
Привет мир!
"Привет мир!"
ATEST> (foo (make-instance 'b)
            (make-instance 'spec))
Hello world 2!
"Hello world 2!"
ATEST> (foo (make-instance 'b)
            t)
Hello world 2!
"Hello world 2!"
ATEST> (defmethod foo ((b b) r)
         (write-line "Hello world 2!")
         (call-next-method))
WARNING:
   redefining FOO (#<STANDARD-CLASS ATEST::B>
                   #<SB-PCL:SYSTEM-CLASS COMMON-LISP:T>) in DEFMETHOD
#<STANDARD-METHOD ATEST::FOO (B T) {1003E98273}>
ATEST> (foo (make-instance 'b)
            t)
Hello world 2!
Hello world!
"Hello world!"
ATEST> (foo (make-instance 'b)
            (make-instance 'spec))
Hello world 2!
Привет мир!
"Привет мир!"
ATEST> 

Что не так?

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

какова вероятность что у пользователя установлен g++ или компилятор вобще

Если у пользователя не установлен ребол, то программа не только компилятор не запустит, но и вообще не запустится. Так что компилятор в обоих случаях предполагается существующим в системе.

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

Эм, чему там ломаться? https://ideone.com/6TXtD1

(aif (get-data) (fwrite t it)) напечатает t, а не ожидаемый результат (get-data).

Если наследуешься и не используешь комбинаторы методов или по-просту не вызываешь родительский метод, то, значит, и не ожидаешь поведения, определенного для объектов класса ‹a›.

ОК. Это фича, а не баг

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

Ты используешь iter в пакете, значит ты знаешь зачем тебе iter и что он тебе даёт и ты суёшь next оттуда в labels и после этого ломается ВНЕЗАПНО?

То есть, если я использую iter, то не имею права локально использовать даже те имена, которые не используются в моей программе. Я про это и говорю. Из-за этого достаточно неудобно использовать локальные функции. Кроме того, обновление библиотеки, расширяющее интерфейс становится несовместимым со старой версией.

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

Потому что aif не часть CL и криво реализован?

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

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

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

Да. Например, FreePascal. Без шуток. Не понимаю, почему к нему такое негативное отношение?

Вот, например, посмотрите этот редактор текста написанный в Lazarus — CudaText. Лучший, опенсорсный аналог SublimeText. http://uvviewsoft.com/cudatext/

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

На нём можно gui-программы писать? Можно минимальный пример?

https://docs.racket-lang.org/gui/
Пример:

; Make a frame by instantiating the frame% class
(define frame (new frame% [label "Example"]))
 
; Make a static text message in the frame
(define msg (new message% [parent frame]
                          [label "No events so far..."]))
 
; Make a button in the frame
(new button% [parent frame]
             [label "Click Me"]
             ; Callback procedure for a button click:
             [callback (lambda (button event)
                         (send msg set-label "Button click"))])
 
; Show the frame by calling its show method
(send frame show #t)

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

Да просто ппц как всё понятно стало, теперь фронтендеры просто толпами ломануться вписывать «send/suspend/dispatch response-generator'ы»

После этого кто-то ещё говорит, что perl непонятен.

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

Да. Например, FreePascal. Без шуток. Не понимаю, почему к нему такое негативное отношение?

Это проблема поколений. Новое поколение не хочет писать на том, на чём писало предыдущее. Я, например, обнаружил, что FreeBASIC уделывает NodeJS в несколько раз по скорости вычислений, а если учесть полную поддержку встраивания в него Си и Ассемблера - может уделать и в 10-15-ть раз. Но да, Node'а «не говно мамонта», а fbc - якобы говно мамонта. Тот факт, что и там, и там можно писать программы для любых применений - мало кому интересен.

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

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

Спасибо :-)

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

Да просто ппц как всё понятно стало, теперь фронтендеры просто толпами ломануться вписывать «send/suspend/dispatch response-generator'ы»

Фронтендеры будут писать свои render-post.html, render-blog-page.html и т.д. Зачем им код движка?

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

Это и есть то самое неоспоримое преимущесиво lisp-1 над lisp-n?

Ага. Реальное преимущество видно, когда пишешь

(define frame (new (add-std-commands (add-border frame%)) 
                   [label «Example»]))

Вот как будешь делать такое в lisp-n?

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

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

Это неправда, ребол умеет паковать себя в бинарь вместе с кодом твоей программы, это называется encapping. Бинарь ребола (весь рантайм и интерпретатор) это всего 1 мегабайт - поэтому никаких проблем с этим нет.

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

Мне нужно быть в теме, чтобы запустить редактор?

«Паскаль говно, и я даже читать не буду»

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

(aif (get-data) (fwrite t it)) напечатает t, а не ожидаемый результат (get-data).

Опять почему неожидаемый? Вот смысл макроса aif понятен - он загрязняет формы понятием it. Сделано это ради удобства. А вот какой смысл макроса fwrite?

(defmacro fwrite (stream x)
  `(aif ,stream (format it "~a" ,x) nil))

Этим кодом ты говоришь лиспу: понимай в коде fwrite понятие it подобно aif. Это тоже сделано ради удобства? Тогда почему результат (aif (get-data) (fwrite t it)) для тебя неожидаем?

Если мы ожидаем в результате напечатать именно (get-data), значит у макроса совсем другой смысл и он не должен на свой код распространять понятие it, раскрывая из себя aif.

(defmacro fwrite (stream x)
  (alexandria:once-only (x)
    `(aif ,stream (format it "~a" ,x) nil)))

Я конечно согласен в том что CL заслуживает некоторой критики за свои несовершенства, но в данном случае я на стороне CL.

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

(alexandria:once-only (x)

Тоже неправильно. (fwrite nil (do-something-dangerous)) не должен ничего выполнять, а у тебя сначала выполнится (do-something-dangerous), а потом проверится условие.

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

Вот смысл макроса aif понятен - он загрязняет формы понятием it. Сделано это ради удобства.

И получается, что в макросах CL нельзя пользоваться анафорическими макросами. И вообще любыми формами, меняющими контекст (например, тем же iterate или tagbody). А всем остальным нельзя определять локально функции, имена которых совпадают с функциями, которые импортированы откуда либо. Причём все импортированные функции надо помнить наизусть. Компилятор предупреждение выдаст только для CL.

В Racket таких проблем с именами нет вообще. Я могу в модуле создать функцию list и гарантированно ничего не сломается. Если я пишу (require foo), то меня интересуют только те имена, которые я из этого foo буду использовать. Если вдруг два модуля экспортируют одинаковое имя, то мне придётся либо выбрать из них одно, либо переименовать одно из них при импорте (кстати, этого тоже не хватает в CL), но даже в этом случае я увижу ошибку сразу при require, а не когда у меня сломается случайный библиотечный макрос.

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

Хороший порошок, для ручной стирки всегда его беру.

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

Ну как-то так. mix отсюда

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

Кроме того, (add-border (add-border frame%)) сделать можно (и получить окно с двумя рамками), а в mix такое уже никак.

Фактически, разница та же, что между указателями на функцию в Си и Лиспе. В Лиспе делается легко compose или curry, в Си можно вернуть только указатель на уже существующую функцию.

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