トップ «前の日記(2012-01-05) 最新 次の日記(2012-01-10)» 編集

Route 477



2012-01-08

[ruby] myrurema 0.3.0をリリースしました

最新のbitclustで動かないというレポートをいただいたので(ありがとうございます)直しました。

あとrefeでは「refe Ar i」でArray#indexなどが検索できるというのを知った(思い出した?)ので、それにも対応しました。

/Users/yhara $ rurema Ar ind
(1)Array#index (2)Array#indexes (3)Array#indices 
which one? > 

[ruby] gem生成ツールをJewelerからBundlerに乗り換えた

BundlerはRubyGemsの依存関係をメンテナンスするツールだけど、実はJeweler等のようにgemを生成するための機能もある。

bundle gemコマンドでひな形を生成することができ、あとはrake buildでpkg/foo-x.y.z.gemができたりとかそういう感じ。

/tmp $ bundle gem foo
      create  foo/Gemfile
      create  foo/Rakefile
      create  foo/.gitignore
      create  foo/foo.gemspec
      create  foo/lib/foo.rb
      create  foo/lib/foo/version.rb
Initializating git repo in /private/tmp/foo

既にあるプロジェクトをbundlerに移行したい場合も、まず上のように/tmpにひな形を作ってから、それを参考にGemfile, Rakefile, lib/*/version.rbを書くのが良いと思う。

Jewelerとの違いは以下。

  • 生成される*.gemspecがシンプル。
  • バージョン名をVERSIONというファイルに書くのではなく、lib/foo/version.rbのFoo::VERSIONという定数から取得する。
  • Gemfileを書く必要がある。が、最近のBundlerはGemfileに「gemspec」と書くと*.gemspecのdependencyを見てくれる機能があるので特に手間ではない()

(Jewelerもだけど)git前提なのでそこは注意。

[scheme] beginで囲まれたdefineに展開されるマクロを書いたときの、定義される変数のスコープについて

BiwaSchemeにInternal defineを実装するために、R6RSの仕様を読んでいる。そこで一点疑問が。

11.4.7 Sequencingによると、 (begin (define ..) (define ..)) みたいなbeginは「spliced into the surrounding body, as if the begin wrapper were not actually present.」のように書いてある。

つまりこういうことができる。

(begin
  (define a 'a)
  (define b 'b))

(display a)

ならば、以下のようなこともできるのかと思ったのだけど、そうとは保証されてないみたいだ。

(define-syntax m
  (syntax-rules ()
    ((_)
      (begin
        (define a 'a)
        (define b 'b)
        ))))
(m)
(display a)

てか、beginで囲んだdefineがspliceされるのってこういうことするためだと思ってたんだが、違うのかな。

できなかったやつ

/Users/yhara/proj/biwascheme % /Applications/Racket\ v5.1.1/bin/racket -f _misc/definition.scm
reference to undefined identifier: b

/Users/yhara/proj/biwascheme % petite _misc/definition.scm  Petite Chez Scheme Version 8.4
Copyright (c) 1985-2011 Cadence Research Systems

Exception: variable b is not bound

/Users/yhara/proj/biwascheme % ypsilon _misc/definition.scm 

error: unbound variable b
...

できたやつ

/Users/yhara/proj/biwascheme % LARCENY_ROOT=/Users/yhara/research/Scheme/larceny-0.97-bin-native-ia32-macosx larceny -- _misc/definition.scm               
Larceny v0.97 "Funny in the Head" (Aug 19 2009 04:24:46, precise:Posix:unified)
b

/Users/yhara/proj/biwascheme % gosh _misc/definition.scm 
b
本日のツッコミ(全2件) [ツッコミを入れる]
leque (2012-01-09 06:59)

これが動いたり動かなかったりするのは begin の問題ではなくて、 hygienic macro とトップレベルの束縛の扱いの問題です。<br><br>まず、上のコードは R6RS ではエラーになります。というのは、 m の中に現れる a と b はマクロ展開時に導入される変数名なので、展開先では rename されて見えなくなるからです。<br>m の引数として変数名を取るようにして<br> (define-syntax m<br> (syntax-rules ()<br> ((_ a b)<br> (begin<br> (define a 'a)<br> (define b 'b)))))<br><br> (m a b)<br>にすれば動きます。<br><br>R5RS の場合だと、処理系によって動いたり動かなかったりします。<br>R5RS では、トップレベルの束縛は未定義のものも含めてすべて束縛済みであるものとして扱ってもよいことになっていて(R5RS 5.2.1)、束縛済みとして扱う処理系では、 m 中の a、 b は束縛済みの a、 b を指すものとして rename されないのに対して(さらに、束縛済みの変数に対する define は set! と同じ意味になります)、そうでない処理系では、 R6RS の場合と同じく新たな変数を導入したものとして a、 b が rename されます。

yhara (2012-01-10 11:42)

ありがとうございます。寝る前にベッドで考えてて、「syntax-caseを使えばいけるのではないか?」というところまでは思いついたのですが、マクロ引数に変数名を渡すというのは思いつきませんでした。