LINUX.ORG.RU

Кто хотел лисп, компилирующийся в C++?

 , ,


0

3

Нашёл на просторах Интернета: https://bitbucket.org/ktg/l/src/337c13802c5e?at=master

Умеет макросы

(define-syntax sum
  (syntax-rules ()
    [(sum) 0]
    [(sum a) a]
    [(sum a b) (+ a b)]
    [(sum a b ...) (+ a (sum b ...))]))

(define-syntax-rule (infix a op b) (op a b))

(define-syntax-rule (ret a) (return a))

(defmacro unless (pred a b)
  `(if (not ,pred) ,a ,b))

(main
  (prn (sum 1 2 3 4))
  (prn (infix 1 + 2))
  (unless false (prn "Will print") (prn "Will not print"))
  (ret 1))

Примеры смотреть в https://bitbucket.org/ktg/l/src/337c13802c5e/ex/?at=master

Хвалите и критикуйте!

★★★★★

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

там не NULL, а пустой список

Правильно, а тип пустого списка - это Null. И не важно какие элементы в списке - Null является подтипом (Listof a) для любого а.

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

А то люди стараются, но на C работает 0.74 секунды, а на SBCL 2.71. про остальные и говорить нечего...

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

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

С какого лешего это он динамичный? Это ж не javascript и не педон

Хренак! То есть про REPL ты не слышал?

особенно если это Схема.

Ну это их проблемы

esandmann
()
Ответ на: комментарий от Kuzy
(: a (String -> (Listof String)))
(define (a x)
  (cons "x" (cdr (list x))))

(define (b x)
  (cons "x" (cdr (list x x))))

(define (c x)
  (cons "x" (cdr (list x))))

;;;; --------------------------------

> a
- : (String -> (Listof String))
#<procedure:a>
> b
- : (Any -> (Listof Any))
#<procedure:b>
> c
- : (Any -> (Listof String))
#<procedure:c>
> (a 1)
. Type Checker: Expected String, but got One in: 1
> (b 1)
- : (Listof Any)
'("x" 1)
> (c 1)
- : (Listof String)
'("x")
> cdr
- : (All (a b) (case-> ((Pairof a b) -> b) ((Listof a) -> (Listof a))))
#<procedure:cdr>
> '()
- : (Listof Any) [more precisely: Null]
'()
korvin_ ★★★★★
()
Последнее исправление: korvin_ (всего исправлений: 2)
Ответ на: комментарий от anonymous

для этого можно считать типом пустого списка не Null, а подтип Null. Какой-нибудь IntNull, например. Тогда и возможность конструирования «из нуля» сохранится, и типизация останется. А еще можно сделать несколько разных Null'ов (Null, null, Nil, Nothing, None, Unit :)))

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

> для этого можно считать типом пустого списка не Null, а подтип Null. Какой-нибудь IntNull, например.

Для чего?

и типизация останется.

Она и так остается. '() - это объект типа Null, Null - подтип типов всех списков. Операция добавления любого элемента к '() абсолютно безопасна (если компилтор может гарантировать, что список пуст, то есть терм имеет тип Null), так почему бы ее не выполнить?

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

(если компилтор может гарантировать, что список пуст, то есть терм имеет тип Null), так почему бы ее не выполнить?

потому что в памяти этот список - это какой-нибудь буфер с фиксированным размером. Рантайм от этого буфера распростраяняет ссылки на переиспользованные области, и анонсирует полностью зачищенные области (для которых доказано, что в текущем состоянии системы там нет данных, с которыми можно легально ассоциировать объект языка). Допустим, там буфер из непрерывно размещенных в памяти интов на два гигабайта размером. И тут ты такой пришел, и говоришь, а ну-ка поменяй тип на стринги. Оптимизатор такой, ептыыыть какая жопа случилась - размер референсов на стринги отличается от размера интов! Переразмечать этот буфер уже не имеет смысла, нужно делать новый. А со старым что делать? А тут еще приехало известие, что у нас памяти всего два гига, и если мы сейчас что-то добавим, то это засвопится и станет тормозить. И от этого кошмара можно легко избавиться просто запретив нетипизированные нули. Гдеянеправ?

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

А можно определить свою иерархию?

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

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

в памяти этот список - это какой-нибудь буфер с фиксированным размером.

Ты список с массивом не путай. Список — это всего лишь cons-ячейка. А пустой список вообще константа (пустой указатель).

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

компилятор/рантайм писать проще, не? Вместо дочерта кода, предполагающего что буфер одного типа может стать буфером другого типа, не написали ничего, ну и... всё. Нету тела - нету дела. Ну то есть это нарушает стандарт, ну и посрать. В C++ тоже не все фичи шаблонов реализовали, никто не умер.

А может у меня просто горячечный бред. Нужно подумать ещё.

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

потому что в памяти этот список - это какой-нибудь буфер с фиксированным размером.

В памяти - это ссылка не специальную пару. Нету там никаких буферов и чего ты там еще себе понавыдумывал. Все '() ссылаются на одно и то же место.

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

Ну то есть это нарушает стандарт, ну и посрать.

Какой стандарт это нарушает? ТЫ о чем вообще?

А может у меня просто горячечный бред.

Видимо так.

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

В памяти - это ссылка не специальную пару.

это в идеале так, а в целях ускорения - разве нельзя «разгладить» список в буфер непрерывных интов?

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

разве нельзя «разгладить» список в буфер непрерывных интов

Можно. Для этого его достаточно назвать Vector :-)

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

это в идеале так, а в целях ускорения - разве нельзя «разгладить» список в буфер непрерывных интов?

Для какого ускорения? Списки предназначены для того, чтобы можно было делать быстрый cons/car/cdr, что у тебя ускорится, если ты что-то там разгладишь? Только медленнее станет.

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

допустим у нас есть некий набор интов, тогда их можно представить как буфер в памяти, плюс координаты этого набора внутри буфера (указатель на начало и указатель на конец, или указатель на начало и смещение). Простая структура (*fist, *last). Всё что ты написал - берется за одну инструкцию вообще, например чтобы получить хвост - нужно увеличить first на sizeof(int). Что тут медленней станет?

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

почему сразу linked list? когда статистика показывает, что пользователь в основном использует контейнер для random access, в бэкенде выбирается реализация через вектор, а если в основном для итерирования - через linked list. Да и не liked list там, а совсем другая конструкция.

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

Простая структура (*fist, *last). Всё что ты написал - берется за одну инструкцию вообще, например чтобы получить хвост - нужно увеличить first на sizeof(int). Что тут медленней станет?

Что тут медленней станет?

http://en.wikipedia.org/wiki/Linked_list#Linked_lists_vs._dynamic_arrays

Медленнее станет вставка и удаление.

что пользователь в основном использует контейнер для random access

использовать linked list для random access

ССЗБ

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

Да и не liked list там, а совсем другая конструкция.

Сравнивал эту другую конструкцию с динамическим массивом?

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

Я не понимаю, что ты хочешь сказать.

Мы с аноном спорили на ту тему, всё ли там сделано парами (позиция анона), или в некоторых случаях соптимизировано в мутабельные буферы.

Учитывая что данные поделия не тормозят, я уверен, что в бэкенде неявно и в стандартной библиотеке явно используются мутабельные буферы, написанные на Си, которые выдают наружу списочный интерфейс. Поэтому логично иметь максимальную статичность всего кода. И мне кажется, в таком раскладе разработчику бэкенда будет проще иметь типизированные Null'ы, чем не иметь их.

Хотя я наверное неправ, и нужно прекращать дискуссию. И вместо этого пойти и написать вот это всё.

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

Я имею ввиду как ты представляешь «сделать собственную иерархия»? Как это например должно выглядеть? Можно делать структуры классы (с-но со структурами подклассами). Можно делать refinement-типы для предикатов фильтров (правда оно пока experimental багует для нетривиальных фильтров).

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

Да, Any - это супертип над всеми типами.

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

почему сразу linked list? когда статистика показывает, что пользователь в основном использует контейнер для random access

Но списки используются не для random access, а для cons/car/cdr. Для random access используют вектора.

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

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

Нет. Список - это список. Он гарантирует константный cons/car/cdr, по стандарту языка.

Учитывая что данные поделия не тормозят

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

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

Для списка int-ов не актуально, когда делают список int-ов, обычно хотят получить список int-ов (не массив).

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

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

потмоу что нормальные люди

а если использователь языка - криворукий лошара?

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

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

а если использователь языка - криворукий лошара?

Тогда у него будет тормозить.

Ну то есть это реальная проблема

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

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

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

И что эти люди забыли в программировании?

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

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

Тогда для тебя picolisp. Там есть только списки символы и числа,

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

Не развеял, я не могу сказать что мой тип T подтип Integer. При этом, он по дефолту подтип Any.

И что, собственно? Любой тип - подтип Any.

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

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

При этом, он по дефолту подтип Any.

Как это вообще связано друг с другом?

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

я не могу сказать что мой тип T подтип Integer.

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

При этом, он по дефолту подтип Any

Any — тип, который содержит все значения.

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

Всмысле? Я не предъявлял никаких претензий. Ты сказал что это не магия. Ну так покажи мне как задефайнить свой тип MyAny с теми же свойствами что и Any.

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

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

Ну на самом деле сейчас не получится определять подтипы по предикаты, т.к. refinement сломаны:

(: integer>5? (Any -> Boolean : #:+ Integer))

(define (integer>5? x)
  (and (exact-integer? x) (> x 5)))

(declare-refinement integer>5?)

. Type Checker: type mismatch;
 mismatch in filter
  expected: (((Refinement Any integer>5?) @ x) | (! (Refinement Any integer>5?) @ x))
  given: ((Positive-Integer @ x) | Top) in: (and (exact-integer? x) (> x 5))

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

Ну так покажи мне как задефайнить свой тип MyAny с теми же свойствами что и Any.

Покажи как задефайнить в любом статически типизированном ЯП свой MyInteger с теми же свойствами, что Integer.

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

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

Это будет надтип.

Не, это будет подтип:

(define-type yoba (U 1 2 3 4 5))

(: my-+ (yoba yoba -> Integer))
(define (my-+ x y)
  (+ x y))

(: my-id (yoba -> yoba))
(define (my-id x) x)

->
> (my-+ 1 2)
- : Integer
3
> (my-+ 1 6)
. Type Checker: type mismatch
  expected: yoba
  given: Positive-Byte in: 6
> (my-id 5)
- : Integer [more precisely: yoba]
5
> (+ (my-id 5) 1)
- : Integer [more precisely: Positive-Index]
6
> 

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