lispとrubyとpythonと その2(common lisp)

common lispでの
・文字列
連結
分割
切り出し
比較
・同値性、同一性
・変換
数字→文字列
文字列→数字
文字列→時刻
時刻→文字列
・標準出力に文字列出力
・標準入力から読み込み
・コマンドライン引数の受け取り
が以下。
やっぱりというか標準ライブラリが貧弱。
いちいち探して入れるのはやっぱり面倒くさい。

;;文字列連結
;;concatenateで連結
(setf s1 (concatenate 'string "abc" "あいうえお"))
(print s1)

;;formatで連結する手もある
(setf s2 (format nil "~A~A" "abc" "あいうえお"))
(print s2)

;;文字列の分割
;;標準ではsplit的なものがない。
;;splitくらいつくりゃあいいんだけど、やっぱ作るの面倒くさい。
;;この辺のいたらなさがlispの辛いところ。
;;split-sequenceを入れて使うことにする
;;インストールはこんな感じで、asdfで入れる。
;; ;; CL-USER> (require 'asdf)
;; ;; NIL
;; ;; CL-USER> (require 'asdf-install)
;; ;; ("ASDF-INSTALL")
;; ;; CL-USER> (asdf-install:install 'split-sequence)
;; ;; NIL

(require 'split-sequence)
(setf seq (split-sequence:split-sequence #\, "あaあ,いiい,うuう,えeえ"))
(mapc
 #'(lambda (s) (format t "~A~%" s))
 seq)

;;文字列の検索
;;これも標準ではない??
;;しょうがないからcl-ppcreで。
(require 'cl-ppcre)
;;ヒットすれば多値が戻る
(multiple-value-bind (s e)
    (cl-ppcre:scan "かきくけこ" "あいうえおかきくけこさしすせそ")
  (format t "~A-~A~%" s e))

;;部分文字列の取得
(format t (subseq "あいうえおabdde"))

;;特定の文字の場所を探して部分文字列取得とかありがちじゃない?
(setf target "あいうえお-かきくけこ")
(multiple-value-bind (s e)
    (cl-ppcre:scan "-" target)
  (if s
      (print (subseq target (1+ s)))))

;;文字列比較
;;普通の比較
(if (string= "aaa" "aaa")
    (format t "true"))

;;case-insensitiveな比較
(if (string-equal "aaa" "AAA")
    (format t "true"))

;;common lisp の eq、eql、equal、equalpは分かりにくくて、使い辛いと思う。
;;eq 同一性の比較 ただし同じ数値とかちゃんと比較できないこともある
;;ポインタの比較だけするから早い
(setf a 'a)
(setf b a)
(if (eq a b)
    (format t "true"))

;;eql 同一性の比較
(if (eql 1 1)
    (format t "true"))

;;equal リストなら内容が一致(同値)であればtrueになる
;;文字列もこれ使う(もしくはstring=)
;;他にもなにやらルールがあるが覚えられん
(if (equal '(a b c) '(a b c))
      (format t "a"))

;;equalp equalよりもさらにルーズなルール
;;大文字、小文字の区別をしなかったり、1と1.0が等しかったり
(if (equalp 1 1.0)
      (format t "a"))



;;数字→文字列
(setf ns (format nil "~A" 123.000))
(format t ns)

;;文字列→数字
(setf i (read-from-string "1234.000"))
(format t "~A" (1+ i))

;;文字列→数字その2
(setf i1 (parse-integer "123"))
(format t "~A" (1+ i1))

;;日付→文字列
;;;現在日付
(setf dt (get-universal-time))
;;;表示
(multiple-value-bind (s m h d mm y)
    (decode-universal-time dt)
  (format t "~A/~A/~A ~A:~A:~A" y mm d h m s))

;;;sbcl限定であればこんなのもOK
(sb-int:format-universal-time t dt)

(multiple-value-bind (s m h d mm y)
    (decode-universal-time dt)
  (sb-int:format-decoded-time t s m h d mm y))
  
;;文字→日付
;;;これも標準ではない。。。
;;;しょうがないからなにかないか探す。
;;;net-telent-dateでなんとかなりそう。
;;;が、asdfで入れようと思ったんだけど、ダウンロードがはじまらない。
;;;webサーバが死んでるのか??
;;;aptで入れれたりしないかな・・・とapt-cache search net-telent-dateとしてみた。
;;;xxxi@alex:~$ apt-cache search net-telent-date
;;;cl-net-telent-date - Common Lisp utilities for printing and parsing dates
;;;これでいいのかな??
;;;とりあえずこれにしてみた。
;;;使い方は↓な感じ
;;;しかしなんでこれ「.」区切りなんだろ。。。普通に「-」でいいじゃん。。。
(require 'net-telent-date)
(setf ymdhms (net.telent.date:parse-time "2008/07/04 12:37:06"))
(sb-int:format-universal-time t ymdhms)

;;標準出力に出力
;;;色々ある
(print "hello world")
(princ "こんにちは")

;;;formatの第一引数にtを渡すと出力さきは標準出力になる
(format t "こんにちは")

;;標準入力から読み込み
(do ((l (read-line *standard-input*) (read-line *standard-input*)))
    ((string-equal l "exit") 'EXIT)
  (format t "print:~A" l))

;;コマンドライン引数の取得
;;処理系依存らしい。sbclであれば*posix-argv*に入っている
(dolist (arg *posix-argv*)
  (format t "args:~A~%" arg))