2018年1月26日金曜日

タブレットスタンド

 また、iPadProの影響で背筋を痛めそうだったのでタブレットスタンドというやつを買った。

 これで寝転がっていろいろできるぜ、と思っていたのだけれど。
 タップしたり、スワイプしたりするたびに、びよ〜〜んびよ〜〜んとiPadが揺れる。おかげですぐに船酔い状態。気分が悪くなってしまった。
 あかん。

2018年1月24日水曜日

fletとletf

 「Land of Lisp」ではじめてfletというものを知った。
 letの関数版。関数内にローカルの関数をつくれるものらしい。elispにもcl.elにあった。同じようなことはletの変数にlambdaをセットしてfuncallしてやってみたことはあるけれど。
 便利そうだけど、あんまり使わないかも、とか、思っていたら。
 そういやつくった関数に何か皮をかぶせた処理をいれたい、とか、よくあることだった。そういうときは別の関数をつくって皮をかぶせていたけれど、fletに押し込んでやれば、いいのか……。
 なるほど。

 で、fletの*HELP*を読んでいたらletfというものがあることを知る。

(setq wrk '(1 2 3))
(1 2 3)

(cl-letf (((nth 1 wrk) 44))
  (nth 1 wrk))
44

wrk
(1 2 3)

 おっ、すげえ、と思ったけれど。

(cl-letf (((nth 1 wrk) 44))
  wrk)
(1 2 3)

 となってしまった。
 なんとなく、(1 44 3)が返ってくるような気がしていたのだけど。
 もしかしたら(nth 1 wrk)の部分を44に差し替えているだけなのかな? と思ってmacroexpandしてみたら。

(macroexpand '(cl-letf (((nth 1 wrk) 44))
        (nth 1 wrk)))

(let* ((c (nthcdr 1 wrk)) 
       (old (car c)))
  (unwind-protect 
      (progn (setcar c 44)
      (nth 1 wrk))
    (setcar c old)))

(macroexpand '(cl-letf (((nth 1 wrk) 44))
  wrk))
(let* ((c (nthcdr 1 wrk)) (old (car c)))
  (unwind-protect (progn (setcar c 44) 
    wrk) 
    (setcar c old)))

 あれ?
 最初のやつは44が返ってくるのに、なんで二番目のやつは(1 44 3)が返ってこないんだろう……? というか、CommonLispにはデフォルトでletfってないのかな。「undefined function: LETF」になってしまったけど。

メモ:
#:g1: Emacs Lispのcl-fletは使いものにならないなんてことはない

2018年1月22日月曜日

スクリプト放浪

 パソコンを長々と使っていると、いろいろと作業を自動化したいわけで。
 よくちょこちょことスクリプトを書いたりしていた。
 shellスクリプトからsed&awkを経てperlに至り。途中、ruby1をつまみ食いしたりして。DOSバッチはUNIXツールのパチモンをいれていたのでawkやperlスクリプトという感じ。さらにtcl/Tkも使ったことがあった。これは画面がつくれたのがよかった。
 そうこうしているうちに。
 一番使うのはEmacsだったこともあってelispを勉強しはじめ2。それでもperlやtcl/Tk、shellを使っていたのだけど、ある日突然、elispで充分じゃね、と気づいてからはelisp一本やり。3以来、elisp以外はほとんと使っていない。
 CommonLispやschemeをインストールしてみたりしているけれど、なんだかんだとelispで充分で、どうやら個人的なスクリプト環境はナッシュ均衡に逹っしてしまったらしい。

Footnotes:

1

初期のruby

2

付属のelispのinfoを読みふけった。

3

WindowsでもMacでもFreeBSDでも使えることだし。

2018年1月20日土曜日

再帰がすごいのか、listがすごいのか

 文字列と数値が混在していてつねに数値としてあつかいたいのに〜、と苛々することがよくあったので下記のような関数をでっちあげた。数値としてあつかいたいとき、無条件に使うわけである。

(defun y-num(x)
  (cond ((null x) 0)
 ((numberp x) x)
 ((stringp x) (string-to-number x))))

(y-num "123")
123

 ずっとそうやって使っていたんだけど、ふとlistも対応しよう、と思って対応してみたところ。

(defun y-num(x)
  (cond ((null x) 0)
 ((numberp x) x)
 ((stringp x) (string-to-number x))
 ((listp x)(mapcar 'y-num x))))

(y-num '("1" "2" "3"))
(1 2 3)

 あっ、と思った。これだけで入れ子のlistでもOKじゃん。

(y-num '("1" ("1" "2" "3") "2" "3"))
(1 (1 2 3) 2 3)

 再帰ってすげー、と思って。
 いやいや、そうか、と思い直した。
 Lispで再帰がよく使われるのはlistが基本構造なので、むちゃくちゃ相性がいいからなんだ。

2018年1月7日日曜日

遅延プログラミング

 最近、読んだ「Land of Lisp」の中に遅延プログラミングがでてきた。
 ポール・グラハムの「On Lisp」にもあったよなぁ1、とか、考えていてふと気づいた。レキシカルスコープがサポートされたんだからelispでも可能なんじゃね?
 試してみた2

;; -*- lexical-binding: t; -*-

(defmacro lazy(body)
  (let ((forced (gensym))
 (value (gensym)))
    `(let ((,forced nil)
   (,value nil))
      (lambda()
 (unless ,forced
   (setf ,value (progn ,body))
   (setf ,forced t))
 ,value))))

(defun force(lazy-value)
  (funcall lazy-value))

(defmacro lazy-cons(a d)
  `(lazy (cons ,a ,d)))

(defun lazy-car(x)
  (car (force x)))

(defun lazy-cdr(x)
  (cdr (force x)))

(defun lazy-nil()
  (lazy nil))

(defun lazy-null(x)
  (null (force x)))

(defun make-lazy(lst)
  (lazy (when lst
   (cons (car lst)(make-lazy (cdr lst))))))

(defun take(n lst)
  (unless (or (zerop n)(lazy-null lst))
    (cons (lazy-car lst)(take (1- n)(lazy-cdr lst)))))

(defun take-all(lst)
  (unless (lazy-null lst)
    (cons (lazy-car lst)(take-all (lazy-cdr lst)))))

 いちおう動いているみたいだ。
 注意。「lazy」はレキシカルスコープの環境で動かすこと。考えてみれば、当たり前なんだけど、最初、うまく動かなくて考えこんでしまった。lazyの定義はレキシカルスコープでやって、実行をダイナミックスコープ環境でやっていたので。closureになってなかった。
 それにしてもcl.elでlabelsも使えるんだ。知らんかったわ。

;; -*- lexical-binding: t; -*-
(setq wrk (labels ((f (n)
        (lazy-cons n (f (1+ n)))))
     (f 1)))

(take 10 wrk)

Footnotes:

1

確認してみたら3ページほどの記述だった。

2

マクロがそのまま、使えなかったので適当に変更した。

2018年1月6日土曜日

ついにThinkPadのディスプレイが……

 お亡くなりになってしまった。
 外部ディスプレイにつなげれば、まだ使えるけれど。そろそろ後継を考えなくてはなぁ。古くなったiPhoneとか、iPadが使えれば、いいのだけれど。使えないんだよなぁ。ハイスペックなのに。