83's

Top > Archives > 2008 > February

February 05, 2008

GaucheでMySQL/SQLiteの個人的まとめ 21:49

大体使い方がわかってきた。Gauche:DBI/DBD見れば わかるけど、一応流れをメモっておく。

MySQLのドライバはDBI | dev | Kahua Projectから、SQLite3のはそのページに見当たらないのでuchizonoにあったものを使わせてもらた。

レッツ・コネクト。

(use dbi)

(define *mysql-con* (dbi-connect "dbi:mysql:db=test;host=localhost" :username "root" :password "himitsu"))

(define *sqlite-con* (dbi-connect "dbi:sqlite3:path/to/db/test.db"))

クエリ。

(let1 q (dbi-prepare *mysql-con* "insert into books (name, price) values (?, ?)")
  (for-each (pa$ apply dbi-execute q) 
            '(("JavaScript" 4200) ("On Lisp" 3800))))

?に値を入れられるのがイカス。つまり

(dbi-execute q "JavaScript" 4200)

で1つめの?に"JavaScript"、2つめの?に4200。

手軽にやりたければ

(dbi-do *mysql-con* "insert into books (name, price) values (\"SICP\", 4600)")

次は結果の取り出し。

dbd/mysql.scmを見ると、クエリ結果のクラス<mysql-result-set><relation><sequence>を継承してる。

gosh> (use gauche.sequence)
gosh> (for-each print (dbi-do *mysql-con* "select * from books"))
#(1 4200 JavaScript)
#(2 3800 On Lisp)
#t

各レコードはベクタになってた。

ちなみにSQLiteのほうの<sqlite3-result-set><collection>を継承してる。

gosh> (use gauche.collection)
gosh> (for-each print (dbi-do *sqlite-con* "select * from books"))
(1 4200 JavaScript)
(2 3800 On Lisp)
#t

こっちはリストだった。

February 06, 2008

Shift + EnterでI'm Feeling Lucky 00:16

さっき発見したショートカッツ。

FirefoxのGoogleツールバーの検索ボックスに検索語を書いてShift + Enterしたら I'm Feeling Lucky。え、常識?

February 16, 2008

extend 18:10

GaucheでOOP中。

;; foo.scm
(define-module foo
  (export <foo> say))

(select-module foo)

(define-class <foo> () ())

(define-method say ((self <foo>))
  (print "hello"))

(provide "foo")
;; bar.scm
(define-module bar
  (use foo)
  (export <bar>))

(select-module bar)

(define-class <bar> (<foo>) ())

(provide "bar")
;; test.scm
(use bar)

(say (make <bar>))

test.scm実行するとunbound variable: sayっていうエラーになる。 useしたbarモジュールでfooのインタフェースがexportされていないから見えないってことか。

bar.scmを

- (use foo)
+ (extend foo)

したら通った。なるほど。 extend使うとbarをuseした文脈からfooモジュールでexportしたやつを見に行けるようになるわけか。

<bar>は<foo>を継承してるから初めのでいくかと思ってたけど、 まあよくよく考えてみると、そうか、そうだよね、という具合。

しっかし普段requireさえ書かなくて良いようなぬるい環境(= Rails)にいると、 こういうのがいろいろ面倒くさくていけない。 とりあえずdefine-moduleとselect-moduleとprovideに重複が! そうか、そこでマクロか。

February 20, 2008

省略可能な引数のためのマクロ 23:09

省略可能引数のパージング に便利なマクロが! というか無いと世知辛すぎる(´Д⊂

# Ruby
def foo(x, y = 0, z = 0)
  [x, y, z]
end


;; Gauche
(define (foo x . args)
  (let-optionals* args ((y 0) (z 0))
    (list x y z)))

省略が1個の場合はこんなのも。

# Ruby
def foo(x, y = nil)
  bar(x, y)
end


;; Gauche
(define (foo x . args)
  (bar x (get-optional args '())))

そしてキーワード引数も。

# Ruby
def foo(options = {})
  options[:x] ... 
  options[:y] ...
    ...
end
foo(:x => "ルビーの指輪")


;; Gauche
(define (foo . options)
  (let-keywords options ((x '()) (y '()))
    (... x ... y ...)))

(foo :x "main gauche")

おお。

まあこういうのは自分でマクロ書けばいかようにもなるけど、 超頻出なモンはオレオレマクロよりも合意のとれたものを使いたいんだよなぁ。 普通(≠ふつう)の趣味プログラマの心境としてはさ、 巻かれたくなるよね長いものに。そろそろ趣味グラマじゃなくなるけど。

あと関係ないけど

(define-method move ((self <dog>) x y)
  ...)

この定形パターンが結構めんどくさい。

February 21, 2008

t.referencesで外部キーの定義をちょっと簡単に、しかし明確に書ける 23:00

なんでかこういうちょっと気の利いたやつは知るとうれしくなってしまう。

マイグレーションでt.integer :tag_idと書くところをt.references :tagと書けるんだってさ。 確かに関連に使うフィールドはintのxxx_idって規約で決まってんだから、いちいちそんなこと書きたくないよね。 「referencesってintegerより長くなって指が絡まりそうだYO!」と言いたくなる衝動は :polymorphic => trueあたりを見てなだめていただきたい。DRY優先。 詳しくは以下。

TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type column if the :polymorphic option is supplied. If :polymorphic is a hash of options, these will be used when creating the _type column. So what can be written like this:

  create_table :taggings do |t|
    t.integer :tag_id, :tagger_id, :taggable_id
    t.string  :tagger_type
    t.string  :taggable_type, :default => 'Photo'
  end

Can also be written as follows using references:

  create_table :taggings do |t|
    t.references :tag
    t.references :tagger, :polymorphic => true
    t.references :taggable, :polymorphic => { :default => 'Photo' }
  end

ActiveRecord 2.0.xからかな。1の時からあったらショック。