LINUX.ORG.RU

А как у common lisp дела с производительностью?

 


4

10

Решил покурить cl ,не ну реально красивый язык. Учить решил по книге Practical Common Lisp (может посоветуете что ещё?), а запускать код на clisp. Ну так вот какие реализации языка предпочесть? Касаемо книг хотелось бы что то типа k&r, в такой же манере, но для common lisp, ну вы поняли.

Ну и вообще что посоветуете начинающему лисперу?

★★★★★

Вместо PCL посоветую ANSI Common Lisp(Кстати по свободной цене).
Также посоветую Land Of Lisp. LOL только на английском, но написана замечательно, читается легко, снабжена тематическими иллюстрациями-комиксами. При написании автор консультировался с RMS. В общем книга с душой написана.

deterok ★★★★★
()

Да, бери sbcl как уже посоветовали и ставить Slime лучше из Quicklisp.

deterok ★★★★★
()

Лучше clojure учи. Хотя бы деньги заработаешь.

anonymous
()

Основные реализации: SBCL, Clozure CL, LispWorks и Allegro CL. Последние две - коммерческие, и у них есть свои среды IDE, в том числе, бесплатные, хотя и с ограничениями. Для начала я бы посоветовал установить (1) SBCL + Emacs + Slime и отдельно бесплатный (2) LispWorks Personal Edition.

Что касается скорости. Ядро языка быстрое. С опциональными декларациями типов даже может быть очень быстрым.

Что является медленным. Это CLOS (это такой свой вариант ООП). И это боксинг для некоторых вещественных типов (не всех и не всегда) при выходе из функций. Если ты не собрался писать числодробильное или критическое по скорости приложение, то может забить на эти две вещи совсем.

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 1)

Касаемо книг хотелось бы что то типа k&r, в такой же манере, но для common lisp, ну вы поняли.

On Lisp. Тем более перевод есть.

urxvt ★★★★★
()

начинающему лисперу

Схема же.

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

Прочту после PCL
Будет наверное третьей.

Силен.

anonymous
()

У SBCL непонятные для нетёртых лисперов сообщения об ошибках. Подсядь на иглуСкачай LispWorks Personal. Ну или CCL, там тоже для новичков попонятнее ругань.

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

«Чо», и быстрее luajit?

Если в SBCL всё выкинуть и переписать по-нормальному приделать SSA-оптимизацию, то будет дышать в спину gcc. Если не 4.5+, то 4.0 точно.

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

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

доо, возьмем наш любимый шатаут:

var i = "", ilen, clen, j, q = [ /agggtaaa|tttaccct/ig,
  /[cgt]gggtaaa|tttaccc[acg]/ig, /a[act]ggtaaa|tttacc[agt]t/ig,
  /ag[act]gtaaa|tttac[agt]ct/ig, /agg[act]taaa|ttta[agt]cct/ig,
  /aggg[acg]aaa|ttt[cgt]ccct/ig, /agggt[cgt]aa|tt[acg]accct/ig,
  /agggta[cgt]a|t[acg]taccct/ig, /agggtaa[cgt]|[acg]ttaccct/ig],
  b = [ /B/g, '(c|g|t)', /D/g, '(a|g|t)', /H/g, '(a|c|t)', /K/g, '(g|t)',
  /M/g, '(a|c)', /N/g, '(a|c|g|t)', /R/g, '(a|g)', /S/g, '(c|g)',
  /V/g, '(a|c|g)', /W/g, '(a|t)', /Y/g, '(c|t)']

while(j = readline()) i+=j+"\n"; ilen = i.length

i = i.replace(/^>.*\n|\n/mg, ''); clen = i.length

for(j = 0; j<q.length; ++j) print(q[j].source, (i.match(q[j]) || []).length)

for(j = -1; j<b.length - 1;) i = i.replace(b[++j], b[++j])

print(["", ilen, clen, i.length].join("\n"))

3.77 secs vs

(eval-when (:compile-toplevel :load-toplevel :execute)
  (require :asdf)
  (require :cl-ppcre)

#+sb-thread
(progn
  (define-alien-routine sysconf long (name int))
  (use-package :sb-thread)))

(eval-when (:compile-toplevel)
(setf cl-ppcre:*regex-char-code-limit* 128))

(defconstant  +regex-list+
  '("agggtaaa|tttaccct"
    "[cgt]gggtaaa|tttaccc[acg]"
    "a[act]ggtaaa|tttacc[agt]t"
    "ag[act]gtaaa|tttac[agt]ct"
    "agg[act]taaa|ttta[agt]cct"
    "aggg[acg]aaa|ttt[cgt]ccct"
    "agggt[cgt]aa|tt[acg]accct"
    "agggta[cgt]a|t[acg]taccct"
    "agggtaa[cgt]|[acg]ttaccct"))

(defconstant  +alternatives+
  '(("B" "(c|g|t)")  ("D" "(a|g|t)")
    ("H" "(a|c|t)")  ("K" "(g|t)")
    ("M" "(a|c)")    ("N" "(a|c|g|t)")
    ("R" "(a|g)")    ("S" "(c|t)")
    ("V" "(a|c|g)")  ("W" "(a|t)")
    ("Y" "(c|t)")))

#+sb-thread
(progn
  (defconstant  +cpu-count+ (sysconf 84))
  (defvar *mutex* (make-mutex))
  (defvar *aux-mutex* (make-mutex))

  (defmacro bg  (&body body) `(make-thread (lambda () ,@body)))
  (defmacro join-all (&body body)
	`(mapcar
	  #'join-thread
	  (loop for item in (list ,@body)
		 append (if (consp item) item (list item))))))

(defun read-all
    (stream &aux (buf-size (* 1024 1024))
     (size 0)
     (buf-list
      (loop
         for buf = (make-string buf-size :element-type 'base-char)
         for len = (read-sequence buf stream)
         do (incf size len)
         collect (if (< len buf-size) (subseq buf 0 len) buf)
         while (= len buf-size))))
  (declare (type fixnum size))
  (loop with res-string = (make-string size :element-type 'base-char)
     with i of-type fixnum = 0
     for str in buf-list
     do (setf (subseq res-string i) (the simple-base-string str))
     (incf i (length (the simple-base-string str)))
     finally (return res-string)))

(defun length-to-replace (match)
  (loop for x in match
     sum (- (the fixnum (cdr x))
            (the fixnum (car x))) of-type fixnum))

(defun replace-aux
    (match replacement target-string result-string
     &key (match-begin 0) (match-end -1)
     (match-length (length match))
     &aux
     (len (length replacement))
     (first-match (if (zerop match-begin) '(0 . 0) (nth (1- match-begin) match)))
     (target-start (cdr first-match))
     (result-start (+ (the fixnum (* len match-begin))
                    (- target-start
                       (the fixnum (length-to-replace (subseq match 0 match-begin)))))))
  (declare (type fixnum match-begin match-end match-length target-start result-start len)
           (type list match)
           (type simple-base-string result-string target-string)
           (type vector replacement))
  (loop with (i j) of-type fixnum = (list result-start target-start)
     with mmatch = (if (> match-begin match-end)
                       match (subseq match match-begin match-end))
     for pair in mmatch
     do (setf (subseq result-string i) (subseq target-string j (car pair))
              i (+ i (- (the fixnum (car pair)) j))
              (subseq result-string i) replacement
              j (cdr pair)
              i (+ i len))
     finally (if (or (minusp match-end) (<= match-length match-end))
                 (setf (subseq result-string i ) (subseq target-string j))))
  nil)

#+sb-thread
(defun parts
    (parts-num len
     &aux
     (ranges (loop with (step rest) of-type fixnum =  (multiple-value-list (floor len parts-num))
                with i of-type fixnum = 0 while (< i len)
                collect i into res of-type fixnum
                do (incf i step)(if (plusp rest) (progn (incf i) (decf rest)) )
                finally (return (append res (list len))))
             ))
  (declare (type fixnum len parts-num)
           (type list ranges))
  (mapcar #'cons ranges (subseq ranges 1)))

(defun replace-all
    (regexp replacement target-string
     &aux (rmatch '()) (match '())
     (result-string (make-string 0 :element-type 'base-char)))
  (declare (type simple-base-string result-string target-string)
           (type vector replacement))
  (cl-ppcre:do-scans
      (match-start match-end reg-starts reg-ends regexp target-string nil)
    (push (cons match-start match-end) rmatch))
  (if rmatch
      (progn
        (setf match (reverse rmatch)
              result-string (make-string
                             (+ (- (length target-string)
                                   (length-to-replace match))
                                (the fixnum (* (length replacement)
                                               (length match)))) :element-type 'base-char))
        #-sb-thread
        (replace-aux match replacement target-string result-string)
        #+sb-thread
        (mapcar #'join-thread
                (loop with len of-type fixnum = (length match)
				   with parts-list  = (parts +cpu-count+ len)
                   with current of-type fixnum = 0
                   repeat +cpu-count+
                   collect
					 (bg (let (range)
                           (with-mutex (*mutex*)
                             (setf range (nth current parts-list))
                             (incf current))
                           (replace-aux match replacement target-string result-string
                                        :match-begin (car range) :match-end (cdr range)
                                        :match-length len)))))
        result-string)
      target-string))

(defun main (&optional (stream *standard-input*)
             &aux (sequence (read-all stream))
             (size (length sequence)))
  (declare (type simple-base-string sequence))
  (setf sequence (replace-all ">[^\\n]*\\n|\\n" "" sequence))

  #-sb-thread
  (progn
    (loop for regex in +regex-list+ do
         (format t "~a ~a~%" regex
                 (/ (length
                     (the list
                       (cl-ppcre:all-matches regex sequence))) 2)))
    (format t "~%~a~%~a~%" size (length sequence))
    (loop for pair in +alternatives+ do
         (setf sequence (replace-all  (car pair) (cadr pair) sequence )))
    (format t "~a~%" (length sequence)))
  #+sb-thread
  (let* ((len (length +regex-list+))
         (result (make-list (1+ len))))
    (join-all
	 (loop with idx of-type fixnum = 0
		repeat len
		collect
          (bg (let (reg cur)
                (with-mutex (*aux-mutex*)
                  (setf cur idx reg (nth cur +regex-list+))
                  (incf idx))
              (setf (nth cur result)
                    (format nil "~a ~a" reg
                            (/ (length
                                (the list
                                  (cl-ppcre:all-matches reg sequence))) 2))))))
	 (bg (loop with seq = (copy-seq sequence)
            for pair in +alternatives+ do
              (setf seq (replace-all  (car pair) (cadr pair) seq ))
            finally (setf (nth len result)
                          (format nil "~%~a~%~a~%~a" size (length sequence) (length seq))))))
    (format t "~{~a~%~}" result))
  )

45.30 secs

разница на лицо

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

разница на лицо

Фрейд добро по-отечески улыбнулся и закурил трубку.

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

Если посмотреть все тесты, то regex-dna для V8 (vs C, например) выбивается: есть подозрение что разработчики могли just for fun впилить специализированные оптимизации. Хотя может у них regex-движок очень хорош..

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

Если посмотреть все тесты, то regex-dna для V8 (vs C, например) выбивается:

да, но зато и в остальных можно наблюдать лапшу на CL против простых решений на JS

wota ★★
()

Practical Common Lisp (может посоветуете что ещё?

Да пожалуйста: CLTL v2

anonymous
()

Ну так вот какие реализации языка предпочесть?

clisp, sbcl

anonymous
()

Не, ты бери лучше clisp. Портабельность, удобный REPL, всё здорово.

sbcl умеет компиляцию в машинный код, многопоточность (хотя clisp, в принципе, тоже умеет), но для обучения clisp, ИМХО, здорово.

А вот SLIME, который тут советуют, поломал мне отступы в emacs. Но это моё мнение чисто как непрофессионала, очевидно, всё можно поправить

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

В аналах какого-нибудь другого ресурса сохранилось обсуждение; может есть ссылка не лор-тему?

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

когда там явка слила лиспу,

http://benchmarksgame.alioth.debian.org/u32/benchmark.php?test=all&lang=j...

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

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

sbcl умеет компиляцию в машинный код

Громко сказано, скорее в «образ», все-таки там не машинные команды, или я ошибаюсь?

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

Тсссс! Не спугни лиспанутых, они-то верят, что их убогая поделка это настоящий компилятор.

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

Не, ты бери лучше clisp.

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

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

Заказывал этот ANSI Common Lisp два раза, так и не прислали, и не позвонили мне. Негодую. Купил бы уже даже без скидки. :( в Воронеже таких книг не продают.

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

В аналах какого-нибудь другого ресурса сохранилось обсуждение; может есть ссылка не лор-тему?

скорее всего он про что-то вроде:

http://benchmarksgame.alioth.debian.org/u64q/program.php?test=fastaredux&...

хотя аналогичный вариант на С++:

http://benchmarksgame.alioth.debian.org/u64q/program.php?test=fastaredux&...

в 10 раз быстрее и тоже не принят

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

Меня больше радовал некто, отстаивающий dynamic-typing аргументом, что, мол, ближе к ассемблеру (а оттуда уже «первородство», большая гибкость и все такое): «и там, и там типов нет».

// Вроде в флейм-треде про nemerle где-то было.

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

Слушай, что за фигню тут набросил нам? Любой мало-мальский начинающий лиспер знает, что &key, &aux и &optional нельзя использовать, если важна скорость. Да, вообще, такая портянка, что совершенно лень читать и вникать. Далеко не уверен, что там «эквивалент».

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

Образ и clisp может. И даже лучше, потому что не умирает :)

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

Ну у меня таких не попадалось. Что же это за библиотеки?

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

Слушай, что за фигню тут набросил нам?

это самый быстрый вариант, который запостили на http://benchmarksgame.alioth.debian.org/

Любой мало-мальский начинающий лиспер

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

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

Сам набросил простыню какую-то

это лучшее, что родили лисперы для, пожалуй, самого популярного бенчмарка

а кто-то что-то должен тебе писать. Ну-ну

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

wota ★★
()
Ответ на: комментарий от wota
 (declare (type fixnum match-begin match-end match-length target-start result-start len)
           (type list match)
           (type simple-base-string result-string target-string)
           (type vector replacement))

Это без декларации optimize будет проверять типы в рантайме без какой-либо выгоды. Этот код не может быть «самым супер-пупер лучшим и быстрым». Ты бы лучше соснул хуйца.

http://www.sbcl.org/manual/Declarations-as-Assertions.html

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

Да, сумасшедших вокруг CL много.

Порываюсь задасть провокационный вопрос: а вокруг кого больше всего сумасшедших? (нет, даже не вокруг психиатров и санитаров)

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

Может, вокруг хаскеля?

По мне, CL довольно простой язык, а в хаскеле есть монадические трансформеры (али как их?), мамкин борщ и всё такое

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

не знаю о чем ты, но там все наоборот

там попаболь яванутого владельца и ничего более. окончательный ответ чела был --- «запилите себе свой шотаут» :)

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

Да, сумасшедших вокруг CL много.

не пались так явно :)

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

Этот код не может быть «самым супер-пупер лучшим и быстрым».

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

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