LINUX.ORG.RU

Какой Lisp лучше в каких случаях и почему? И вообще в чём принципиальна разница между ними.

 , , ,


3

6

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

Сабж.

Deleted

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

А Питман говорит что не называется.

Он сам не знает чего хочет.

The whole point of unwind-protect is to assure that files do get closed when a specific dynamic contour is exited.

The purpose of dynamic-wind is to taken action on every entry and every exit to a dynamic contour.

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

К слову, без замыканий тоже можно сказать, что unwind-protect работает неправильно:

(defvar f nil)
(with-open-file (s p)
   (setf f (lambda () (format s "~a" 'fail))))
(funcall f) ;; unwind-protect уже закрыл файл, а мы его пишем

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

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

Тогда придётся либо использовать только функции из CL

Непонял, почему это?

;; библиотека

(defun f (x) (* x 2))

(defmacro m2 (x) `(f ,x))

;; пользователь библиотеки

(let ((x 4))
  (flet ((f (x) (+ x 3))
    (+ (f 2) (m2 2))))
;; ожидает (2+3)+(2*2) = 9, а получает 10
monk ★★★★★
()
Ответ на: комментарий от monk

К слову, без замыканий тоже можно сказать, что unwind-protect работает неправильно:

Интересно, я не думал об этом.

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

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

;; ожидает (2+3)+(2*2) = 9, а получает 10

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

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

Я не против ни за их наличие, я лишь говорю что чем больше это встроено тем сложнее менять.

В общем-то нет. Вот был в Delphi встроенный string. Это не мешало использовать PChar, когда потребовалось.

Также есть https://docs.racket-lang.org/compatibility/defmacro.html с макросами «как в CL».

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

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

То есть, что наличие гигиены лучше, чем её отсутствие, ты согласен? Так-то, правила для макросов просты: не используй в теле экспортные символы не из CL.

Также приходится постоянно помнить, что перед заливкой в git надо удалить все fasl, пересобрать и заново запустить все тесты. Так как работа в образе не идентична работе с нуля. Например, мог случайно удалить функцию, которая где-то используется. Но пока не пересоберёшь заново, в образе функция будет и будет работать. Компиляция макроса может работать при load и не работать при compile. В общем, мелочей, которые матёрый лиспер обязан знать почти столько же, сколько у C++.

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

Я спрашивал про уровень CL, от которого ракетчики оттолкнулись. Как же те умозаключения что если разработчик лезет в дебаггер то он не знает что разрабатывает и то что он по большей части патчит образ то чаще всего у него код проекта в целом превращается в УГ? Разве это не наложило некоторые ограничения на ракету как на реализацию?

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

Как же те умозаключения что если разработчик лезет в дебаггер то он не знает что разрабатывает и то что он по большей части патчит образ то чаще всего у него код проекта в целом превращается в УГ?

Поэтому стандартный гораздо менее удобный, чем в SBCL.

Разве это не наложило некоторые ограничения на ракету как на реализацию?

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

Поэтому там есть примитивы для реализации любых инструментальных средств (IDE, отладчик, профилировщик), изменяемые списки, racket/load и swindle.

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

в т.ч. биндинг к ЖВМ, привет клоужуристам

А вот да, как насчет биндингов к jvm в других реализациях? Или как насчет годной либы?

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

Так на racket-lang.org в разделе community всё перечислено.

monk ★★★★★
()

Ребят, а пните как правильно компилировать scheme/guile что-бы делать просто бинарник,исполняемый файл. В ракете drraсket собирает бинарник и суёт всё в zip архив распаковываю запускаю и всё ок, а вот с guile как? Делаю guild compile example.ss . Оно делает мне example.go, но его запустить нельзя. Я что-то туплю.

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

Ни racket, ни guile, по сути, не компилируют в нативный код. Racket просто умеет паковать интерпретатор вместе с интерпретируемым кодом (и даже с нужными либами, емнип). Guile из коробки, насколько я знаю, такого не умеет.

Делаю guild compile example.ss

Это компиляция в байт-код. Guile любой исходный код перед исполнением автоматически компилирует в байт-код (ну или ищет уже закешированный файл, откомпиленный ранее). guild compile нужен если зачем-то понадобилось накомпилять байт-код заранее. Для исполнения байт-кода, естественно, по-прежнему нужен guile (конкретнее та его часть, которая виртуальная машина).

Оно делает мне example.go, но его запустить нельзя.

Это и есть файл с байт-кодом. Кстати, не нашёл сходу как его запустить на выполнение не имея исходного кода.

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

Оно делает мне example.go, но его запустить нельзя.

Это и есть файл с байт-кодом. Кстати, не нашёл сходу как его запустить на выполнение не имея исходного кода.

В схеме всё настолько плохо? Например, Питон спокойно выполняет файлы с байткодом без исходников.

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

В схеме всё настолько плохо? Например, Питон спокойно выполняет файлы с байткодом без исходников.

  1. linux-org-ru спрашивал, а я отвечал не про язык scheme, а про его реализацию guile. Так-то для схемы и компиляторы в нативный код есть.
  2. Не вижу ничего плохого в невозможности выполнять байт-код без исходников.
  3. И наконец, я же не написал «нету». Просто бегло проглядев документацию, я такой возможности сходу не увидел. Вероятно, тем не менее, что она есть. Просто никому особо не нужна, вот и не висит в доках на видном месте.
anonymous
()
Ответ на: комментарий от Virtuos86

А да, забыл.

4. Питон — говно.

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

1. Да, я имел в виду конкретно Guile, а не все сорта Скима во вселенной.
2. Виртуальная машина всё равно выполняет именно байткод. Если необходимости лезть в исходники нет, а подразумевается только использование, то зачем таскать по сути лишний хлам?
4. Лисп тоже, только вдобавок еще и никому не нужен.

Virtuos86 ★★★★★
()

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

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

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

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

Похоже это не оригинал сообщения, а переведено с какого-то языка через google-translate, по крайней мере София мне на это намекает (Софька - это моя нейросетка домашняя, науськалась переведённый текст почты читать гуглотранслейтовый, сказала что эвкристика похожа на переведёнку), хотя она у меня дурёха ещё, мож чё напутала... как всегда :D

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

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

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

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

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

Ни racket, ни guile, по сути, не компилируют в нативный код.

А существует ли scheme, которая компилирует в нативный код? Или call/cc не позволяет?

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

ChezScheme умеет из ss делать so либу с машкодом которую можно вроде как запустить через petite какой-то https://www.scheme.com/csug8/use.html#g13

Вроде как Гамбит умеет в машкод http://gambitscheme.org/wiki/index.php/Main_Page

P.S. Сам ещё не пробовал.

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

можно вроде как запустить через petite какой-то

Там же написано, что petite - это интерпретатор Scheme.

Вроде как Гамбит умеет в машкод http://gambitscheme.org/wiki/index.php/Main_Page

Точно, умеет.

P.S. Но код .с, который он создаёт - это что-то.

monk ★★★★★
()
Ответ на: call/cc от Deleted

что это за зверь неведомый?

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

Хорошее описание вот: https://stackoverflow.com/questions/22888722/could-someone-explain-call-cc-in...

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

Позволяет тривиально реализовывать goto, корутины, зелёные потоки, веб сервера с сохранением состояния между страницами...

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

Скорее фундаментальная как я понимаю.

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

Для библиотек полезная. В непосредственном применении в 90% это замена goto из C (выход из цикла, особенно вложенного) или longjmp из C.

В общем, нужна редко, но когда нужна, заменить нечем.

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

Проблема именно call/cc в том, что она тривиально решается на уровне байткодов (примерно так: https://norvig.com/paip/interp3.lisp), так как интерпретатор байткода всё равно хранит состояние. А при компиляции в машинный код приходится либо это состояние записывать в явном виде на каждую операцию Scheme, либо надо явно закладываться на ассемблер, что он умеет копировать стек и получить адрес текущей инструкции (Си не умеет, x86 умеет).

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

как тогда в гамбите смогли?

$ cat test.scm
(define (main)
  (when (> 2 1)
    (display "Hello, world")))

(main)

$ gsc -c test.scm
$ cat test.c
#ifdef ___LINKER_INFO
; File: "test.c", produced by Gambit v4.8.8
(
408008
(C)
"test"
(("test"))
(
"test"
)
(
)
(
" test"
"main"
)
(
)
(
">"
"display"
"when"
)
 ()
)
#else
#define ___VERSION 408008
#define ___MODULE_NAME "test"
#define ___LINKER_ID ____20_test
#define ___MH_PROC ___H__20_test
#define ___SCRIPT_LINE 0
#define ___SYMCOUNT 1
#define ___GLOCOUNT 5
#define ___SUPCOUNT 2
#define ___SUBCOUNT 2
#define ___LBLCOUNT 10
#define ___MODDESCR ___REF_SUB(1)
#include "gambit.h"

___NEED_SYM(___S_test)

___NEED_GLO(___G__20_test)
___NEED_GLO(___G__3e_)
___NEED_GLO(___G_display)
___NEED_GLO(___G_main)
___NEED_GLO(___G_when)

___BEGIN_SYM
___DEF_SYM(0,___S_test,"test")
___END_SYM

#define ___SYM_test ___SYM(0,___S_test)

___BEGIN_GLO
___DEF_GLO(0," test")
___DEF_GLO(1,"main")
___DEF_GLO(2,">")
___DEF_GLO(3,"display")
___DEF_GLO(4,"when")
___END_GLO

#define ___GLO__20_test ___GLO(0,___G__20_test)
#define ___PRM__20_test ___PRM(0,___G__20_test)
#define ___GLO_main ___GLO(1,___G_main)
#define ___PRM_main ___PRM(1,___G_main)
#define ___GLO__3e_ ___GLO(2,___G__3e_)
#define ___PRM__3e_ ___PRM(2,___G__3e_)
#define ___GLO_display ___GLO(3,___G_display)
#define ___PRM_display ___PRM(3,___G_display)
#define ___GLO_when ___GLO(4,___G_when)
#define ___PRM_when ___PRM(4,___G_when)

___DEF_SUB_STR(___X0,12UL)
               ___STR8(72,101,108,108,111,44,32,119)
               ___STR4(111,114,108,100)
___DEF_SUB_VEC(___X1,5UL)
               ___VEC1(___REF_SYM(0,___S_test))
               ___VEC1(___REF_PRC(1))
               ___VEC1(___REF_FIX(1))
               ___VEC1(___REF_NUL)
               ___VEC1(___REF_FAL)
               ___VEC0

___BEGIN_SUB
 ___DEF_SUB(___X0)
,___DEF_SUB(___X1)
___END_SUB



#undef ___MD_ALL
#define ___MD_ALL ___D_FP ___D_R0 ___D_R1 ___D_R2 ___D_R4
#undef ___MR_ALL
#define ___MR_ALL ___R_FP ___R_R0 ___R_R1 ___R_R2 ___R_R4
#undef ___MW_ALL
#define ___MW_ALL ___W_FP ___W_R0 ___W_R1 ___W_R2 ___W_R4
___BEGIN_M_COD
___BEGIN_M_HLBL
___DEF_M_HLBL_INTRO
___DEF_M_HLBL(___L0__20_test)
___DEF_M_HLBL(___L1__20_test)
___DEF_M_HLBL_INTRO
___DEF_M_HLBL(___L0_main)
___DEF_M_HLBL(___L1_main)
___DEF_M_HLBL(___L2_main)
___DEF_M_HLBL(___L3_main)
___DEF_M_HLBL(___L4_main)
___DEF_M_HLBL(___L5_main)
___END_M_HLBL

___BEGIN_M_SW

#undef ___PH_PROC
#define ___PH_PROC ___H__20_test
#undef ___PH_LBL0
#define ___PH_LBL0 1
#undef ___PD_ALL
#define ___PD_ALL ___D_FP ___D_R4
#undef ___PR_ALL
#define ___PR_ALL ___R_FP ___R_R4
#undef ___PW_ALL
#define ___PW_ALL ___W_R4
___BEGIN_P_COD
___BEGIN_P_HLBL
___DEF_P_HLBL_INTRO
___DEF_P_HLBL(___L0__20_test)
___DEF_P_HLBL(___L1__20_test)
___END_P_HLBL
___BEGIN_P_SW
___DEF_SLBL(0,___L0__20_test)
   ___IF_NARGS_EQ(0,___NOTHING)
   ___WRONG_NARGS(0,0,0,0)
___DEF_GLBL(___L__20_test)
   ___SET_GLO(1,___G_main,___PRC(4))
   ___POLL(1)
___DEF_SLBL(1,___L1__20_test)
   ___JUMPGLOSAFE(___SET_NARGS(0),1,___G_main)
___END_P_SW
___END_P_COD

#undef ___PH_PROC
#define ___PH_PROC ___H_main
#undef ___PH_LBL0
#define ___PH_LBL0 4
#undef ___PD_ALL
#define ___PD_ALL ___D_FP ___D_R0 ___D_R1 ___D_R2 ___D_R4
#undef ___PR_ALL
#define ___PR_ALL ___R_FP ___R_R0 ___R_R1 ___R_R2 ___R_R4
#undef ___PW_ALL
#define ___PW_ALL ___W_FP ___W_R0 ___W_R1 ___W_R2 ___W_R4
___BEGIN_P_COD
___BEGIN_P_HLBL
___DEF_P_HLBL_INTRO
___DEF_P_HLBL(___L0_main)
___DEF_P_HLBL(___L1_main)
___DEF_P_HLBL(___L2_main)
___DEF_P_HLBL(___L3_main)
___DEF_P_HLBL(___L4_main)
___DEF_P_HLBL(___L5_main)
___END_P_HLBL
___BEGIN_P_SW
___DEF_SLBL(0,___L0_main)
   ___IF_NARGS_EQ(0,___NOTHING)
   ___WRONG_NARGS(0,0,0,0)
___DEF_GLBL(___L_main)
   ___IF(___NOT(___EQP(___GLO__3e_,___PRM__3e_)))
   ___GOTO(___L7_main)
   ___END_IF
   ___SET_R1(___TRU)
   ___GOTO(___L6_main)
___DEF_SLBL(1,___L1_main)
   ___SET_R0(___STK(-3))
   ___ADJFP(-4)
___DEF_GLBL(___L6_main)
   ___SET_STK(1,___R1)
   ___SET_STK(2,___R0)
   ___SET_R1(___SUB(0))
   ___SET_R0(___LBL(3))
   ___ADJFP(8)
   ___POLL(2)
___DEF_SLBL(2,___L2_main)
   ___JUMPGLOSAFE(___SET_NARGS(1),3,___G_display)
___DEF_SLBL(3,___L3_main)
   ___SET_R2(___R1)
   ___SET_R0(___STK(-6))
   ___SET_R1(___STK(-7))
   ___POLL(4)
___DEF_SLBL(4,___L4_main)
   ___ADJFP(-8)
   ___JUMPGLOSAFE(___SET_NARGS(2),4,___G_when)
___DEF_GLBL(___L7_main)
   ___SET_STK(1,___R0)
   ___SET_R2(___FIX(1L))
   ___SET_R1(___FIX(2L))
   ___SET_R0(___LBL(1))
   ___ADJFP(4)
   ___POLL(5)
___DEF_SLBL(5,___L5_main)
   ___JUMPGLOSAFE(___SET_NARGS(2),2,___G__3e_)
___END_P_SW
___END_P_COD

___END_M_SW
___END_M_COD

___BEGIN_LBL
 ___DEF_LBL_INTRO(___H__20_test," test",___REF_FAL,2,0)
,___DEF_LBL_PROC(___H__20_test,0,-1)
,___DEF_LBL_RET(___H__20_test,___IFD(___RETI,0,0,0x3fL))
,___DEF_LBL_INTRO(___H_main,0,___REF_FAL,6,0)
,___DEF_LBL_PROC(___H_main,0,-1)
,___DEF_LBL_RET(___H_main,___IFD(___RETN,1,0,0x1L))
,___DEF_LBL_RET(___H_main,___IFD(___RETI,8,1,0x3f03L))
,___DEF_LBL_RET(___H_main,___IFD(___RETN,5,1,0x3L))
,___DEF_LBL_RET(___H_main,___IFD(___RETI,8,8,0x3f01L))
,___DEF_LBL_RET(___H_main,___IFD(___RETI,4,0,0x3f1L))
___END_LBL

___BEGIN_MOD_PRM
___DEF_MOD_PRM(0,___G__20_test,1)
___END_MOD_PRM

___BEGIN_MOD_C_INIT
___END_MOD_C_INIT

___BEGIN_MOD_GLO
___DEF_MOD_GLO(0,___G__20_test,1)
___END_MOD_GLO

___BEGIN_MOD_SYM_KEY
___DEF_MOD_SYM(0,___S_test,"test")
___END_MOD_SYM_KEY

#endif

Там почти байткод.

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

А существует ли scheme, которая компилирует в нативный код?

Кроме gambit'а, ещё chicken и bigloo. Это из относительно популярных, наверняка ещё есть/были.

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

Bigloo скорее на равных. Вот, кстати, stalin ещё вспомнился из компиляторов, в бенчах есть.

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

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

Скорость на ext2 хорошая в джва раза быстрее прикинь чем 4

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

which uses incremental native-code compilation

Это кусками. Работает быстро, но бинарник получить не удаётся. Разве что вместе с компилятором. Скомпилировать в so, разумеется, совсем никак.

monk ★★★★★
()

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

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

Это же идеология C++, нет?

(Скорее всего) нет. В С++ стараются не добавлять фичи само наличие которых чего-то стоит (в плане производительности).

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

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

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

например весь файл должен быть написан на одном #lang

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

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

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

А где про это почитать подробнее можно. На их сайте сложновато сориентироваться

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