Lisp как универсальная обертка


Published on

Published in: Technology, Education
1 Like
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Lisp как универсальная обертка

  1. 1. Lisp как универсальнаяоберткаVsevolod Dyomkin@vseloved2013-05-31
  2. 2. Темы* Кратко о языке* Примеры Lisp-путирешения задач* Нужен ли Lisp и кому?
  3. 3. “Perl делает простыевещи простыми,a сложные —возможными”
  4. 4. Lisp делает сложныевещи доступными,а простыескладываются самисобой
  5. 5. Принципы Lisp* Всё — выражение* Всё — первоклассное* Программа — это живой образ* Ядро языка — 25 базовых форм,всё остальное — надстройка над ними,которую можно менять
  6. 6. Lisp — этовычислительно-ориентированныйязык
  7. 7. (defstruct node(key 0 :read-only t)(value 0 :read-only t)(left nil :type (or null node) :read-only t)(right nil :type (or null node) :read-only t))(defun copy-node (node &key (key (node-key node))(value (node-value node))(left (node-left node))(right (node-right node)))(make-node :key key:value value:left left:right right))(defun left-rotate (node)(let ((left (node-left node)))(copy-node left:right (copy-node node:left (node-right left)))))Вместо “Hello World”
  8. 8. (clsql:def-view-class synset ()((synsetid :initarg :synsetid :reader synset-id:type integer :db-kind :key)(pos :initarg :pos :reader synset-pos:type char)(lexdomainid :initarg :lexdomainid:type integer :db-constraints (:not-null))(definition :initarg :definition :reader synset-def:type string)(word :initarg :word :reader synset-word :db-kind :virtual)(sensenum :initarg :sensenum :db-kind :virtual))(:base-table "synsets"))CL-USER> (make synset :word "foo" :synset-id 42 :pos #V:definition "A test synset")#<SYNSET foo/V 42 {100329C7F3}>Оборачиваем SQL или A poor mans ORM
  9. 9. Оборачиваем SQL или A poor mans ORM(defmethod slot-unbound (class (synset synset) (slot (eql word)))(setf (slot-value synset slot)(query1 (select (lemma :from words)`(:where wordid:= ,(select (wordid :from senses)`(:where synsetid:= ,(synset-id synset):limit 1)):limit 1)))))
  10. 10. (defun select (from &optional args)(values (fmt "(SELECT ~A ~{~A~^ ~})"(etypecase from(symbol(fmt "* FROM ~A"(clsql:view-table (find-class from))))(list(ds-bind (fields tables) (split :from from)(fmt "~{~A~^,~} FROM ~{~A~^,~}"(mapcar #`(if (listp %)(fmt "~A(~A)"(first %) (second %))%)fields)table))))(mapcar #`(case %(:group-by "GROUP BY")(:order-by "ORDER BY")(t %))args))(when (symbolp from) from)))Оборачиваем SQL или A poor mans ORM
  11. 11. Альтернативный вариант SQL(clsql:select [item_id] [as [count [*]] num]:from [table]:where [is [null [sale_date]]]:group-by [item_id]:order-by ((num :desc)):limit 1)
  12. 12. Оборачиваем черные ящики – клиент redis(def-cmd HMGET (key field &rest fields) :multi"Get the values associated with the specified FIELDSin the hash stored at KEY.")
  13. 13. Оборачиваем черные ящики – клиент redis(defmacro def-cmd (cmd (&rest args) reply-type docstring)`(defun ,cmd ,args,docstring(return-from ,cmd(with-reconnect-restart(tell ,cmd ,@args)(prog1 (expect ,reply-type)(unless *pipelined*(clear-input (conn-stream *connection*))))))))
  14. 14. Оборачиваем черные ящики – клиент redis(let ((redis:*echo-p* t))(redis:with-persistent-connection (:port 10000)(loop (process-job)))(defun process-job ()(red:blpop "queue")(let* ((id (red:incr "id"))(results (calculate-results)))(result-key (fmt "result~A" id)))(redis:with-pipelining(dolist (result results)(red:lpush result-key result))(red:lpush "results" result-key))))
  15. 15. Оборачиваем сложные алгоритмы - CKY(macrolet((CKY (&body body)`(with-slots (rules nts->idx) grammar(let* ((pi0 #{}) (bps #{}) ;; also need to init them(min most-negative-single-float))(do ((pos 1 (1+ pos)))((>= pos *sentence-length*))(do ((i 1 (1+ i)))((> i (- *sentence-length* pos)))(let ((j (+ i pos)))(dotable (_ k nts->idx)(let (max arg)(do ((s i (1+ s)))((>= s j))(dotable (rule q rules)(when (and (tryadic rule)(= k (first rule))),@body)))(when (if (listp max) max (> max min))(setf (@ pi0 (1- i) (1- j) k) max(@ bps (1- i) (1- j) k) arg)))))))(values pi0 bps)))))
  16. 16. Оборачиваем сложные алгоритмы - CKY(defmethod parse ((grammar pcfg) (sentence list))"Return the parse tree of SENTENCE for PCFG.Parsing is performed in 2 steps:- the main method returns as values the matrices PI0 (pi matrix)and BPS (backpointers matrix)- the :around method restores the parse tree from these matricesThis brings additional flexibility for the return values of themethod: for instance, we can try to return several trees or haveseveral roots."(CKY (let* ((cur (cons rule (1- s)))(l (@ pi0 (1- i) (1- s) (second rule)))(r (@ pi0 s (1- j) (third rule)))(score (if (and l r)(+ (log q) l r)min)))(when (> score (or max min))(setf max scorearg cur)))))
  17. 17. Оборачиваем сложные алгоритмы - CKY(defmethod parse :around ((grammar pcfg) (sentence list))(with-raw-results(values (idx->nts (decode-parse-tree sentence bps 0 last iroot))(exp (or (@ pi0 0 last iroot) min))pi0bps)))
  18. 18. Оборачиваем сложные алгоритмы - CKY(declaim (inline @))(defun @ (m i j k)(get# (+ (* i *sentence-length* *nt-count*)(* j *nt-count*)k)m))(defsetf @ (m i j k) (v)`(set# (+ (* ,i *sentence-length* *nt-count*)(* ,j *nt-count*),k),m ,v))
  19. 19. Бонус: оборачиваем оптимизацию perform-pass-1 ((poly-ctx poly-ctx)(hash-table node-idx))"Scans SRC-OSM xml stream extracting <node> tags, checks each nodefor polygon belonging via POLY-CONTEXT, and sets index NODE-IDXin case of success"(:with (the (unsigned-byte 56) way-offset) := 0)(xml-on-tag "node"(attrs ("id" uint64 node-id)("lon" float lon)("lat" float lat))(on-match (when (poly-check poly-ctx lon lat)(setf (gethash node-id node-idx) 1))))(xml-on-tag "way" (on-match (when (zerop way-offset)(setf way-offset tag-offset))))(tracing-tag-offset tag-offset)(:finally (return (1- way-offset))))
  20. 20. Бонус: оборачиваем оптимизацию defun/iter-xml (name (&rest typed-args) doc-string&rest clauses)`(defun/fast ,name ,(cons (sb-sys:fd-stream src-osm) typed-args),doc-string(iter-xml-stream (upon-stream src-osm),@clauses)))
  21. 21. Бонус: оборачиваем оптимизацию defun/iter-xml (name (&rest typed-args) doc-string&rest clauses)`(defun/fast ,name ,(cons (sb-sys:fd-stream src-osm) typed-args),doc-string(iter-xml-stream (upon-stream src-osm),@clauses)))(defmacro defun/fast (name typed-args doc-string &body body)`(defun ,name ,(mapcar #second typed-args),doc-string(declare (optimize (speed 3) (safety 0) (debug 0)(compilation-speed 0) (space 0)),@(mapcar (curry #apply(lambda (type arg)`(type ,type ,arg)))typed-args)),@body))
  22. 22. (defun graylog (message &key level backtrace file line-no)(let (sock)(unwind-protect(let ((msg (salza2:compress-data(babel:string-to-octets(json:encode-json-to-string#{:version "1.0" :facility "lisp":host (get-hostname):|short_message| message:|full_message| backtrace:timestamp (local-time:timestamp-to-unix(local-time:now)):level level :file file :line line-no}):encoding :utf-8)salza2:zlib-compressor)))(setf sock (usocket:socket-connect *graylog-host**graylog-port*:protocol :datagram:element-type ub8))(usocket:socket-send sock msg (length msg))))(usocket:socket-close sock)))Тупой индустриальный код
  23. 23. Lisp ресурсы1. Hyperspec - Cookbook - Cliki – http://cliki.net4. lispdoc - Google Styleguide - - Lisp books -
  24. 24. Инструменты1. Реализации – 8+2:SBCL, CCL, ECL, ABCL2. SLIME, SLIMV3. quicklisp
  25. 25. LispПочему?Зачем?Для кого?И другие вопросы...