あのねノート

せんせいあのね、パソコンで字が書けるようになったよ

Racketでブログを作ろう~Racketチュートリアル中級編をやってみた(第1回)

今朝は実験のレポートについてメールが来ていてもしかして残念なお知らせかもしれないと背筋が凍りました(まだ大丈夫でした)。
さてさて、初級に懲りず中級もやります!大丈夫かな!
初級編はこちら↓
momo-moemoe.hatenablog.com
momo-moemoe.hatenablog.com

中級編は長いし苦戦が予想されるので前後編じゃなくて第1回と書くことで予防線を張ってみました。たぶんめっちゃゆっくり進みます…がんばる…
Continue: Web Applications in Racket
このチュートリアルの内容としては、簡単なブログシステムを作るということっぽいです。

まずはとりあえず次のプログラムを動かせと書いてあるのでコピペして動かしてみます。

#lang web-server/insta
(define (start request)
  (response/xexpr
   '(html
     (head (title "My Blog"))
     (body (h1 "Under construction")))))

実行してみると、ブラウザが開いて「Under Construction」画面が開きました!
f:id:momo_moemoe:20160814084656p:plain
どうやら

<html>
<head>
<title>My Blog</title>
</head>
<body>
Under construction
</body>
</html>

みたいな感じになるみたいです。(htmlわからないので正確かどうかはわかりません)

ここからブログシステムを作っていくということで、当面の目標としては

  • 投稿リストを表示する
  • 新規投稿できるようにする
  • 投稿に対してコメントをつけられるようにする
  • 全ユーザーが同じ投稿を共有できるようにする(別のユーザーから見ても同じ投稿が表示されるようにするということでしょうか)
  • データをディスクに保存する(投稿をデータベース化するようです)

という感じみたい(2章をざっと訳しただけなのでわかりませんが)。

まず投稿の構造体を作ります。

(struct post (title body))

ブログはpost構造体のリストの形をとるのでリストを定義します。タイトルと内容の組を好きなだけわんさか作りましょう。

(define BLOG (list (post "ふたつめ"
                         "表示されてるかな?")
                   (post "ひとつめ"
                         "はじめてだよ!")
                   ))

新しく投稿したものが上にたまるのでこの順番のリストになります。
ここからRacketでHTMLを作ってこのリストの内容を表示させることになるようです。

どうやらRacket→XML→HTMLというふうに置き換えられるそうです。細かい説明はチュートリアルに書かれていますが、ざっくり言うとリストの形でHTMLを書けるみたい。なんでもリストにしちゃうのおもしろいなあ。

ここでExerciseとして置き換え式を書いてね!みたいな問題が出ていたのですが、よくわからないので次を読み進んでみるとプログラムが完成していました。コメントをつけることでExerciseの代わりにしようと思います。

;start:request->response
;リクエストを受け取ってコンテンツを表示するページを作る関数
(define (start request)
  (render-blog-page BLOG request))

render-blog-pageが定義されていないので何とも言えませんが、このstart関数がないとエラーが出てしまうようです。実行を押した時に動くmain関数的なのがこれみたい。

;render-blog-page:blog request->response
;ブログとリクエストを受け取って、ブログを表示するHTMLページを作る
;タイトルとボディが定義されている
(define (render-blog-page a-blog request)
  (response/xexpr
   `(html (head (title "My Blog"))
          (body (h1 "My Blog")
                ,(render-posts a-blog)))))

さっきのヘッダーとボディができてますね。あと、「,(Racketの式)」でシンボル内の式をシンボルとしてではなく式として評価できるので、ボディのMy Blogの下でrender-postsという関数が評価されてpostのリストであるBLOGが評価される(→ボディの内容になる)ようです。

;render-post:post->xexpr
;post構造体を受け取ってX式に変換
(define (render-post a-post)
  `(div ((class "post"))
        ,(post-title a-post)
        (p ,(post-body a-post))))

これで1つのpost構造体を件のX式に置き換えることができます。
htmlでの

<p>This is <div class="emph">another</div> example.</p>

'(p "This is " (div ((class "emph")) "another") " example.")

と書けるそうなので、そういう変換が行われているのでしょう。

;render-posts:blog->xexpr
;postのリストであるブログを受け取ってX式に変換
;mapを使う
(define (render-posts a-blog)
  `(div ((class "posts"))
        ,@(map render-post a-blog)))

1つのpostをX式に変換できるようになったらmapを使ってリストに適用できるようにすればBLOGの内容をX式に変換することができます。

実行するとこうなります。
f:id:momo_moemoe:20160814175412p:plain

うーん、読めるけど書けないなって感じだ!でもこの置き換えの感じ、実験でコンパイラを作ったときにちょっと似てる気がします。
実はこれで章の数的には5分の1ぐらいしか行ってないんですけど、キリがいい感じなので投稿しますね。続きもがんばる。