Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 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 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2009-03-30

PLOT

| 00:19 | PLOT - わだばLisperになる を含むブックマーク はてなブックマーク - PLOT - わだばLisperになる

ILC2009でかの高名なDavid Moon氏がマクロの話をするというので期待していたのですが、蓋をあけてみれば、マクロの話というよりもMoon氏の新しいLISP系言語の話でした。

Moon氏本人により、資料が公開されています。

ぱっと見た感じでは、基本的にCLOS風のOOP+マクロなのでかなりDylan風にみえるのですが、#lisp_schemeでd:id:lequeさんがつぶやいていたように自分もCyanっぽい面もあるなーと思いました。

資料の量が多いので自分は全容が把握できないのですが、Paul Graham氏のArcについてアドバイスしていたことや、Dylanでのアイディアを発展させたようなところもあるように思います。

いまのところ実用的な用途に必要である機能の詳細は記述されていないようで、実装も公開されていないようなのですが、公開されたらいじって遊んでみたいなと思いました。

なんにしろ言語処理系作成マニアの方にはネタの宝庫な気がします。

ということで詳しい方の解説希望!!

2009-03-29

スペシャルではないsymbol-valueを持つシンボルの命名法

| 23:30 | スペシャルではないsymbol-valueを持つシンボルの命名法 - わだばLisperになる を含むブックマーク はてなブックマーク - スペシャルではないsymbol-valueを持つシンボルの命名法 - わだばLisperになる

ぼーっとリリカル☆Lisp開発日記 » ページが見つかりませんでしたをなるほどーと思いつつ眺めていました。

スペシャル変数のシンボルには*special*のように耳当てを付けましょうというのはCommon Lispのスペシャル宣言の性質上確かに推奨されるべきことだと思うのですが、以前から疑問に思っていた「スペシャルではない大域変数にはなんて名前をつけたら良いんだろう」というのを思い出しました。

(set 'foo 33)

のfooみたいなやつですね。

fooのsymbol-valueはどこからでも参照できるんですが、スペシャルではないので

(set 'foo 33)

(let ((foo 66))
  (list foo (symbol-value 'foo)))
;=> (66 33)

となるわけですね。

ローカルにスペシャル宣言すれば

(let ((foo 66))
  (declare (special foo))
  (list foo (symbol-value 'foo)))
;=> (66 66)

ともできますが…。

それはさておき、どうもスペシャル変数に耳当てを付けるのはCommon Lispからの決まりのようで、MacLISPやLisp Machine Lispだと大域変数にも普通に付けてるようなところもあります。

定数だとやたら長い名前をつけたりするんですが、こういう場合もやたら長い、global-foo-variableのような名前を付けておけば良いのでしょうか。

ちなみに、実際問題として、これの命名で困ることはないと思いますので適当に流して下さい(ノ∀`)

acons

| 22:42 | acons - わだばLisperになる を含むブックマーク はてなブックマーク - acons - わだばLisperになる

quekさんのletter: CL パッケージの最も長いシンボルを SERIES(series:collect-max)でを読んで、なるほどと思いつつぼーっとしながら、元のSERIESのコードをdo-symbolsで書いていたのですが、最初に

(let (res)
  (do-symbols (s :cl (caar (sort res #'> :key #'cdr)))
    (push (cons s (length (string s))) res))
;=> LEAST-POSITIVE-NORMALIZED-DOUBLE-FLOAT

という風に書きました。

しかし、せっかくaconsがあるんだからaconsを使おうということで、

(let (res)
  (do-symbols (s :cl (caar (sort res #'> :key #'cdr)))
    (setq res (acons s (length (string s)) res))))
;=> LEAST-POSITIVE-NORMALIZED-DOUBLE-FLOAT

としてみましたが、やはりaconsやpairlisは使い勝手が微妙です。

TAOなら、

(let (res)
  (do-symbols (s :cl (caar (sort res #'> :key #'cdr)))
    (!!acons s (length (string s)) !res)))

みたいに書けるんだと思いますが、こういう時には良いですね。

…以上、quekさんの元エントリとも全く関係ない、どうでも良い話でした(´▽`*)

2009-03-28

CLは標準でシンボル名の大文字小文字を区別して読まない件

| 02:01 | CLは標準でシンボル名の大文字小文字を区別して読まない件 - わだばLisperになる を含むブックマーク はてなブックマーク - CLは標準でシンボル名の大文字小文字を区別して読まない件 - わだばLisperになる

気付けばShibuya.lispの黒田さんのTTからもう一ヶ月経つのですが、割と誤解が多いのでフォローで書いておきたいと思っていて書けてなかったことに、CLはシンボル名の大文字小文字を区別しない件についてがあります。

大文字と小文字を小文字を区別しない件については、自分は区別しない方が好き派なのですが、今どきの主流の考えでは、「区別しないなんて不便だー」となるのではないかと思います。

実際に、「区別しなんて時代錯誤だー」とか、「予約語とバッティングするのがいやだー」等をみかけました。

ここで、CLはどういうことになっているのかを、解説しますと、

まず、

1) 文字列の中身は区別される→ "foo"と"FOO"は別物

です。どんな状況でも一緒ではなく、文字として大文字しかないのではありません。

2) CLでは、シンボルはリード時に大文字にされて解釈される

ので、fooは、FOOとして読まれます。エスケープすれば、大文字小文字の区別を保持できますので、|foo|とfoo(FOO)は別物で、簡単に言えば、小文字で書いても大文字に直されるという感じです。

ということで先約のある名前は、CLでは、PIのようになっていますので、|pi|や、|pI|と書けばバッティングは回避できることになりますし、CLでは名前に記号も使えますので、まず問題になることはありません。(どちらかというと大文字小文字を区別するか否かということよりも名前に記号が使えない方が余程不便に感じます。)

そして、これから分かるように、区別できないわけではないということで、「区別しなんて時代錯誤だー」も「予約語とバッティングするのがいやだー」も当っていないということになります。(さらにやろうと思えば、標準機能で大文字小文字を区別する方法はありますので、そちらの感覚に合せることも可能です)

つまり、機能としては、区別しないこともできるし、区別もできるということになるのですが、デフォルトで区別する他の言語の処理系と比較すると、仮にその処理系に、大文字と小文字の区別をしないための記法が存在しないならば、CL方式の方が両方を書き分けられる分、表現力は上とも言えます。

箸を使わない文化圏からみれば、箸を使って食べるのはへんてこで不便にしか見えないようなものかもしれません。

自分は、このようなCLの性質に慣れてしまっているので、こちらの方が心地良くて、また色々記述を工夫して遊べるので断然こちらの方が好きです。

しかしながら、UNIXを代表する文化は区別する派であり、そちらが主流であるのは明白なので、時代は区別する方向に流れて行くのだろうなー思うと若干寂しいところです。

2009-03-22

GaucheでSLIME

| 22:43 | GaucheでSLIME - わだばLisperになる を含むブックマーク はてなブックマーク - GaucheでSLIME - わだばLisperになる

gaucheでも、SLIMEが使えたら、もっとGaucheのコード書くようになる気がするなあと常々思っていたのですが、ついに、swank-gaucheが登場しました!

まだ発展途上ということですが、今のところでもシンボルの補完と、マクロ展開ができるのでSLIMEに慣れた方なら便利に使えると思います!

自分的にはArglistが早く実装されてくれると物覚えの悪い自分には嬉しいので、期待して待ちたいです。…いや、自分でもできそうなら作ってみたいです(笑)

lequeさんのgauche-modeと合体するとかなり便利に使えるんじゃないかと想像しているのですが、とりあえず思い付いたユーティリティを書いてみました。

  1. Gaucheのリファレンスを引く
  2. マクロ展開をプリティプリント

の2点です。

プリティプリントには、ppが必要です。

基本的な設定(swank-gauche.scm参照)

;; Emacs Lisp
(pushnew "<path-to-slime-dir>/slime/contrib" load-path :test #'equal)
(require 'slime-scheme)
(setq slime-lisp-implementations
      '((gauche ("gosh") :init gauche-init)))

(defun gauche-init (file encoding)
  (format "%S\n\n"
          `(begin
             (add-load-path "<path-to-slime-dir>/slime/contrib") ;; add load path to swank-gauche.scm
             (require "swank-gauche")
             (import swank-gauche)
             (start-swank ,file))))

(defun gauche ()
  (interactive)
  (slime 'gauche))

(defun find-gauche-package ()
  (interactive)
  (let ((case-fold-search t)
        (regexp (concat "^(select-module\\>[ \t']*"
                        "\\([^)]+\\)[ \t]*)")))
    (save-excursion
     (when (or (re-search-backward regexp nil t)
               (re-search-forward regexp nil t))
       (match-string-no-properties 1)))))

(setq slime-find-buffer-package-function 'find-gauche-package)
(setq slime-complete-symbol-function 'slime-complete-symbol*)

Gaucheのリファレンスを引く(C-c C-d C-sh-h)

;; Emacs Lisp
(progn
  (defun gauche-ref-lookup ()
    (interactive)
    (browse-url
     (format "http://practical-scheme.net/gauche/man/?l=jp&p=%s" (thing-at-point 'symbol))))
  
  (define-key slime-mode-map [(control ?c) (control ?d) (shift ?h)] 'gauche-ref-lookup))

マクロ展開をプリティプリント

;; swank-gauche.scm
(use util.match)
(use pp)

(define (subst-by subst pred lst)
  (define self (cut subst-by subst pred <>))
  (match lst
    (() ())
    (((? pred head) . tail)
     (cons (subst head) (self tail)))
    (((? pair? head) . tail)
     (cons (self head) (self tail)))
    ((head . tail)
     (cons head (self tail)))))

(defslimefun swank-macroexpand-1 (string)
  (let ((sexp (read-from-string string)))
    (if (eof-object? sexp)
        ""
        (with-output-to-string 
          (lambda ()
            (pretty-print 
             (subst-by identifier->symbol identifier?
                       (macroexpand-1 sexp))))))))

(defslimefun swank-macroexpand-all (string)
  (let ((sexp (read-from-string string)))
    (if (eof-object? sexp)
        ""
        (with-output-to-string 
          (lambda ()
            (pretty-print 
             (subst-by identifier->symbol identifier?
                       (macroexpand-1 sexp))))))))
  • 動作具合(slime-macroexpand-1)
(match lst
    (() ())
    (((? pred head) . tail)
     (cons (subst head) (self tail)))
    (((? pair? head) . tail)
     (cons (self head) (self tail)))
    ((head . tail)
     (cons head (self tail))))

;==>
(if
 (null? lst)
 ((lambda () ()))
 (if
  (pair? lst)
  (if
   (pred (car lst))
   ((lambda (head tail) (cons (subst head) (self tail))) (car lst) (cdr lst))
   (if
    (pair? (car lst))
    ((lambda (head tail) (cons (self head) (self tail))) (car lst) (cdr lst))
    ((lambda (head tail) (cons head (self tail))) (car lst) (cdr lst))))
  (match:error lst)))

2009-03-20

Rubyの話題は普通のはてな日記で

| 18:37 | Rubyの話題は普通のはてな日記で - わだばLisperになる を含むブックマーク はてなブックマーク - Rubyの話題は普通のはてな日記で - わだばLisperになる

自分的にはこのブログはLISP専門という位置付けで、ここでRubyとかのことを書いてもまとまりがないのでRubyやその他雑多な話題は、グループじゃない方の通常のブログを活用してみることにしました。

多分、Web系のことや個人的な趣味のエントリがメインになる気がしていますが、RubyやRailsの質問/疑問を沢山書くつもりなので、どうか色々教えて下さい。どうか色々教えて下さい。

RubyでL-99 (P9〜P13)

| 02:17 | RubyでL-99 (P9〜P13) - わだばLisperになる を含むブックマーク はてなブックマーク - RubyでL-99 (P9〜P13) - わだばLisperになる

適当につらつらと書いておりますが、折角なのでRSpecでテストも書きたいところ。

次は書いてみよう!

# P09 (**) Pack consecutive duplicates of list elements into sublists.
#     If a list contains repeated elements they should be placed in
#     separate sublists.
#
#     Example:
#     * (pack '(a a a a b c c a a d e e e e))
#     ((A A A A) (B) (C C) (A A) (D) (E E E E))
class Array
  def pack
    self.internal_pack([], [:dummy])
  end

  protected
  def internal_pack(ans, acc)
    head, *tail = self
    if self.empty?
      (ans + [acc])[1..-1]
    elsif head == acc[0]
      tail.internal_pack(ans ,acc + [head])
    else
      tail.internal_pack(ans + [acc], [head])
    end
  end
end

%w(a a a a b c c a a d e e e e).pack
#=> [["a", "a", "a", "a"], ["b"], ["c", "c"], ["a", "a"], ["d"], ["e", "e", "e", "e"]]

# P10 (*) Run-length encoding of a list.
#     Use the result of problem P09 to implement the so-called
#     run-length encoding data compression method. Consecutive
#     duplicates of elements are encoded as lists (N E) where N is the
#     number of duplicates of the element E.
#
#     Example:
#     * (encode '(a a a a b c c a a d e e e e))
#     ((4 A) (1 B) (2 C) (2 A) (1 D)(4 E))
class Array 
  def encode
    self.pack.map do |x|
      [x.size, x.first]
    end
  end
end

%w(a a a a b c c a a d e e e e).encode
#=> [[4, "a"], "b", [2, "c"], [2, "a"], "d", [4, "e"]]

# P11 (*) Modified run-length encoding.
#     Modify the result of problem P10 in such a way that if an
#     element has no duplicates it is simply copied into the result
#     list. Only elements with duplicates are transferred as (N E)
#     lists.
#
#     Example:
#     * (encode-modified '(a a a a b c c a a d e e e e))
#     ((4 A) B (2 C) (2 A) D (4 E))
class Array 
  def encode_modified
    self.pack.map do |x|
      if 1 == x.size
        x.first
      else
        [x.size, x.first]
      end
    end
  end
end

%w(a a a a b c c a a d e e e e).encode_modified
#=> [[4, "a"], "b", [2, "c"], [2, "a"], "d", [4, "e"]]


# P12 (**) Decode a run-length encoded list.
#     Given a run-length code list generated as specified in problem
#     P11. Construct its uncompressed version.
class Array
  def decode
    self.inject([]) do |ans, x|
      ans + if x.class == Array
              Array.new(x[0], x[1])
            else
              Array.new(1, x)
            end
    end
  end
end

# 2
class Array
  def decode
    t = Array
    self.inject([]) do |ans, x|
      ans.+ x.class == Array ? Array.new(x[0], x[1]) : Array.new(1, x)
    end
  end
end

[[4, "a"], "b", [2, "c"], [2, "a"], "d", [4, "e"]].decode
#=> ["a", "a", "a", "a", "b", "c", "c", "a", "a", "d", "e", "e", "e", "e"]

# P13 (**) Run-length encoding of a list (direct solution).
#     Implement the so-called run-length encoding data compression
#     method directly. I.e. don't explicitly create the sublists
#     containing the duplicates, as in problem P09, but only count
#     them. As in problem P11, simplify the result list by replacing
#     the singleton lists (1 X) by X.
#
#     Example:
#     * (encode-direct '(a a a a b c c a a d e e e e))
#     ((4 A) B (2 C) (2 A) D (4 E))
class Array
  def encode_direct
    (self + [:dummy]).internal_encode_direct([], 1, :dummy)[1..-1]
  end

  protected
  def internal_encode_direct(ans, cnt, prev)
    head, *tail = self
    if self.empty?
      ans
    elsif head == prev
      tail.internal_encode_direct(ans, cnt + 1, head)
    else
      tail.internal_encode_direct(ans + [[cnt, prev]], 1, head)
    end
  end
end

%w(a a a a b c c a a d e e e e).encode_direct
#=> [[4, "a"], [1, "b"], [2, "c"], [2, "a"], [1, "d"], [4, "e"]]

2009-03-16

RubyでL-99 (P1〜P8)

| 23:59 | RubyでL-99 (P1〜P8) - わだばLisperになる を含むブックマーク はてなブックマーク - RubyでL-99 (P1〜P8) - わだばLisperになる

Rubyを勉強しております。

Rubyにリストが無いのとブロックの引数がローカルのスコープをつくらないところ(1.8では)にびっくりしました。

びっくりというより若干ショックでしたが、別にLispじゃないので当然のことでした。

ちょっとMatz Lispという言葉を真に受け過ぎていたようです(笑)

無駄に再帰していますが、L-99はそういう問題なのでRubyでも再帰。

色々分からないことが多く、まったくRubyっぽく書けてないですが、10年後位にはRubyっぽく書けるようになるのかもしれません。

# P01 (*) Find the last box of a list.
#     Example:
#     * (my-last '(a b c d))
#     (D)
class Array
  def my_last 
    head, *tail = self
    if tail.empty?
      self
    else
      tail.my_last
    end
  end
end

%w(1 2 3).my_last
#=> ["3"]

# P02 (*) Find the last but one box of a list.
#     Example:
#     * (my-but-last '(a b c d))
#     (C D)
class Array
  def last2
    _, *tail = self
    if tail[1..-1].empty?
      self
    else
      tail.last2
    end
  end
end

%w(a b c d).last2
#=> ["c", "d"]

#P03 (*) Find the K'th element of a list.
#    The first element in the list is number 1.
#    Example:
#    * (element-at '(a b c d e) 3)
#    C
class Array
  def element_at (pos)
    head, *tail = self
    if 0 > pos
      nil
    elsif self.empty? || 1 >= pos 
      head
    else
      tail.element_at(pos - 1)
    end
  end 
end

%w(1 2 3 4).element_at(2)
#=> "2"

# P04 (*) Find the number of elements of a list.
class Array
  def my_size
    _, *tail = self
    if self.empty?
      0
    else
      1 + tail.my_size
    end
  end
end

%w(1 2 3 4).my_size
#=> 4

# P05 (*) Reverse a list.
class Array
  def my_reverse
    head, *tail = self    
    if self.empty?
      []
    else
      tail.my_reverse + [head]
    end
  end
end

%w(1 2 3 4).my_reverse
#=> ["4", "3", "2", "1"]


#P06 (*) Find out whether a list is a palindrome.
#    A palindrome can be read forward or backward; e.g. (x a m a x).
class Array 
  def palindrome?
    self.my_reverse == self
  end
end

%w(x a m a x).palindrome?
#=> true

%w(x m a x).palindrome?
#=> false

# P07 (**) Flatten a nested list structure.
#     Transform a list, possibly holding lists as elements into a
#     `flat' list by replacing each list with its elements
#     (recursively).
#     Example:
#     * (my-flatten '(a (b (c d) e)))
#     (A B C D E)
#     Hint: Use the predefined functions list and append.
class Array
  def my_flatten
    head, *tail = self
    if self.empty?
      []
    elsif head.class == Array
      head.my_flatten + tail.my_flatten
    else
      [head] + tail.my_flatten
    end
  end
end

[1, [2, [3, 4], 5]].my_flatten
#=> [1, 2, 3, 4, 5]

# P08 (**) Eliminate consecutive duplicates of list elements.
#     If a list contains repeated elements they should be replaced
#     with a single copy of the element. The order of the elements
#     should not be changed.
#     Example:
#     * (compress '(a a a a b c c a a d e e e e))
#     (A B C A D E)
class Array 
  def _compress(prev, acc)
    head, *tail = self
    if self.empty?
      acc
    elsif head == prev
      tail._compress(head, acc)
    else
      tail._compress(head, acc + [head])
    end
  end

  def compress
    self._compress(:dummy, [])
  end
end

%w(a a a a b c c a a d e e e e).compress
#=> ["a", "b", "c", "a", "d", "e"]

2009-03-13

TT#2での黒田さん講演回想録 (2)

| 23:51 | TT#2での黒田さん講演回想録 (2) - わだばLisperになる を含むブックマーク はてなブックマーク - TT#2での黒田さん講演回想録 (2) - わだばLisperになる

続きの記憶があまりにも朧げなので困っていたのですが、黒田さんご本人のメモが公開されました!

内容としては、ここに書かれていないのは、具体的な事例の紹介/エピソードくらいのところだと思われるので骨子はTTでのお話そのままという感じです。

参加されなかった方もこれで概要が伺えるかと思います!

これで勝つる!

2009-03-08

Slimy hackathon #1終了!!

| 20:14 | Slimy hackathon #1終了!! - わだばLisperになる を含むブックマーク はてなブックマーク - Slimy hackathon #1終了!! - わだばLisperになる

まったりと開催されましたslimy hackathonですが、無事48時間経過し終了となりました!!

結局のところ皆でテーマを決めて過す週末という感じでしたが、これはこれで良かったと思います。

割と野心的な取組みもあり、今後の開催で続きを作って頂きたいなと思いました。

自分のメインプロジェクトはSLIMEをLispマシンに近付けるというものでした。

Lispマシンのマニュアルからキーバインドをちょこちょこ移植しただけに終ったのですが、便利そうなコマンドが結構あって、やっぱりLispマシンのマニュアルは一回通して読んでみるべきかもしれないと思いました。

例えば、今回、Eval Region Hackというコマンドを見付けたのですが、これは、リージョンを評価するにあたって、defvarの値も更新してくれるというものです。

自分はこんな感じに再現してみました。

;; c-m-sh-e Evaluate Region Hack
;; ----------------------
;; => slime-eval-region ?
;; リージョンにdefvarがある場合、値を再定義
(progn
  (defun slime-eval-region-hack (start end)
    (interactive "r")
    (slime-eval-with-transcript
     `(swank:interactive-eval-region
       ,(replace-regexp-in-string
         "defvar"
         "defparameter"
         (buffer-substring-no-properties start end)))))
  (define-key slime-mode-map [(control meta shift ?e)]
    'slime-eval-region-hack))

CLのコードを書いている方なら、開発中にdefvarのこの挙動が面倒で、defparameterにしたりしている方もいらっしゃるのではないでしょうか。

こんなコマンドがあるなんてさすが、Lispのコードを書いてる人が開発していた環境だ!、等と地味に感心していました。

そんな感じのslimy hackathon #1でしたが、また機会があれば開催してみたいと思っています!

試みられたプロジェクト

no title:

  • slime-edit-definitionの(setf foo)対応」:g000001
  • slime-modeのコマンドを全部試してみる」:NANRIさん
  • slimeとeliの共存についてちょっとだけ調べる」:akaさん
  • 「newLISPをSLIMEから動かす」:koshさん
  • 「clispのarglist表示をいい感じにする」:NANRIさん
  • slime-jp@reddit」:g000001
  • 「色々な処理系でSLIME」:g000001
  • SLIME、Lispマシン化計画」:g000001
  • 「Climacs と SLIME?」:quekさん
  • 「逆引きSLIME」:g000001
  • 「xyzzyからswankへの接続」:snmstsさん

成果物

関連BLOGエントリ

2009-03-07

Slimy hackathon 中間報告 (3)

| 17:23 | Slimy hackathon 中間報告 (3) - わだばLisperになる を含むブックマーク はてなブックマーク - Slimy hackathon 中間報告 (3) - わだばLisperになる

色々な処理系でSLIME/Rubyでslime

色々な処理系でSLIMEのとっかかりとして、Rubyを試してみます。

swank.rbは、SLIMEのコミッターの方が、Rubyの勉強のために、Swankを作成して公開という代物で、本格的に使うことを意図したものではないようです。

以下、自分が試した手順です。

まず、素のEmacsへの導入を想定していますが、Emacs側の設定としては、

;; Emacs lisp
(require 'cl)

(pushnew "/share/sys/cl/src/slime/" ;; slimeのパス
	 load-path)

(require 'slime)

というのがあれば良いでしょう。

Emacs側の設定はこれのみ。

swank.rb起動

$ SWANK_RB=/share/sys/cl/src/slime/contrib
$ cd $SWANK_RB
$ ruby -r swank -e swank.rb
Listening on ["AF_INET", 4005, "localhost", "127.0.0.1"]
...

という風に、標準では、4005番ポートで待機しています。

4005番が使われている場合には、何も言わず終了しますので、他にSwankを起動している方はご注意。

これに、

M-x slime-connect
Host: 127.0.0.1
Port: 4005

で接続します。

n = 3

で、nから3までをリージョン選択して

M-x slime-eval-regionすると、

3という結果が出ます。

def hello
  "hello"
end

hello # slime-regionする
#=> "hello"

現状は、slime-eval-regionする他ないようで、あまり魅力的ではないですね!!

Slimy hackathon 中間報告 (2)

| 17:00 | Slimy hackathon 中間報告 (2) - わだばLisperになる を含むブックマーク はてなブックマーク - Slimy hackathon 中間報告 (2) - わだばLisperになる

slime-edit-definitionの(setf foo)対応」を書いてみました。

先のものと殆ど同じです(´▽`*)

Slimy hackathon 中間報告 (1)

| 13:22 | Slimy hackathon 中間報告 (1) - わだばLisperになる を含むブックマーク はてなブックマーク - Slimy hackathon 中間報告 (1) - わだばLisperになる

まったりと進んでおります、Slimy Hackathon。

完了したタスクもでてまいりました!!

slime-modeのコマンドを全部試してみる」:NANRIさん

は、Partty!で動作を記録していて眺めることができます。

画面サイズを合せてみてみましょう!

SLIME拡張elisp/slime-undefine-functionの(setf foo)対応」:g000001

現行のSLIMEでは、(defun (setf foo) ...)等の(setf foo)の個所でfmakunboundを呼び出すslime-undefine-functionが上手く#'(setf foo)を掴まえられないので、その辺を対処してみました。

同様の問題が、slime-edit-definitionにもあるので、これも対処したいと思います。

以下、活動中タスクです。

slimeとeliの共存についてちょっとだけ調べる」:akaさん

「newLISPをSLIMEから動かす」:koshさん

「clispのarglist表示をいい感じにする」:NANRIさん

slime-jp@reddit」:g000001

「色々な処理系でSLIME」:g000001

SLIME、Lispマシン化計画」:g000001

「逆引きSLIME」:g000001

xyzzyからswankへの接続:snmstsさん

まだまだ、Slimy Hackathonは続きます!

2009-03-06

Slimy hackathon 本日18:30よりスタート!!!

| 08:03 | Slimy hackathon 本日18:30よりスタート!!! - わだばLisperになる を含むブックマーク はてなブックマーク - Slimy hackathon 本日18:30よりスタート!!! - わだばLisperになる

本日18:30よりノープランでスタートです。

初っ端からで申し訳ありませんが、実は今日からバイトすることになりまして帰宅するのが、21:00位になりそうですw

だったら21:00開始が良いんじゃないかとも思ったのですが、こういうのもアリかなと思いまして、18:30スタートとしたいと思います。

48時間もありますので、どういう風にするかから決めたりして行こうかなと思っています。

基本的には、前回も書きましたが、Fixdapにプロジェクトを登録して、それぞれ取り組んでみる、というのを骨子にしたいと思います。

他に連絡用としては、LingrのCL部屋が使えるかと思っています

これらとSkypeやIRCを組み合わせてSlimyな週末を過しましょう!!!

2009-03-05

クラスを<foo>と表記する試み

| 11:34 | クラスをと表記する試み - わだばLisperになる を含むブックマーク はてなブックマーク - クラスをと表記する試み - わだばLisperになる

DylanやSchemeだとクラスを<foo>の様に表記しますが、CLでこれを真似すると

(defclass <foo> () ())

(make-instance '<foo>)

となります。

若干無駄な抵抗で

(defclass :<foo> () ())

(make-instance :<foo>)

というのもありかもしれません。ちょっと問題がありますが…。

結局のところ<foo>は自己評価型のシンボルでもなんでもないのでこういうことになるのですが、quoteを付けなくてもよいようにできないものかなとリーダーマクロでごちゃごちゃ遊んでみました。

内容としては、<foo>というシンボルを読んだときに、symbol-valueに<foo>を詰めこんでしまうというもので副作用メインのリーダーマクロです。

'|'でのエスケープについては考えたのですが、そういえば、バックスラッシュの対応は忘れてしまいました。

パッケージ内で有効なキーワードのようなものがあれば、こういう目的に使えるのかもしれません。

何か手軽で良い方法があったら是非教えてくださいー。

(defun white-char-p (ch)
  (not (null (member ch '(#\Space #\Tab #\Newline)))))

(set-macro-character #\< 
                     (lambda (stream char)
                       (let ((ch (read-char stream)))
                         (if (white-char-p ch)
                             '<
                             (progn
                               (unread-char ch stream)
                               (do ((res (list char))
                                    (in-barp 0)
                                    (ch (read-char stream)
                                        (read-char stream)))
                                   ((eql #\> ch) 
                                    (let ((sym (intern
                                                (coerce (nreverse (push #\> res))
                                                        'string))))
                                      (setf (symbol-value sym) sym)
                                      sym))
                                 (if (eql #\| ch)
                                     (incf in-barp)
                                     (PUSH (if (oddp in-barp)
                                               ch
                                               (char-upcase ch))
                                           RES))))))))

動作

(< 2 3)
;=> T

;; 上の定義だと結局エスケープしないといけない(中途半端)
(\<= 2 3)
;=> T

(progn
  <z|ot|>)
;=> |<Zot>|

(defclass <qqq> () ())
;=> #<STANDARD-CLASS <QQQ>>

(make-instance <qqq>)
;=> #<<QQQ> {100E2D2C91}>

(defclass <foo|bar|baz> () ())
;=> #<STANDARD-CLASS <FOObarBAZ>>

(make-instance <foo|bar|baz>)
;=> #<<FOObarBAZ> {100E2D2C98}>

2009-03-04

TT#2での黒田さん講演回想録 (1)

| 13:14 | TT#2での黒田さん講演回想録 (1) - わだばLisperになる を含むブックマーク はてなブックマーク - TT#2での黒田さん講演回想録 (1) - わだばLisperになる

今回のShibuya.lisp TT#2では、黒田さんの講演は中継不可でした。

参加できなかった方は参加者の回想録を読む他ない状況なのですが、最初の場内アナウンスでブログで言及も不可と説明してしまったためどうも自重される方が多いようです。ちょっとこれは、厳重過ぎる扱いで説明してしまっている(黒田さんもブログでの言及禁止とまではおっしゃってなかったので)のではないかということで、講演後に黒田さんご本人にブログでの回想の言及と観客の皆さんの講演状況の写真撮影のアップについての可否を確認させて頂いたのですが、OKということでした。

ということで、補完の意味も兼ねまして、講演の回想録を書いてみようかと思います。

自分はメモをとっていなかったので、完全に記憶だけで書いてますので、それは違うということがありましたらコメントでも頂ければと思います。

数理システム入社

まず、大学でもLISPの講義を受けたが、中西先生の本をもとにした講義を受けたが、当時触れるような処理系はなかったので講義でも頭の中で動作を想像するような内容だった。

そして、数理システムに入社した当時、数理システムでCommon Lisp使われているというようなことはなかった。

入社して最初の仕事は、並列計算機用のCコンパイラを書くこと。

VAX-11/780管理業務をすることになり、VMSからBSD UNIXに入れ換えを実施した。

当時は、UNIXに入れ込んでいたが、今考えれば、VMSの方がよっぽど良い。*1

BSDにFranz Lispが付いてきていたので*2、起動させてみたが、Ctrl-Dでも処理系を終了させることもできず困った、というのが実際に稼働する処理系との最初の出会い。

Common Lispを使うきっかけ

そんなこんなで当初、Common Lispを業務で使うということもなかったが、CLを使った案件を担当することになり業務で初めてCLを使った。

このときはLucid Common Lispを利用*3

この辺から、CLを業務で利用し始め、また、Schemeを用いてDSLを作成し問題を解決するという案件や、自動車の衝突実験等々を担当。

ただ、最初から顧客がCLを指定して案件を発注してくれることばかりではなく、CLのメリットを説明し顧客に納得してもらうこともある/あった。

顧客がCを指定して来たときに、CLで書いて満足する結果が得られなければ、無償でCで書き直すという条件で交渉したこともある。

また、当初は上司もCLを使うことに、すんなりとGOを出したわけでもなく、納期を1ヶ月早めるのでAllegro CLを買ってくれないかと交渉したこともある。

LISPを使わないやつに限ってLISPを語りたがる

例えば、Javaを使わない人が、Javaを勉強すべきと主張したり、人にJavaを勧めたりすることはあるだろうか?

面白いことにLISPはそういうことが多い。これは、非常に不思議で、LISPにとっては不幸なことだと思う。

それに対しての答えとして「使いたいけど上司が許してくれない」というのがあるが、そんなことでへこたれるんだったらCommon Lisp使わなくてよし(上記参照)

(私の解釈):色々紆余曲折あり、松岡修三氏のようにストレートではありませんが、つまり、君達LISPを使いなさいよ、ということかと思いました。

以降、内容が思い出せれば、つづく

Slimy hackathon 3/6-3/8で開催します!!!

| 10:11 | Slimy hackathon 3/6-3/8で開催します!!! - わだばLisperになる を含むブックマーク はてなブックマーク - Slimy hackathon 3/6-3/8で開催します!!! - わだばLisperになる

そういえば、開催告知してなかったんで告知ですw

3/6 18:30から、3/8 18:30まで、48時間 SLIMEのハッカソンを開催します!

やっぱり参加申し込みがあった方が良いのかしらなどと考えたんですが、Fixdapで良いんじゃないかと思えて来ましたのでFixdapに、この48時間中にしてみたいことをプロジェクトとして登録してみて下さい!

なんと、もう3名も登録されていますね!!!

今日の落書き

| 09:31 | 今日の落書き - わだばLisperになる を含むブックマーク はてなブックマーク - 今日の落書き - わだばLisperになる

(defun (setf fib) (n field)
  (declare (ignore field))
  (if (< n 2)
      n
      (+ (setf (fib :dummy) (1- n))
         (setf (fib :dummy) (- n 2)))))

(setf (fib :dummy) 10)
;=> 55

*1:私の解釈:VMSの方が良い。今となっては、UNIXが世の中を席巻していますが、80年代には様々なOSがあり、実はLISP文化は、どちらかというと非UNIXな文化圏でした。16bit/32bit系で、PDP-11で、UNIXで、Cで、viで、というのに対し、PDP-10で、36bit系で、TOPS-20やITSでLISPでEMACSというような具合で宗派が分かれていたようです。今となっては、vi vs emacs位のものですが。VMSは、UNIX/TOPS-20の中間位?

*2:当時のBSDにはFranz Lispが配布物としておまけで付いてきていました

*3:現在Lucid社はなくなっており、LispWorksからLiquid CLとして販売されている

2009-03-03

Slimy hackathonへの道(3)

| 01:34 | Slimy hackathonへの道(3) - わだばLisperになる を含むブックマーク はてなブックマーク - Slimy hackathonへの道(3) - わだばLisperになる

Slimy hackathonについてさらにあれこれ考えています。

名称

とりあえずの進捗状況ですが、Slimy hackathonという名称について大元のSmiley Hackathon主催のacotieさんにお許しを頂きました。

怒られなくて良かったw

開催日程

それで開催時期なんですが、Shibuya.lisp TT#2も無事終了しましたし、これはもう3/6-3/8しかないだろうという気分になってきたので、3/6-3/8にしたいと思います。

いつもの如く急ですね、すいません(´▽`*)

開催時間なのですが、24時間TVに合せて18:30にしてみたいと思います。

仕事から帰ってきて、「あ、そうだ始まってるんだ!」的な。

48時間なので乗り遅れとか考えなくてもOKでしょうw

それより18:30に終わる方が疲れなくて良いかも。いやもちろん48時間通して参加する人はいないと思うのですが。

運営ツール

運営で使うツールを色々物色しているのですが、WikiとかSkypeとかLingrとかIRCになるのかなと思っています。

プロジェクト管理ツールとしてFixdapというのがあることを久々に思い出したのですが、これは今回結構使えるかもしれません。

ということで、プロジェクトを作成してみました。

ここにタスクを自分で登録して実行という流れとかどうかしらと思ったりしています。

試しに前回書いた思い付きを登録してみました。