lispとrubyとpythonと(common lisp) ver2

ここんとこずっと忙しくて忘れかけてるし復習をかねて昔書いたエントリを更新。
増えたのはcl-interpolの部分くらい。
あとコメントの形式は
http://tips.lisp-users.org/common-lisp/index.cgi?逆引きCommonLisp書式
と一緒にする。
こういうのが↑増えて、Lispがあちこちで使われるようになって、いつか仕事で使える日もくる・・・といいな・・・。

;;コメントは;で始める

;;標準出力に表示
(print "こんにちは 1")
;->"こんにちは 1" 

;;;formatも機能多すぎ。
;;;format関数の情報はここが一番まとまった情報があると思う
;;;http://www.yuasa.kuis.kyoto-u.ac.jp/~hiraisi/format-func.html
;;;改行は~%
(format t "こんにちは 4~%")
;->こんにちは 4

;;;フォーマット
(format t "こんにちは~A~%" "世界")
;->こんにちは世界

;;;タブ文字はこんな感じで表示できる
(format t "こんにちは~Cこんにちは~%" #\tab)
;->こんにちは こんにちは

;;;タブではないけどレイアウト調整には~xTも使える
(format t "あいうえお~@tかきくけこ")
;->あいうえお かきくけこ

(format t "あいうえお~4@tかきくけこ")
;->あいうえお    かきくけこ

;;nilを第一引数にすればフォーマットした文字列が返る
(format nil "こんにちは~A" "世界")
;=>"こんにちは世界"

;;;これでも文字列に出力
(with-output-to-string (strm)
  (format strm "こんにちは ~A" "世界"))
;=>"こんにちは世界"

;;エスケープシーケンスがないとツラい
;;標準ではない・・・
;;しょうがないのでCL-INTERPOLを使う
;;asdfでインストールして
;;cl-interpol:enable-interpol-syntaxを呼び出すと\nとか\tを使えるようになる
(require 'cl-interpol)
(cl-interpol:enable-interpol-syntax)

;;色々な引用符を使えるようになる
;;ディスパッチ文字は?
;;下記どれでもいける
;;ただしslime上からC-x C-eで送ると
;;#?|hello|
;;#?(hello)
;;はエラーになる

;; #?"hello"
;; #?r"hello"
;; #?x"hello"
;; #?xr"hello"
;; #?'hello'
;; #?|hello|
;; #?#hello#
;; #?/hello/
;; #?(hello)
;; #?[hello]
;; #?{hello}
;; #?<hello>

;;引用符のエスケープは\
(print #?"hello \"list\" world")
;;->"hello \"list\" world" 

;;\のエスケープは当然\\
(print #?"hello \\list\\ world")
;;->"hello world"

;;\nが使える
;;newlineは\n
(print #?"hello\nworld")
;;->"hello
;;"world"

;;tabは\t
(print #?"hello\tworld")
;;->"hello world"

;;upperとかlowerもできる
;;\lでその後の一文字を小文字にする
(print #?"\lHELLO WORLD")
;->"hELLO WORLD" 

;;\uでその後の一文字を大文字にする
(print #?"\uhello world")
;->"Hello world"

;;\Lで\Eまでのその後の文字を小文字にする 
(print #?"\LHELLO WORLD\E HELLO WORLD")
;->"hello world HELLO WORLD" 

;;\Uで\Eまでのその後の文字を大文字にする 
(print #?"\Uhello world\E hello world")
;->"HELLO WORLD hello world" 

;;文字列への式の埋め込み
;;$lt;式>
;;$(式)
;;$[式]
;;どれでもいい

(let ((a "あいうえお")
      (b "かきくけこ"))
  (print #?"hello $(a) world")
  (print #?"hello $<a> world")
  (print #?"hello $[b] world")
  (print #?"hello $[(+ 1 2)] world")
  (print #?"hello $[(list 1 2 3)] world"))
;->"hello あいうえお world" 
;  "hello あいうえお world" 
;  "hello かきくけこ world" 
;  "hello 3 world" 
;  "hello (1 2 3) world" 

;;ほんとはcl-ppcreとの併用が便利
(require 'cl-ppcre)
;;文字で書くと\wとかを\\wと書かないといけない
(cl-ppcre:all-matches-as-strings "\\w+" "one foot in the grave")
;=>("one" "foot" "in" "the" "grave")

;;正規表現リテラルなら\wでOK
(cl-ppcre:all-matches-as-strings #?/\w+/ "one foot in the grave")
;=>("one" "foot" "in" "the" "grave")


;;関数定義
(defun fun0(msg)
  (format t "「~A」を引数としてfunが呼ばれた~%" msg))

(fun0 "hello")
;->「hello」を引数としてfunが呼ばれた

;;条件分岐
(defun fun1(n)
  (if (< n 10)
      (format t "10未満~%")
      (format t "10以上~%")))

(fun1 1)
;-> 10未満

(fun1 10)
;->10以上
    
(defun fun2(n)
  (cond 
    ((= n 0) 
     (format t "0です~%"))
    ((< n 5)
     (format t "5未満です"))
    ((= n 5) 
     (format t "5です"))
    ((> n 5)
     (format t "5より大きいです"))))

(fun2 0)
;->0です

(fun2 6)
;->5より大きいです

;;繰り返し
(defun fun3(n)
  (do ((i 0 (1+ i)))
      ((>= i n) nil)
    (format t "繰り返し~A回目~%" i)))

(fun3 3)
;->繰り返し0回目
;  繰り返し1回目
;  繰り返し2回目

(defun fun4(n)
  (dotimes (i (1+ n) nil)
    (format t "繰り返し~A回目~%" i)))

(fun4 3)
;->繰り返し0回目
;  繰り返し1回目
;  繰り返し2回目
;  繰り返し3回目

;;;loopはもう言語内言語と思った方がよい
;;;使いこなせない。。。
(defun fun5(n)
  (loop for i  from 0 to n
       collect (format t "繰り返し~A回目~%" i)))

(fun5 3)
;->繰り返し0回目
;  繰り返し1回目
;  繰り返し2回目
;  繰り返し3回目

;;;こんなのもある(series)
(require :series)
(series::install)

(defun fun5_1(n)
  (collect (#M(lambda (i)
  (format t "繰り返し~A回目~%" i)
  i)
       (series:scan-range :upto (1- n)))))

(fun5 3)
;->繰り返し0回目
;  繰り返し1回目
;  繰り返し2回目
;  繰り返し3回目


;;定数定義
;;(defconstant const-value "定数")

;;変数宣言(スペシャル変数)
(defvar sp-value "スペシャル変数" "変数の説明・・・")

;;レキシカル変数
(let ((s "レキシカル変数"))
  (format t "変数の値:~A~%" s))
p
;;クラス定義
(defclass cls0 nil
    ((slot0)
     (slot1)))

;;;コンストラクタ
(defmethod initialize-instance :after ((o cls0) &rest initargs)
  (with-slots (slot0 slot1) o
    (setf slot0 "初期値")
    (setf slot1 "初期値")))

;;;メソッド
(defmethod set-slots ((o cls0) val0 val1)
  (with-slots (slot0 slot1) o
    (setf slot0 val0)
    (setf slot1 val1)))

(defmethod print-slots ((o cls0))
  (with-slots (slot0 slot1) o
    (format t "slot0:~A~%" slot0)
    (format t "slot1:~A~%" slot1)))
  
;;;継承
(defclass cls1 (cls0)
  ((slot2 :accessor cls1-slot2
   :initform "初期値"
   :initarg slot2)))

;;;オーバーライド
(defmethod print-slots ((o cls1))
  (with-slots (slot0 slot1 slot2) o
    (format t "cls1-slot2:~A~%" slot2)))

(setf o (make-instance 'cls0))
(print-slots o)
;->slot0:初期値
;  slot1:初期値

(set-slots o "スロット1の値" "スロット2の値")
(print-slots o)
;->slot0:スロット1の値
;  slot1:スロット2の値

(setf o (make-instance 'cls1))
(print-slots o)
;->cls1-slot2:初期値

(set-slots o "スロット1の値" "スロット2の値")
(print-slots o)
;->cls1-slot2:初期値

;;ラムダ式
(setf f #'(lambda (s)
     (format t "~A~%" s)))

;;;呼び出し
(funcall f "こんにちは")
;->こんにちは

;;;これでもよびだせる
(apply f '("こんにちは"))
;->こんにちは

;;;リテラルだからこれでもオケ(意味ないけど)
((lambda (s) (format t "~A~%" s)) "こんにちは")
;->こんにちは

;;クロージャ
(defun make-decorator(prefix suffix)
  #'(lambda (s)
      (concatenate 'string prefix s suffix)))

(setf decorator (make-decorator "<" ">"))
(format t (funcall decorator "html"))
;-><html>