トップ 最新 追記

follow ikegami__ at http://twitter.com

イネムリネズミ日記

いけがみを召喚するには、出現予定を参考にしてください。三週間前までにメールをくだされば、日程を追加するなどしてスケジュールに組み込むことができるかもしれません。勉強会や個人的な会合、中途採用面接などに応じます。日記に書かないことはこちら

2003|04|05|06|07|11|12|
2004|01|02|03|04|05|06|07|10|11|
2005|01|02|03|04|05|06|07|08|11|
2006|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|11|12|
2010|03|04|12|
2011|02|03|04|06|08|09|10|

2007-11-08 小春日和 [長年日記]

_ Emacs flymake-mode for Haskell

[2007-11-11] The setting is improved and works well. Please refer to EmacsWiki:FlymakeHaskell. The following description was OBSOLETED!.

flymake is a great tool for hacking which enables on-the-fly syntax checks of the files being edited using the external syntax check tool (usually the compiler).

Here is an extension of flymake for Haskell using ghc. Happy Haskell hacking as you like!

(require 'flymake)
  
;; flymake for Haskell
(defun flymake-Haskell-init ()
  (flymake-simple-make-init-impl
    'flymake-create-temp-with-folder-structure nil nil
    buffer-file-name
    'flymake-get-Haskell-cmdline))
(defun flymake-get-Haskell-cmdline (source base-dir)
  (list "ghc" (list "--make" "-fno-code" (concat "-i" base-dir) source)))          
(push '(".+\\.hs$" flymake-Haskell-init)
  flymake-allowed-file-name-masks)
(push '(".+\\.lhs$" flymake-Haskell-init)
  flymake-allowed-file-name-masks)
(push '("^\\(.*\\):\\([0-9]+\\):\\([0-9]+\\): \\(.*\\)$" 1 2 3 4)
  flymake-err-line-patterns)

[2007-11-08 22:30] After announcement on Haskell-Cafe, Thomas Schilling suggested to add the '-fno-code' flag to speed-up type checking. He also considered about the multi-line pattern matching problem on Emacs. Thanks Thomas! His advice has been already included in the above snippet.

Flymake displays warning/error messages at the pop-up window. If you do not use XEmacs, then try credmp's flymake-display-err-minibuf. I like the following setting.

(add-hook
 'haskell-mode-hook
 '(lambda () 
    (define-key haskell-mode-map "\C-cd" 
      'credmp/flymake-display-err-minibuf)))

TODO:

  • display warnings with -Wall option. Because some errors have several lines, we need a new buffer to show them.

P.S.

I'm not an expert in emacsen and referred to EmacsWiki: MultilineRegexp. However, the following setting does not work. Could you modify the above code and put into EmacsWiki: FlymakeHaskell, please?

(push
  '("^\\(.*\.hs\\|\.lhs\\):\\([0-9]+\\):\\([0-9]+\\):\\(\\(.*\n?\\)*\\)" 
   1 2 3 4) flymake-err-line-patterns)

The above demo video was created with the first implementation. The speed for type checking is now improved by Thomas's suggestion. I'm satisfied very much.


2007-11-23 小雪 [長年日記]

_ Speedtest - how fast are you?

1度目は248points, 2度目は293pointsでした。1度目でタイプミスが減点の元だと思ったので、2度目は慎重になった。ハマればもっと伸びると思うけど、ここらへんでやめておく。

2度目の結果:
You reached 293 points, so you achieved position 14545 on the ranking list
You type 367 characters per minute
You have 63 correct words and
you have 0 wrong words

14545番目か、世界の壁は厚いな(笑)

6 char/second は、こんどのお祭りに参加するには十分な速度である。10年前は、もっと速く正確にタイプできたものだが。学内コンテストで1位をとったのが私の唯一の自慢である(学業成績はさんざんであった)。

もひとつの特技は、タイプライタペアリング(Shift+2=@)もロジカルペアリング(Shift+2=")もタッチタイピングできることである。特技といえるほど凄いことなのかわからんが、どうして混乱しないのかといろんな人から聞かれた。単に、両方の使用歴が長いだけです。

だから、キーボードに関してはあまりこだわりがない。むしろもっとヘンタイになりたいので、今はHHK無刻印を使っている。

_ Highlight trailing whitespace in haskell files

;; Highlight trailing whitespace in haskell files
(add-hook 'haskell-mode-hook
          '(lambda ()
             (setq show-trailing-whitespace t)))

from [Haskell-cafe] emacs haskellers: r-stripping files becomes popular.

ハイライトするのはいい。元スレでは、手動で「文末の空白を削除しますか?mini-buffer(y/n)」というアプローチを取っているが、私は auto-save-buffers 派なのでダメ。というか、y/n は禁止だ(クリティカルな場合を除く)!rogueじゃないんだから。

他人のソースを触ったときにまずいじゃん、という意見も確かにわからないではないが、とりあえず以下のコードで運用してみる。全ての人にはお勧めできないので、意味がわからない人は .emacs に付け加えないように。

;; for Emacs21
(load-library "files")
(add-hook 'write-file-hooks
   '(lambda ()
      (if (eq major-mode 'haskell-mode)
        (delete-trailing-whitespace))))
;; for Emacs22
;; (add-hook 'before-save-hook
;;   '(lambda ()
;;     (if (eq major-mode 'haskell-mode)
;;       (delete-trailing-whitespace))))

[追記:]これでいいかと思ったが、auto-save-buffers と組み合わせて使うと、思考が止まったときに、カーソルがひょこひょこ動いてしまう問題に気がついた。ポイントのない行だけを delete-trailing-whitespace してもらいたいのだが、そのためにはもうちっと改造が必要だ。

そのためには、現在の point (というか、(what-line))をローカルな値に保存しておいたうえで、delete-trailing-whitespace とほぼ同じコードを実装すればいい...

ああっ、もう Haskell のために金輪際 EmacsLisp をいじらないと約束したではないか。うう。

[追記:2007-11-25]作り直した。これでうまくいくと思う。


2007-11-25 冬日和 [長年日記]

_ Emacsいじり

もうやらねえ!と何回誓ったことか。もうやらない(n回目)。

% wc .emacs etc/emacs-config/*.el
(snip)
    1221    3796   38749 total

_ "delete-trailing-whitespace-except-for-the-current-line" for auto-save-buffers

現在のカーソルがある行を除いた全ての行の文末の空白を取り除く EmacsLisp 関数を作ってみた。 これで、先日のカーソルひょこひょこ病は直った。

(defun delete-trailing-whitespace-except-for-the-current-line ()
  "Delete all the trailing whitespace across the current buffer,
except for the current line where the point is. All whitespace
after the last non-whitespace character in a line is deleted. This
respects narrowing, created by \\[narrow-to-region] and friends. A
formfeed is not considered whitespace by this function."
  (interactive "*")
  (let ((opoint (point)) start l)
    (save-match-data
      (save-excursion
        (save-restriction
          (goto-char (point-min))
          (widen)
          (forward-line 0)
          (setq start (point))
          (goto-char opoint)
          (forward-line 0)
          (setq l (1+ (count-lines 1 (point))))
          (goto-char (point-min))
          (while (and (re-search-forward "\\s-$" nil t)
                      (not (= (count-lines (point-min) (point)) l)))
            (skip-syntax-backward "-" (save-excursion (forward-line 0) (point)))
            ;; Don't delete formfeeds, even if they are considered whitespace.
            (save-match-data
              (if (looking-at ".*\f")
                  (goto-char (match-end 0))))
            (delete-region (point) (match-end 0))))))))

中身は、GNU Emacs21 に付随する simple.el で定義されている what-line と delete-trailing-whitespace をつなげたようなものである。ライセンスはもちろん GPL。

what-line はカーソルのある行を mini-buffer に文字列を表示する関数だったので、 カーソルのある行番号を取得するためには (count-lines (point-min) (point)) する必要がある。 しかし、ここには罠があって、もしバッファが narrowing されていると、取得された値が望みの値 と違うのである。とほほ。

これを作ったあとで、Conal から「なんで行末の空白が気になるんだよ(気にしなければいいじゃ ん)」というまっとうな返事が Haskell-cafe に届いていた。いや、気にしなくてもいいのだけれど、 darcs で管理しているときに、行末の空白という minor change が嫌なんでありまするよ。

_ TempoSnippets for Emacs21

よくわかってないんだけど、次の変更で Emacs21 (on tty) も動くみたいよ。 単にエラーが出る行をコメントアウトしただけなので、 まだ問題が残っているかもしれないが。tty では :underline ができないってことなのかな。

--- /Users/ikegami/install/tempo-snippets.el    2007-11-26 05:26:24.000000000 +0900
+++ /usr/local/share/emacs/site-lisp/tempo-snippets.el  2007-11-26 05:36:41.000000000 +0900
@@ -101,16 +101,16 @@
   "*Face used for editable text in tempo snippets."
   :group 'tempo-snippets)
 
-(defface tempo-snippets-auto-face
-  '((((background dark)) (:underline "steel blue"))
-    (((background light)) (:underline "light cyan")))
-  "*Face used for automatically updating text in tempo snippets."
-  :group 'tempo-snippets)
-
-(defface tempo-snippets-auto-form-face
-  '((default (:inherit 'tempo-snippets-auto-face)))
-  "*Face used for text in tempo snippets that is re-evaluated on input."
-  :group 'tempo-snippets)
+;; (defface tempo-snippets-auto-face
+;;   '((((background dark)) (:underline "steel blue"))
+;;     (((background light)) (:underline "light cyan")))
+;;   "*Face used for automatically updating text in tempo snippets."
+;;   :group 'tempo-snippets)
+
+;; (defface tempo-snippets-auto-form-face
+;;   '((default (:inherit 'tempo-snippets-auto-face)))
+;;   "*Face used for text in tempo snippets that is re-evaluated on input."
+;;   :group 'tempo-snippets)
 
 (defcustom tempo-snippets-interactive t
   "*Insert prompts for snippets.
@@ -260,7 +260,7 @@
         ;; XXX: this assumes on-region to be nil
         (tempo-insert eval-result nil)
         (setq overlay (make-overlay beg (point)))
-        (overlay-put overlay 'face 'tempo-snippets-auto-form-face)
+        ;; (overlay-put overlay 'face 'tempo-snippets-auto-form-face)
         ;; evaporating would cause problems when form before prompt!
         (overlay-put overlay 'tempo-snippets-form form)
         (overlay-put overlay 'modification-hooks
@@ -364,7 +364,7 @@
       (let ((mirrors (overlay-get source 'tempo-snippets-mirrors)))
         (push overlay mirrors)
         (overlay-put source 'tempo-snippets-mirrors mirrors))
-      (overlay-put overlay 'face 'tempo-snippets-auto-face)
+;;       (overlay-put overlay 'face 'tempo-snippets-auto-face)
       (overlay-put overlay 'modification-hooks
                    '(tempo-snippets-delete-overlay))
       (overlay-put overlay 'insert-in-front-hooks

デフォルトの face は背景が水色で、それは嫌なので変更した。

(custom-set-faces
 '(tempo-snippets-editable-face ((((background dark)) (:background "blue")))))

_ Haskell の動的補完

via Emacs の略語展開のメモ ー ありえるえりあ.

試行錯誤で Haskell 用の動的補完を作っていきますよ。とりあえず、今はこれだけ。

(load-library "tempo-snippets")
(tempo-define-snippet "haskell-module"
  '("module " (p "Module: " module) " (" n ") where" n)
  "module"
  "Insert a Haskell module."
  nil)
(tempo-define-snippet "haskell-import"
  '("import " (p "Module: " module) "")
  "import"
  "Insert a declaration of an importing module in Haskell."
  nil)
(tempo-define-snippet "haskell-data-0"
  '("data " (p "Datatype: " datatype) " = " (s datatype))
  "data0"
  "Insert an algebraic datatype in Haskell."
  nil)
(tempo-define-snippet "haskell-data-1"
  '("data " (p "Datatype: " datatype) " = " (s datatype) " { " n > "}")
  "data1"
  "Insert an algebraic datatype in Haskell."
  nil)
(tempo-define-snippet "haskell-data-2"
  '("data " (p "Datatype: " datatype) " = A" n > "| B")
  "data2"
  "Insert an algebraic datatype in Haskell."
  nil)
(tempo-define-snippet "haskell-type"
  '("type " (p "Type: " type) " = " n)
  "type"
  "Insert a type definition in Haskell."
  nil)
(tempo-define-snippet "haskell-newtype"
  '("newtype " (p "Newtype: " newtype) " = " (s newtype) n)
  "newtype"
  "Insert a newtype definition in Haskell."
  nil)
(tempo-define-snippet "haskell-deriving"
  '(> "deriving (" (p "Class: " class) ")")
  "deriving"
  "Insert a deriving clause in Haskell."
  nil)
(tempo-define-snippet "haskell-function"
  '((p "Name: " name) " :: " (p "Type: " type) n (s name) " = ")
  "function"
  "Insert a function in Haskell."
  nil)
(tempo-define-snippet "haskell-main"
  '("main :: IO ()" n "main = do ")
  "main"
  "Insert the Haskell main function."
  nil)

これで、Haskell でも Tempo-Snippets Demo みたいなことができるわけです。やったね。

_ FlymakeHaskell

perl script に恥ずかしいバグがあったので修正しておきました。


2007-11-30 釣瓶落とし [長年日記]

_ LiveCoding#5

直前の報告になってしまいましたが、明日 (12/1, Sat) の Live Coding #5 に参加します。 体調不良で参加が危ぶまれていたのですが、どうにかなりそうです。 まだ、定期的に頭痛くなったり、いろいろアレですので、当日は弱々しいでしょう。 もうすでに参加申込は満員で締め切っておりますので、知らなかった方は残念でした。

22:00 終了ということなのですが、普段の私は就寝する時間です。なので、家に帰らずにホテルに泊まることにしました。 土曜日って宿泊料が一番高い日みたいですね。ビンボーなのに。でも、こんなんで体調崩したら本当のアホだから。 もしかしたら、途中で退場することになるかもしれないです。

さて、 20 分で何かを作るということなので、小さな題材を選びました。andy 氏の書いた Htrace - Haskell Raytracer の添削をします。これは Prelude ライブラリのみを使ったソースコードでコメントも豊富です。 Haskell を学びたての人には、良い教材になると思います。

Ray tracer は、光と反射の物理学をふんだんに使います。そのため、時間のかかる計算を必要とします。 Haskell コンパイラ ghc は高品質な最適化を施してくれますが、 それとは別に、ソースコードの書き方を工夫することで、より一層の高速化を図ることができます。

今月出た面白い比較 (Benchmark) があります。 Benchmarking ray tracing, Haskell vs. OCaml という Lennart Augustsson 先生 (Chalmers大) の記事では、ray tracer を書くときの 4 つの Haskell tips を紹介しています。 これを使うと、動作がだいぶ速くなるのですね。

ただし、コードに凝りすぎると速度が向上する半面、聴衆が 20 分で理解するには難易度が上がってしまいます。 その場で考え、タイプする私もしんどいです。そこらへんのトレードオフを加味した結果、中途半端にチューニングしたコードをお見せすることにします。 それでも 7 char/s のタイプをしなければ、時間内に終らないので相当厳しそう。 かといって 1 文字変数とか使ったら、聴衆の皆さんはわけがわからないからなあ。

私的には、私の発表より他の参加者のみなさんの発表を聞きたいです。 誘ってくださった氏久さんと、会場を提供してくださった 株式会社 グッデイ 様に感謝いたします。


出現予定(召喚方法 ikegami@madscientist.jp):

RSS feed を再開しました。RSS の思想を尊重するために全文配信はしません、あしからず。