SlideShare a Scribd company logo
1 of 33
Lisp tutorial for Pythonista.
Day #3 : Lisp meets web.




                                                          Ransui Iso
                           Strategic Technology Group, X-Listing Co, Ltd.
宿題やった?
今日は Web アプリだよ!

   超基本部分しかやらないけど
モチベーション維持のためにもネタは重要
Allegro Serve ってのがある
  有名な商用処理系の Allegro Common Lisp に
ついてくる Web サーバとちょっとしたフレームワーク
Portable Allegroserve
      ってのを使います
 Allegro serve を他の処理系でも使えるように
移植したやつがあるので、有り難く使わさせて頂く
インストールは簡単

   最初の日にインストールした QuickLisp を使うです


CL­USER> (ql:system­apropos "aserve")
#<SYSTEM aserve / portableaserve­20101006­cvs / quicklisp 2010­12­07>
NIL
CL­USER> (ql:quickload "aserve")

        ****  なんかいろいろでる ****

("aserve")
CL­USER> 
QuickLisp の更新方法

 リポジトリとかたまに更新されるのでチェックしとけ!

CL­USER> (ql:update­client)
Installed version 2010121400 is as new as upstream version 2010121400. 
No update.
T
CL­USER> (ql:update­all­dists)
No update available for "quicklisp 2010­12­07".
NIL
REPL 環境下でテストしてみる

●   とりあえずお約束の Hello World から
CL­USER> (require :aserve)
NIL
CL­USER> (use­package :net.aserve)
T
CL­USER> (use­package :net.html.generator)
T
CL­USER> (start :port 4040)
#<WSERVER port 4040 {1002D47421}>
CL­USER> (defun hello­world (request entity)
           (with­http­response (request entity)
             (with­http­body (request entity)
               (princ "Hello World" *html­stream*))))
HELLO­WORLD
CL­USER> (publish :path "/hello­world"
                  :content­type "text/plain; charset=utf8"
                  :function #'hello­world)

    で、ブラウザで http://localhost:4040/hello­world にアクセス
UTF8 なんだし日本語出るだろ jk

●   .sbclrc に設定もしてるし大丈夫じゃね?
CL­USER> (defun hello­world (request entity)
           (with­http­response (request entity)
             (with­http­body (request entity)
               (princ " 波浪ワールド " *html­stream*))))
UTF8 なんだし日本語出るだろ jk

●   .sbclrc に設定もしてるし大丈夫じゃね?
CL­USER> (defun hello­world (request entity)
           (with­http­response (request entity)
             (with­http­body (request entity)
               (princ " 波浪ワールド " *html­stream*))))




2­aserve­worker: 01/04/11 ­ 17:56:08 ­ while processing command "GET 
/hello­world HTTP/1.1"
got error The value 27874 is not of type (UNSIGNED­BYTE 8).




            多バイト文字文化圏の悲哀!
unicode/byte 文字列変換
●   最終的に byte 列として解釈できりゃ OK らしい
(defun bin­to­str (data)
  (let* ((size (length data))
         (octets (make­array size 
                             :element­type '(unsigned­byte 8)
                             :fill­pointer 0)))
    (dotimes (i size)
      (vector­push (char­code (elt data i)) octets))
    (sb­ext:octets­to­string octets :external­format :utf­8)))

●   ついでなので逆変換もいっとけ
(defun str­to­bin (str)
  (let* ((octets (sb­ext:string­to­octets str 
                         :external­format :utf­8
                         :null­terminate nil))
         (size (length octets))
         (result (make­array size 
                             :element­type 'character
                             :fill­pointer 0)))
    (dotimes (i size)
      (vector­push (code­char (elt octets i)) result))
    result))
また色々新しいの出た!
 例によってザックリと解説
let と let* の違い

●   let は変数束縛が同時に起こる感じ
       ●
(let ((x 10)
      (y 20)
       ●

      (z (+ x y))
       ●

      ●
  ... body ... )
      ●

      ●   z の初期化には x と y が必要だけど、初期化は * 同時 * なので x,y
            ともにまだ存在しない!なので未定義変数参照エラー。

●   let* は変数束縛が逐次的に起こる感じ
(let* ((x 10)
       (y 20)
       (z (+ x y))

  ... body ... )

      ●   こっちは問題ない。この差は多分にコンパイラの都合。
配列の作成

●   make-array で作成する
(make­array  次元指定 or 最大サイズ
              :element­type  データ型
              :initial­contents  初期値
              :fill­pointer  要素の追加位置ポインタを使うか?
              :adjustable  サイズを可変にするか?
                                  他にもオプションあるけど、普通使うのはこんくらい

(setf arr (make­array 3 :element­type 'simple­string
    :initial­contents '("ham" "spam" "egg"))

(serf arr (make­array '(2 2) :element­type 'integer
    :initial­contents '((1 0) (0 1)))

(setf arr (make­array 0 :fill­pointer t :adjustable t))
配列の参照と書き換え

●   単純に参照する場合は aref か elt を使う
(setf arr (make­array 3 :element­type 'integer))
(setf (aref arr 0) 0)
(setf (elt arr 1) 5)
(setf (aref arr 5) 10) ← 当然のことながらエラー
                         
               aref は配列専用で elt はシーケンス汎用。 aref のほうが効率はいいはず。

●   fill-pointer を使うと色々便利
(setf arr (make­array 3 :element­type 'integer :fill­pointer t))
(fill­pointer arr)
(setf (fill­pointer arr) 0)
arr
(vector­push 1 arr)
(vector­push 2 arr)
(vector­push 3 arr)
(vector­push 4 arr) ← 配列の長さを超えたので値は追加できない
                      
          :adjustable を t に指定して vector­push­extend を使えば可変長配列として
          要素ををどんどん追加できる。
dotimes フォーム

●   単純なカウンタ付きループ
(dotimes (var max­value result­value) body)

      ●   変数 var は 0 からスタートして (­ max­value 1) まで回る

      ●   result­value でループが終了したときの dotimes フォームの戻
           り値を指定できる。省略時は nil 。

      ●   body は普通に色々書けばいい。
           –   ループを脱出したい場合は return を使う。この場合 result­value は使われ
                ない。

           –   return と書くのが気持ち悪い人は
               (defmacro break­loop (&body body) `(return ,@body))
               とか定義しておくとちょびっと幸せかも。

           –   ちなみに break って名前はすでに cl:break として使われてて、デバッガへ
                行くとかいう機能になってるですと!こんなイイ名前をもったいない!
他のパッケージ内のシンボルの参照

●   2 つの参照方法がある
     ●   package­name:symbol­name
          –   公開 (export されている ) シンボルを参照する

     ●   package­name::symbol­name
          –   非公開 (export されていない ) シンボルを強制的に参照する




sb-ext パッケージ                SBCL の拡張機能
sb-impl パッケージ               SBCL の内部実装へのインタフェース
さっきまでのプログラムをファイルに書く

●   pastebin 見てね
     ●   http://pastebin.com/7AfPE0GG
     ●   helloworld.lisp  とか名前をつけて保存


●   実行と終了
     ●   sbcl ­­load helloworld.lisp
     ●   REPL が生きてるので (quit) で終了できる

●   リロード
     ●   REPL で (load "helloworld.lisp")
     ●   (publish­pages)
パッケージに関する操作

●   (require :module­name)
      ●   標準パッケージはこれでロードできる。

●   (asdf:oos 'asdf:load­op :module­name)
      ●   インストールされているモジュールをロードする
      ●   QuickLisp でインストールしたモジュールも内部では ASDF の管
           理下にある

●   (use­package :package­name)
      ●   Python で言うところの from package­name import * に似
           ているけど、名前空間の操作しかしない点が異なる。
HTML で出力してみる

●   html マクロを使う
(defun hello­html­world (request entity)
  (with­http­response (request entity)
    (with­http­body (request entity)
      (html (:html
              (:head (:title (u " 波浪ワールド ")))
              (:body 
               (:h1 (u " 波浪ワールド "))
               ((:p :style "color: red;") (u " 赤い文字ですよ "))
               ((:p :style (format nil "color: ~a;" 
                                   (nth (random 5) 
                                        '("red" "blue" 
                                           "green" "purple" "black"))))
                (u " ここはランダムで色が変わるのです ")) ))) )))


    Lisp の中にテンプレートが完全に組み込まれてますよ!
          テンプレの中に処理もそのまま書ける!
HTML マクロの基礎

●   (:tag­name body)
      ●   タグ名はキーワードで指定する
      ●   タグに囲まれる値部分はリストの要素として書く

●   ((:tag­name :attr­name value) body)
      ●   タグに属性をつけたい場合はタグ全体をリスト化して属性名をキー
           にしたキーワード引数風味に書く
      ●   値部分は普通の書き方と同じ

●   テンプレ的機能
      ●   body とか value 部分には「バイナリ文字列」を返す S 式が書ける
           –   便宜的にバイナリ文字列って言ってるよ
           –   いまんとこはマルチバイト文字想定される時は u マクロで囲んどけ。
フォームの取り扱い

●   入力欄は普通に書けばイイ
(defun hello (request entity)
  (with­http­response (request entity)
    (with­http­body (request entity)
      (html (:html
              (:head (:title (u " あいさつ ")))
              (:body
               (:h1 (u " あいさつ "))
               ((:form :method "POST" :action "greeting")
                ((:input :type "text" :name "name" :value ""))
                ((:input :type "submit" :name "greeting­button" 
                              :value "Hi!")) ) )) ))))
フォーム値の取り出し方法

●       request 引数に入ってるので引っ張り出す
(defun get­field­value (request field­name)
  (cdr (assoc field­name (request­query request) :test #'equal)))

    –   assoc 関数:連想リストを検索する
         ●   連想リストとは
             ((key1 value1) (key2 value2) ...)
             形式のリスト。すごく単純な Key Value データの表現。
         ●   線形検索なので当然のことながら効率は良くない。
         ●   が、 hash­table に比べればずっとお手軽。

    –   request­query 関数は
             ((name1 . value1) (name2 . value2) ...)
             形式の dot pair のリストでフォーム値を返す
         ●   dot pair については先週のスライド見てね
テンプレへの値の埋め込み

●   :princ­safe キーワードを使おう
      ●   < > & をエスケープしてくれるので安全
(defun greeting (request entity)
  (let ((name (get­field­value request "name")))
    (if (null name)
        (setf name " 名無しさん ")
        (setf name (bin­to­str name)))

    (with­http­response (request entity)
      (with­http­body (request entity)
        (html (:html
                (:head (:title (u " あいさつ ")))
                (:body
                 (:h1 (u " あいさつ "))
                 (:p (:princ­safe (u (format nil "Hello ~a" name)))) ))
)))))

(format t ... )   : 標準出力ストリームへ書き出す
(format nil ... ) : ストリームへの書き出し無し
お待ちかねの課題です
こんなの作ってね!
            超シンプル掲示板!
書きこまれたデータの保持

●   SQL 系は次回やる予定なので、今回はオンメモリ

(defvar *bbs­datas* nil)

(defun add­new­article (subject body)
  (push (cons subject body) *bbs­datas*))
テンプレートの構成



            書き込みエリア




                      ページ全体
            表示エリア
ページ全体テンプレート

●   こんな感じかな?

(defun page­template ()
  (html
    (:html
      (:head (:title "Tiny BBS"))
      (:body
       (write­section­template)
       (dolist (article *bbs­datas*)
         (view­template article))))))
表示部分のテンプレ

●   こんな感じ

(defun view­template (article)
  (html
    ((:div :style "border: 1px solid black; padding: 2px;")
     ((:div :style "background­color: lightgray; color: black;") 
      (:princ­safe (u (car article))))
     (:pre (:princ­safe (u (cdr article))))) ))
で、あと書かなきゃいけないのは
   書き込み部分のテンプレ
   コントローラ関数 :bbs
コントローラ関数 bbs の作り方のヒント

●   request からフォーム値を取り出す
     ●   書き込みボタンが押されてたら
         –   add-new-article を呼ぶ

     ●   ページ全体テンプレを呼ぶ

     ●   おしまい!
いやー。ヒント出しすぎ
 もう、余裕で作れるでしょ?

More Related Content

What's hot

Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)
Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)
Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)Google Developer Relations Team
 
【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream APIdcomsolution
 
これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールNobuhisa Koizumi
 
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかBoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかYuki Miyatake
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~Nobuhisa Koizumi
 
60分で体験する Stream / Lambda
 ハンズオン
60分で体験する Stream / Lambda
 ハンズオン60分で体験する Stream / Lambda
 ハンズオン
60分で体験する Stream / Lambda
 ハンズオンHiroto Yamakawa
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会Akihiko Matuura
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11nekko1119
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルなおき きしだ
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
並行プログラミングと継続モナド
並行プログラミングと継続モナド並行プログラミングと継続モナド
並行プログラミングと継続モナドKousuke Ruichi
 
Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~CHY72
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
 
templateとautoの型推論
templateとautoの型推論templateとautoの型推論
templateとautoの型推論MITSUNARI Shigeo
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編egtra
 
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜勝成 鈴江
 

What's hot (20)

Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)
Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)
Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)
 
【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API
 
これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツール
 
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかBoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうか
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
 
Map
MapMap
Map
 
60分で体験する Stream / Lambda
 ハンズオン
60分で体験する Stream / Lambda
 ハンズオン60分で体験する Stream / Lambda
 ハンズオン
60分で体験する Stream / Lambda
 ハンズオン
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
並行プログラミングと継続モナド
並行プログラミングと継続モナド並行プログラミングと継続モナド
並行プログラミングと継続モナド
 
Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
templateとautoの型推論
templateとautoの型推論templateとautoの型推論
templateとautoの型推論
 
Haskell超入門 Part.1
Haskell超入門 Part.1Haskell超入門 Part.1
Haskell超入門 Part.1
 
Sml#探検隊
Sml#探検隊Sml#探検隊
Sml#探検隊
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編
 
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
 

Viewers also liked

重建街的故事
重建街的故事重建街的故事
重建街的故事kirstykirsty
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Ransui Iso
 
Lisp Tutorial for Pythonista : Day 4
Lisp Tutorial for Pythonista : Day 4Lisp Tutorial for Pythonista : Day 4
Lisp Tutorial for Pythonista : Day 4Ransui Iso
 
프레젠테이션1
프레젠테이션1프레젠테이션1
프레젠테이션1성아 박
 
Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Ransui Iso
 
Curriculum Vitae Morello Orfeo
Curriculum Vitae   Morello OrfeoCurriculum Vitae   Morello Orfeo
Curriculum Vitae Morello OrfeoOrfeo Morello
 

Viewers also liked (7)

重建街的故事
重建街的故事重建街的故事
重建街的故事
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
 
Lisp Tutorial for Pythonista : Day 4
Lisp Tutorial for Pythonista : Day 4Lisp Tutorial for Pythonista : Day 4
Lisp Tutorial for Pythonista : Day 4
 
프레젠테이션1
프레젠테이션1프레젠테이션1
프레젠테이션1
 
Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5Lisp Tutorial for Pythonista : Day 5
Lisp Tutorial for Pythonista : Day 5
 
Curriculum Vitae Morello Orfeo
Curriculum Vitae   Morello OrfeoCurriculum Vitae   Morello Orfeo
Curriculum Vitae Morello Orfeo
 
Danza lenta
Danza lentaDanza lenta
Danza lenta
 

Similar to Lisp Tutorial for Pythonista : Day 3

Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2Masao Kato
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説do_aki
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)啓 小笠原
 
Lisp batton - Common LISP
Lisp batton - Common LISPLisp batton - Common LISP
Lisp batton - Common LISPMasaomi CHIBA
 
第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章Tomonobu_Hirano
 
初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)Masahiro Hayashi
 
第一回Data mining勉強会 -第二章 - 原案
第一回Data mining勉強会 -第二章 - 原案第一回Data mining勉強会 -第二章 - 原案
第一回Data mining勉強会 -第二章 - 原案yushin_hirano
 
Erlangやってみた
ErlangやってみたErlangやってみた
Erlangやってみたina job
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Ransui Iso
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法博文 斉藤
 
lispmeetup#63 Common Lispでゼロから作るDeep Learning
lispmeetup#63 Common Lispでゼロから作るDeep Learninglispmeetup#63 Common Lispでゼロから作るDeep Learning
lispmeetup#63 Common Lispでゼロから作るDeep LearningSatoshi imai
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
eZ Publish勉強会9月〜テンプレート言語〜
eZ Publish勉強会9月〜テンプレート言語〜eZ Publish勉強会9月〜テンプレート言語〜
eZ Publish勉強会9月〜テンプレート言語〜ericsagnes
 
Write good parser in perl
Write good parser in perlWrite good parser in perl
Write good parser in perlJiro Nishiguchi
 
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜Hiromi Ishii
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweightgintenlabo
 

Similar to Lisp Tutorial for Pythonista : Day 3 (20)

Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
 
Lisp batton - Common LISP
Lisp batton - Common LISPLisp batton - Common LISP
Lisp batton - Common LISP
 
第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章
 
初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)初心者講習会資料(Osaka.R#7)
初心者講習会資料(Osaka.R#7)
 
Tokyor23 doradora09
Tokyor23 doradora09Tokyor23 doradora09
Tokyor23 doradora09
 
第一回Data mining勉強会 -第二章 - 原案
第一回Data mining勉強会 -第二章 - 原案第一回Data mining勉強会 -第二章 - 原案
第一回Data mining勉強会 -第二章 - 原案
 
Erlangやってみた
ErlangやってみたErlangやってみた
Erlangやってみた
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
 
Processing
ProcessingProcessing
Processing
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法
 
lispmeetup#63 Common Lispでゼロから作るDeep Learning
lispmeetup#63 Common Lispでゼロから作るDeep Learninglispmeetup#63 Common Lispでゼロから作るDeep Learning
lispmeetup#63 Common Lispでゼロから作るDeep Learning
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
eZ Publish勉強会9月〜テンプレート言語〜
eZ Publish勉強会9月〜テンプレート言語〜eZ Publish勉強会9月〜テンプレート言語〜
eZ Publish勉強会9月〜テンプレート言語〜
 
Write good parser in perl
Write good parser in perlWrite good parser in perl
Write good parser in perl
 
Boost Fusion Library
Boost Fusion LibraryBoost Fusion Library
Boost Fusion Library
 
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweight
 

More from Ransui Iso

「Pythonでやってみた」~広がるプログラミングの愉しみ~
「Pythonでやってみた」~広がるプログラミングの愉しみ~「Pythonでやってみた」~広がるプログラミングの愉しみ~
「Pythonでやってみた」~広がるプログラミングの愉しみ~Ransui Iso
 
Pythonで作る俺様サウンドエフェクター
Pythonで作る俺様サウンドエフェクターPythonで作る俺様サウンドエフェクター
Pythonで作る俺様サウンドエフェクターRansui Iso
 
アドテクを支える人と技術
アドテクを支える人と技術アドテクを支える人と技術
アドテクを支える人と技術Ransui Iso
 
Playing with curses
Playing with cursesPlaying with curses
Playing with cursesRansui Iso
 
小中学生Hack-a-thonにオッサンが乗り込んだ話
小中学生Hack-a-thonにオッサンが乗り込んだ話小中学生Hack-a-thonにオッサンが乗り込んだ話
小中学生Hack-a-thonにオッサンが乗り込んだ話Ransui Iso
 
XML-RPC : Pythonが「電池付属」と呼ばれる理由
XML-RPC : Pythonが「電池付属」と呼ばれる理由XML-RPC : Pythonが「電池付属」と呼ばれる理由
XML-RPC : Pythonが「電池付属」と呼ばれる理由Ransui Iso
 
ソフトシンセを作りながら学ぶPythonプログラミング
ソフトシンセを作りながら学ぶPythonプログラミングソフトシンセを作りながら学ぶPythonプログラミング
ソフトシンセを作りながら学ぶPythonプログラミングRansui Iso
 
Introduction of ToySynth
Introduction of ToySynthIntroduction of ToySynth
Introduction of ToySynthRansui Iso
 
PyQtではじめるGUIプログラミング
PyQtではじめるGUIプログラミングPyQtではじめるGUIプログラミング
PyQtではじめるGUIプログラミングRansui Iso
 
PySynth : A toy pure python software synthesizer.
PySynth : A toy pure python software synthesizer.PySynth : A toy pure python software synthesizer.
PySynth : A toy pure python software synthesizer.Ransui Iso
 

More from Ransui Iso (10)

「Pythonでやってみた」~広がるプログラミングの愉しみ~
「Pythonでやってみた」~広がるプログラミングの愉しみ~「Pythonでやってみた」~広がるプログラミングの愉しみ~
「Pythonでやってみた」~広がるプログラミングの愉しみ~
 
Pythonで作る俺様サウンドエフェクター
Pythonで作る俺様サウンドエフェクターPythonで作る俺様サウンドエフェクター
Pythonで作る俺様サウンドエフェクター
 
アドテクを支える人と技術
アドテクを支える人と技術アドテクを支える人と技術
アドテクを支える人と技術
 
Playing with curses
Playing with cursesPlaying with curses
Playing with curses
 
小中学生Hack-a-thonにオッサンが乗り込んだ話
小中学生Hack-a-thonにオッサンが乗り込んだ話小中学生Hack-a-thonにオッサンが乗り込んだ話
小中学生Hack-a-thonにオッサンが乗り込んだ話
 
XML-RPC : Pythonが「電池付属」と呼ばれる理由
XML-RPC : Pythonが「電池付属」と呼ばれる理由XML-RPC : Pythonが「電池付属」と呼ばれる理由
XML-RPC : Pythonが「電池付属」と呼ばれる理由
 
ソフトシンセを作りながら学ぶPythonプログラミング
ソフトシンセを作りながら学ぶPythonプログラミングソフトシンセを作りながら学ぶPythonプログラミング
ソフトシンセを作りながら学ぶPythonプログラミング
 
Introduction of ToySynth
Introduction of ToySynthIntroduction of ToySynth
Introduction of ToySynth
 
PyQtではじめるGUIプログラミング
PyQtではじめるGUIプログラミングPyQtではじめるGUIプログラミング
PyQtではじめるGUIプログラミング
 
PySynth : A toy pure python software synthesizer.
PySynth : A toy pure python software synthesizer.PySynth : A toy pure python software synthesizer.
PySynth : A toy pure python software synthesizer.
 

Recently uploaded

20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 

Recently uploaded (9)

20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 

Lisp Tutorial for Pythonista : Day 3

  • 1. Lisp tutorial for Pythonista. Day #3 : Lisp meets web. Ransui Iso Strategic Technology Group, X-Listing Co, Ltd.
  • 3. 今日は Web アプリだよ! 超基本部分しかやらないけど モチベーション維持のためにもネタは重要
  • 4. Allegro Serve ってのがある 有名な商用処理系の Allegro Common Lisp に ついてくる Web サーバとちょっとしたフレームワーク
  • 5. Portable Allegroserve ってのを使います Allegro serve を他の処理系でも使えるように 移植したやつがあるので、有り難く使わさせて頂く
  • 6. インストールは簡単 最初の日にインストールした QuickLisp を使うです CL­USER> (ql:system­apropos "aserve") #<SYSTEM aserve / portableaserve­20101006­cvs / quicklisp 2010­12­07> NIL CL­USER> (ql:quickload "aserve")         ****  なんかいろいろでる **** ("aserve") CL­USER> 
  • 8. REPL 環境下でテストしてみる ● とりあえずお約束の Hello World から CL­USER> (require :aserve) NIL CL­USER> (use­package :net.aserve) T CL­USER> (use­package :net.html.generator) T CL­USER> (start :port 4040) #<WSERVER port 4040 {1002D47421}> CL­USER> (defun hello­world (request entity)            (with­http­response (request entity)              (with­http­body (request entity)                (princ "Hello World" *html­stream*)))) HELLO­WORLD CL­USER> (publish :path "/hello­world"                   :content­type "text/plain; charset=utf8"                   :function #'hello­world) で、ブラウザで http://localhost:4040/hello­world にアクセス
  • 9. UTF8 なんだし日本語出るだろ jk ● .sbclrc に設定もしてるし大丈夫じゃね? CL­USER> (defun hello­world (request entity)            (with­http­response (request entity)              (with­http­body (request entity)                (princ " 波浪ワールド " *html­stream*))))
  • 10. UTF8 なんだし日本語出るだろ jk ● .sbclrc に設定もしてるし大丈夫じゃね? CL­USER> (defun hello­world (request entity)            (with­http­response (request entity)              (with­http­body (request entity)                (princ " 波浪ワールド " *html­stream*)))) 2­aserve­worker: 01/04/11 ­ 17:56:08 ­ while processing command "GET  /hello­world HTTP/1.1" got error The value 27874 is not of type (UNSIGNED­BYTE 8). 多バイト文字文化圏の悲哀!
  • 11. unicode/byte 文字列変換 ● 最終的に byte 列として解釈できりゃ OK らしい (defun bin­to­str (data)   (let* ((size (length data))          (octets (make­array size                               :element­type '(unsigned­byte 8)                              :fill­pointer 0)))     (dotimes (i size)       (vector­push (char­code (elt data i)) octets))     (sb­ext:octets­to­string octets :external­format :utf­8))) ● ついでなので逆変換もいっとけ (defun str­to­bin (str)   (let* ((octets (sb­ext:string­to­octets str        :external­format :utf­8                          :null­terminate nil))          (size (length octets))          (result (make­array size                               :element­type 'character                              :fill­pointer 0)))     (dotimes (i size)       (vector­push (code­char (elt octets i)) result))     result))
  • 13. let と let* の違い ● let は変数束縛が同時に起こる感じ ● (let ((x 10)       (y 20) ●       (z (+ x y)) ● ●   ... body ... ) ● ● z の初期化には x と y が必要だけど、初期化は * 同時 * なので x,y ともにまだ存在しない!なので未定義変数参照エラー。 ● let* は変数束縛が逐次的に起こる感じ (let* ((x 10)   (y 20)   (z (+ x y))   ... body ... ) ● こっちは問題ない。この差は多分にコンパイラの都合。
  • 14. 配列の作成 ● make-array で作成する (make­array  次元指定 or 最大サイズ :element­type  データ型 :initial­contents  初期値 :fill­pointer  要素の追加位置ポインタを使うか? :adjustable  サイズを可変にするか? 他にもオプションあるけど、普通使うのはこんくらい (setf arr (make­array 3 :element­type 'simple­string :initial­contents '("ham" "spam" "egg")) (serf arr (make­array '(2 2) :element­type 'integer :initial­contents '((1 0) (0 1))) (setf arr (make­array 0 :fill­pointer t :adjustable t))
  • 15. 配列の参照と書き換え ● 単純に参照する場合は aref か elt を使う (setf arr (make­array 3 :element­type 'integer)) (setf (aref arr 0) 0) (setf (elt arr 1) 5) (setf (aref arr 5) 10) ← 当然のことながらエラー   aref は配列専用で elt はシーケンス汎用。 aref のほうが効率はいいはず。 ● fill-pointer を使うと色々便利 (setf arr (make­array 3 :element­type 'integer :fill­pointer t)) (fill­pointer arr) (setf (fill­pointer arr) 0) arr (vector­push 1 arr) (vector­push 2 arr) (vector­push 3 arr) (vector­push 4 arr) ← 配列の長さを超えたので値は追加できない   :adjustable を t に指定して vector­push­extend を使えば可変長配列として 要素ををどんどん追加できる。
  • 16. dotimes フォーム ● 単純なカウンタ付きループ (dotimes (var max­value result­value) body) ● 変数 var は 0 からスタートして (­ max­value 1) まで回る ● result­value でループが終了したときの dotimes フォームの戻 り値を指定できる。省略時は nil 。 ● body は普通に色々書けばいい。 – ループを脱出したい場合は return を使う。この場合 result­value は使われ ない。 – return と書くのが気持ち悪い人は (defmacro break­loop (&body body) `(return ,@body)) とか定義しておくとちょびっと幸せかも。 – ちなみに break って名前はすでに cl:break として使われてて、デバッガへ 行くとかいう機能になってるですと!こんなイイ名前をもったいない!
  • 17. 他のパッケージ内のシンボルの参照 ● 2 つの参照方法がある ● package­name:symbol­name – 公開 (export されている ) シンボルを参照する ● package­name::symbol­name – 非公開 (export されていない ) シンボルを強制的に参照する sb-ext パッケージ SBCL の拡張機能 sb-impl パッケージ SBCL の内部実装へのインタフェース
  • 18. さっきまでのプログラムをファイルに書く ● pastebin 見てね ● http://pastebin.com/7AfPE0GG ● helloworld.lisp  とか名前をつけて保存 ● 実行と終了 ● sbcl ­­load helloworld.lisp ● REPL が生きてるので (quit) で終了できる ● リロード ● REPL で (load "helloworld.lisp") ● (publish­pages)
  • 19. パッケージに関する操作 ● (require :module­name) ● 標準パッケージはこれでロードできる。 ● (asdf:oos 'asdf:load­op :module­name) ● インストールされているモジュールをロードする ● QuickLisp でインストールしたモジュールも内部では ASDF の管 理下にある ● (use­package :package­name) ● Python で言うところの from package­name import * に似 ているけど、名前空間の操作しかしない点が異なる。
  • 20. HTML で出力してみる ● html マクロを使う (defun hello­html­world (request entity)   (with­http­response (request entity)     (with­http­body (request entity)       (html (:html               (:head (:title (u " 波浪ワールド ")))               (:body                 (:h1 (u " 波浪ワールド "))                ((:p :style "color: red;") (u " 赤い文字ですよ "))                ((:p :style (format nil "color: ~a;"                                     (nth (random 5)                                          '("red" "blue"    "green" "purple" "black"))))                 (u " ここはランダムで色が変わるのです ")) ))) ))) Lisp の中にテンプレートが完全に組み込まれてますよ! テンプレの中に処理もそのまま書ける!
  • 21. HTML マクロの基礎 ● (:tag­name body) ● タグ名はキーワードで指定する ● タグに囲まれる値部分はリストの要素として書く ● ((:tag­name :attr­name value) body) ● タグに属性をつけたい場合はタグ全体をリスト化して属性名をキー にしたキーワード引数風味に書く ● 値部分は普通の書き方と同じ ● テンプレ的機能 ● body とか value 部分には「バイナリ文字列」を返す S 式が書ける – 便宜的にバイナリ文字列って言ってるよ – いまんとこはマルチバイト文字想定される時は u マクロで囲んどけ。
  • 22. フォームの取り扱い ● 入力欄は普通に書けばイイ (defun hello (request entity)   (with­http­response (request entity)     (with­http­body (request entity)       (html (:html               (:head (:title (u " あいさつ ")))               (:body                (:h1 (u " あいさつ "))                ((:form :method "POST" :action "greeting")                 ((:input :type "text" :name "name" :value ""))                 ((:input :type "submit" :name "greeting­button"  :value "Hi!")) ) )) ))))
  • 23. フォーム値の取り出し方法 ● request 引数に入ってるので引っ張り出す (defun get­field­value (request field­name)   (cdr (assoc field­name (request­query request) :test #'equal))) – assoc 関数:連想リストを検索する ● 連想リストとは ((key1 value1) (key2 value2) ...) 形式のリスト。すごく単純な Key Value データの表現。 ● 線形検索なので当然のことながら効率は良くない。 ● が、 hash­table に比べればずっとお手軽。 – request­query 関数は ((name1 . value1) (name2 . value2) ...) 形式の dot pair のリストでフォーム値を返す ● dot pair については先週のスライド見てね
  • 24. テンプレへの値の埋め込み ● :princ­safe キーワードを使おう ● < > & をエスケープしてくれるので安全 (defun greeting (request entity)   (let ((name (get­field­value request "name")))     (if (null name)         (setf name " 名無しさん ")         (setf name (bin­to­str name)))     (with­http­response (request entity)       (with­http­body (request entity)         (html (:html                 (:head (:title (u " あいさつ ")))                 (:body                  (:h1 (u " あいさつ "))                  (:p (:princ­safe (u (format nil "Hello ~a" name)))) )) ))))) (format t ... ) : 標準出力ストリームへ書き出す (format nil ... ) : ストリームへの書き出し無し
  • 26. こんなの作ってね! 超シンプル掲示板!
  • 27. 書きこまれたデータの保持 ● SQL 系は次回やる予定なので、今回はオンメモリ (defvar *bbs­datas* nil) (defun add­new­article (subject body)   (push (cons subject body) *bbs­datas*))
  • 28. テンプレートの構成 書き込みエリア ページ全体 表示エリア
  • 29. ページ全体テンプレート ● こんな感じかな? (defun page­template ()   (html     (:html       (:head (:title "Tiny BBS"))       (:body        (write­section­template)        (dolist (article *bbs­datas*)          (view­template article))))))
  • 30. 表示部分のテンプレ ● こんな感じ (defun view­template (article)   (html     ((:div :style "border: 1px solid black; padding: 2px;")      ((:div :style "background­color: lightgray; color: black;")        (:princ­safe (u (car article))))      (:pre (:princ­safe (u (cdr article))))) ))
  • 31. で、あと書かなきゃいけないのは 書き込み部分のテンプレ コントローラ関数 :bbs
  • 32. コントローラ関数 bbs の作り方のヒント ● request からフォーム値を取り出す ● 書き込みボタンが押されてたら – add-new-article を呼ぶ ● ページ全体テンプレを呼ぶ ● おしまい!