櫓日誌

スポンサーサイト

一定期間更新がないため広告を表示しています

| スポンサードリンク | - | | - | - |
はてなに移行しました
はてなに移行しました
| YAGURA | - | 11:30 | comments(18) | trackbacks(131) |
ふつける

9章まで読み終わった。主に電車で読んでるのでなかなか読み進まないな。単に読むだけじゃなくて、演習問題で手を動かしてみないとなかなか身につかないし。

ここまで読んだ感じだと、同じ関数型言語でも Lispより数式に近い記述形式なので、理解しやすいような。インデントや$で、コードもスッキリするので読みやすい。

| YAGURA | ソフトウェア | 01:26 | comments(0) | trackbacks(1) |
Firefoxとか

今までずっとSleipnirを使っていたけど、ついにFirefoxに切り替えました。 家と会社のパソコン両方にFirefoxエクステンションをインストールするのが面倒でデフォルト機能が豊富なSleipnirを使い続けてたけど、最近はBookmarkletの登録が面倒になってきたので。

    追加したFirefoxエクステンション
  • Tab Mix Plus: タブ機能拡張
  • Google Blowser Sync: 複数のパソコンでFirefoxの設定を共有
  • FoxyTunes: FirefoxからiTunesを操作

    最近導入したソフトもついでに。
  • xyzzy: Windows用Emacsが重いのでこちらもようやく乗り換え
  • Thumbwin: アイコン化したアプリケーションのサムネイルをデスクトップに表示
  • Livedoor Reader: 言わずと知れた? RSSリーダー。

| YAGURA | - | 01:22 | comments(67) | trackbacks(0) |
オブラブ2006夏イベント

6/29のオブラブイベントに参加してきた。 当日は風邪で体調が最悪で何度も途中から帰ろうかと思ったけど、どのセッションも楽しいものだった。帰らなくてよかった。スタッフの皆さんのおもてなしや盛り上げも素晴らしかった。

*ワールドカフェ
いろいろな人と議論できるのが楽しい。ただ、ソフトウェア開発の楽しさなど、一つのテーマについてもう少し語れても良かったのと、重複しているテーマがいくつかあったので、開始前に全体でテーマを選考する時間があるとさらによかった。

*パネルディスカッション
はぶさん面白。達人プログラマ好きなので、DRY重要と言われたのがうれしい。 オブ脳カーのエアコンフィルターは、私の買ったオブ脳本で出来ていたことが発覚。

| YAGURA | ソフトウェア | 03:03 | comments(0) | trackbacks(0) |
Binding.of_caller

Binding.of_caller を調べてみました。クリティカルセーフなのはもちろん、継続を使って効率良く caller bindingを取得してます。(るびまの記事で解説があったのにきちんと理解できてなかったよ。。)たとえば、関数Aから呼び出された関数Bの中で Binding.of_caller を使うと以下のような流れになります。

AからBを呼び出す->B内でBinding.of_caller(&block)を実行->継続ポイントをセット->set_trace_funcをセット->関数Bからreturnして関数Aに戻る->set_trace_func により継続ポイントから再開->関数Aのbindingを取得->Aのbindingをパラメータにして blockを実行。

ただし、Binding.of_caller は関数Bの最後の式にしないと set_trace_funcが期待通りに動かない(このために Binding.of_callerはクロージャになっている)。ややこしいけど、うまいなぁ。自分で実装してたら思いつかないな。

| YAGURA | ソフトウェア | 19:07 | comments(0) | trackbacks(1) |
続:Rubyで内包表現

配列リテラル([1,2,3]のような配列のことをこう呼ぶらしい)のinitialize上書きは無理っぽいので諦めて、コードを整理してみました(ついでにバグ取りも)。 用語はこちらを参考にさせて頂きました。

書式:
I['value_expression' | 'var <- source',  'predicate_1', 'predicate_2', ・・・, 'predicate_n']

この式は以下のような式に展開されます。

source.select do |var|
  predicate_1(var) &&  predicate_2(var) && ・・・ && predicate_n(var)
end.map do |var|
  value_expression(var)
end
例1:
xs = [10,30,3,-5,1,10,100,-60]
p I['(x*2).abs' | 'x<-xs', 'x < 50']
=> [20, 60, 6, 10, 2, 20, 120]
例2:
def quicksort(x = nil, *xs)
  return []  if x == nil
  quicksort(*I['y' | 'y <- xs', 'y < x']) + [x] + quicksort(*I['y' | 'y <- xs', 'y >= x'])
end
p quicksort(*xs)
=> [-60, -5, 1, 3, 10, 10, 30, 100]
コードはこちら:
require 'active_support/binding_of_caller'

class Intention
  def initialize(value_expression, var, source)
    @value_expression = value_expression
    @var = var
    @source = source
  end
  
  def to_a(predicates, binding)
    predicates << 'true'  if predicates == []
    eval(<<-EOF, binding)
      #@source.select {|#@var|  #{predicates.join('&&')} }.map do |#@var|
        #@value_expression
      end
    EOF
  end
end

class String
  def |(other)
    raise  unless other =~ /^(.+)<-(.+)$/
    Intention.new(self, $1, $2)
  end
end

class I
  def self.[](intention, *predicates)
    raise  unless  intention.instance_of?(Intention)
    Binding.of_caller do |binding|
      intention.to_a(predicates, binding)
    end
  end
end
| YAGURA | ソフトウェア | 18:15 | comments(0) | trackbacks(0) |
Rubyで内包表現

Haskellの内包表現を知ってRubyでも使いたくなった。試しに実装。

require 'active_support/binding_of_caller'

class Naiho
  attr_reader :element, :bind, :range
  def initialize(element, bind, range)
    @element = element
    @bind = bind
    @range = range
  end
  
  def to_list(restrictions, binding)
    eval(<<-NAIHO, binding)
      #@range.select {|#@bind|  #{restrictions.join('&&')} }.map do |#@bind|
        #@element
      end
    NAIHO
  end
end

class String
  def |(other)
    raise  unless other =~ /^(.+)<-(.+)$/
    Naiho.new(self, $1, $2)
  end
end

$n = Object.new
def $n.[](naiho, *restrictions)
  raise  unless  naiho.instance_of?(Naiho)
  Binding.of_caller do |binding|
    naiho.to_list(restrictions, binding)
  end
end


=begin
class Array
  def initialize(args)
    if args.first.instance_of?(Naiho)
      naiho, *restrictions = args
      Binding.of_caller do |binding|
        naiho.to_list(restrictions, binding)
      end
    else
      super
    end
  end
end
=end
例1:
xs = [10,20,3,-5,1,10,100]
$n['x*2' | 'x <- xs', 'x <= 10']
=> [20, 6, -10, 2, 20]
例2:
def quicksort(x = nil, *xs)
  return []  if x == nil
  quicksort(*$n['y' | 'y <- xs', 'y < x']) + [x] + quicksort(*$n['y' | 'y <- xs', 'y >= x'])
end
quicksort(*xs)
=> [-5, 1, 3, 10, 10, 20, 100]

ほんとは、Arrayのinitializeを上書きできれば以下の式で済むんだけど、配列式の場合は Arrayのinitializeが呼ばれないみたいだ。set_trace_funcにすら反応しなかった。

['x*2' | 'x <- xs', 'x <= 10']

この実装のために、caller bindingが取得できなくて困っていたところに、るびまのRailsの記事でRailsはset_trace_funcで実現していることを知った。というわけで、躊躇なくbinding_of_callerを利用。スレッドセーフではなくなりそうだけど、その辺は継続を使うことでどうにかしてるのかな。そのうち見てみよう。

それにしてもメタプログラミングは楽しいや。

| YAGURA | ソフトウェア | 22:24 | comments(0) | trackbacks(1) |
RSpecの拡張

RSpecのスタックの例だと、スタックの仕様を「空」、「要素が1つだけ」、「ほとんど満杯」、「満杯」の4つのコンテキストで表しているんだけど、これだと要素が2や3のときの場合がなくて、仕様としては不十分じゃないだろうか。これはたぶんスタックの振る舞いが変わる4つの境界をコンテキストとして選んでいるからであって、仕様というよりはテストケースっぽいような。

仕様を記述するのであれば、仕様と上のような仕様の具体例を分けて考えたいと思う。たとえばスタックであれば「空」、「満杯」、「空でもなく満杯でもない」の三つをコンテキストする。この場合のコンテキストは抽象的で、一つ以上の具体例に対応する。「空」の場合は一つだけだけど、「満杯」や「空でもなく満杯でもない」は、いろいろな具体例がありえる。要素が一つだけのスタック、ほとんど満杯のスタックは、「空でもなく満杯でもない」コンテキストの具体例の一種だ。

試しに、一つのコンテキストで複数の具体例を表せるように、RSpecを拡張してみた。add_instanceで具体例を追加できる。specifyはcontextの具体例の数だけ繰り返し実行する。スタックの場合、下のような感じになるけど、もっときれいに仕様っぽく書けないかな。そもそも仕様っぽさってなんだって話になってくるのか。。

続きを読む >>
| YAGURA | - | 01:09 | comments(0) | trackbacks(0) |
RSpec
自動化ツールを作成・改良する間、RSpecで仕様を追加・修正したので、テスト駆動ではなく振る舞い駆動で考えるということがどういうことか、少しわかってきた。

振る舞い駆動とは言っても、やっていることはテスト駆動のときと変わらない。今回は以下のような流れでツールを作った。
基本的な仕様を記述(RSpec)→動くモデル(Rubyのクラス群)を作成→仕様通りか検証(RSpecを適用)→仕様を拡張(RSpecを追記)
→モデルを拡張→仕様通りか検証→モデルを単純化→仕様通りか検証→仕様を拡張→・・・

XUnitとの違いとしては、XUnitではテストケースを記述していたのが、RSpecでは、contextとspecifyを使って仕様を記述する。contextとspecifyの関係は契約による設計の事前条件と事後条件の関係に近いかもしれない。contextがクラスなどのモジュールの状態を表し、specifyがある状態において満たさなければならない振る舞い仕様を表しているようにも見えるので。I/Fに着目するか、状態に着目するかの違いなのかもしれない。

ただ、その他にはさほど大きな違いを感じなかった。最初は、テスト仕様と考えないようになったことで、プログラムの内部仕様(ホワイトボックス視点)ではなく、外部仕様(ブラックボックス視点)に集中するようになるかと思ったけど、自分の場合はそうはならなかった。完全にブラックボックス視点にするとたくさんの仕様を書かないといけなかったので、結局はホワイトボックス視点が必要に・・・

他にも、RSpecは仕様というよりは具体例の集合(たとえば、入力が奇数の場合1、偶数の場合0を返すという仕様ではなく、入力が1のとき1を返せ、2のとき0を返せということを記述する)なのでどのような具体例を記述すべきかとか(仕様というよりはテスト的な考え方?)、イテレーティブに開発する場合、どこまでを基本仕様と考えるべきかとか、考えたいことはいろいろあるけど、風邪気味なのでそれはまた別の機会に。。
| YAGURA | - | 00:22 | comments(0) | trackbacks(0) |
自動化
最近、部署が代わって、もっぱら仕様の調整とか調査、Cでのコーディングをするようになった。今の部署では仕様をExcelファイルで表すことがよくあるんだけど、これでは仕様が、ExcelファイルとCのソースコードの二重化にしてしまう。
これでは大変だとということで、Excelファイルから Excelマクロを使ってC言語で記述した簡単なテーブルを生成して二重化を防ぐことはやっている。しかし、中には簡単なテーブルではすまないくらい複雑な構造をもつものもある。そういうものは入力側のExcelマクロもしくは出力側のCで頑張って処理してやらないといけない。
これはこれで大変だということで、ExcelファイルをCSV形式にして、Rubyで処理、最後はerbでCのソースコードを生成という風にしようと思ってる。まだ作りかけだけど、今のところはこれで問題なさそう。Excelマクロだけではなくて使えるツールは使って、役に立つ自動化が進むといいな。

それと、今回の自動化ツールを作る際に、前から気になっていたRSpecを使ってみた。やってることはTestUnitと変わらないんだけれど、assertではなくshouldを使うとより「仕様」を書いている雰囲気がする。ただ、context と specification の使い分けがいまいちよくわからない。どういう粒度で書くと読みやすいか/わかりやすいか、まだコツがつかめてないのかな。
| YAGURA | - | 01:16 | comments(0) | trackbacks(0) |
    123
45678910
11121314151617
18192021222324
252627282930 
<< June 2017 >>

このページの先頭へ