---
# System prepended metadata

title: Untitled

---

### 問題：

手続きを定義しなさい。引数には `method`と`path`を受け取る。

`method` は `GET`, `POST`, `HEAD`, `PUT`などの文字列である。
path は `/` から始まる任意の文字列である。 (`"/"` だけの場合もありうる)

返り値は `[status, contents]` からなるリスト/配列とする。
`status`は`"200 OK"`, `"404 NotFound"`などの文字列である。
`contents`は、method, path の関係ごとに紐付けられた文字列である

以下の要件を満たすように実装せよ。

```
GET "/hello" → ("200 OK", "こんにちは")
GET "/bye"   → ("200 OK", "さよなら")
POST "/bye"  → ("200 OK", "ばいばい")
DELETE "/bye" → ("200 ok" "きえました")
該当なし     → ("404 NotFound", "ないです")
```

処理とデータは可能な限り分離せよ。
`if (path == "/hello") 〜 elseif (path == "/bye")`のように、条件文にマジックナンバーが含まれるコードは望ましくない。

### 回答

```lisp=
(defvar getdata
 '(("hello" . "こんにちは")
   ("bye" . "さよなら")))
(defvar postdata
 '(("bye" . (lambda (_elm)
 (list 200 "OK" "ばいばい")))))
 
(defvar data
'("/hello" . (("GET" . "こんにちは")))
 ("/bye" . (("POST")))

404 NotFound
405 Method Not allowed



(defun fn (method path)
(unless (string-prefix-p "/" path)
(error "not path start with /"))

(let (status contents code str)
(setq contents
(cond
((string= "GET" method)
(cond
;; (string= "/hello" path)
;; (setq code 200
;; str "OK"
;; contents "こんにちは")
(setq contents (alist-get method getdata))
(unless contents
(setq code 404
contents "Not found"))))
((string= "POST" method)
(t
(let ((fn (alist-get method postdata)))
(setq data (if fn (funcall fn method)))
(setq code (nth 0 data))
(setq str (nth 1 data))
(setq contents (nth 2 data))))

(setq status (format "%s %s" code str))
(list status contents)))
```


