トップ 最新 追記

Route 477



2007-05-01

[ruby] Re: シンボルというと(略)

僕も前に一度書いたことがありますが

Rubyのコードをたくさん読めば、「ここはシンボル使うしかないだろう!」って思えるようになるんですが、 理由を説明しろと言われると「だって記号っぽいから」「?」とかなりがち。

とりあえずは、

  • Symbolは軽い・わかりやすい・タイプ数が少ない というメリットがある。
  • プログラムの内部でしか使わない文字列に使う。
  • C言語のenum的な用途に使う。

という風に説明することにしています。

[idea][ruby] Visual optparse

optparseの設定を書くと自動的に(vrubyかなんかで)GUIを作ってくれるもんがあったら良いなぁ。

Rubyで書いたツールが簡単にCUI/GUI両対応に!

[hiki] orphanプラグインってひょっとして

ページタイトルでのリンクしか考慮に入れてない?

ページ名でのリンクがあるやつもorphanにカウントされてしまうような。

本日のツッコミ(全2件) [ツッコミを入れる]

zetamatta [前にお書きになった記事はいいですね。C言語の enum に関連付けてなら、うまく説明できそうです。ありがとうございま..]

yhara [おお、お役に立てて良かったです。C言語を知ってる人なら話は早いですよね。]


2007-05-02

[erlang] Erlang触ってみた

NコアのプロセッサならN倍速く動くというフレーズに釣られてErlang触ってみた。

Debianだとapt-get install erlang でインタプリタが入る。超簡単。

参考文献は以下のような感じ。

「!」でメッセージ送信ってのはπ計算を思い出すな。

reverseはこんな感じ (kmonos.netより)

reverse(List) ->
        case List of
                []          -> [];
                [Head|Tail] -> reverse(Tail) ++ [Head]
        end.

いかにも関数型っぽい。HaskellとかOCamlを知らない人は面食らうだろうなぁ。

ついでなんで文中にある「[|]だけのreverse」を実装してみた。

sample.erl:

-module(sample).
-export([reverse/1, revs/1]).

reverse(List) ->
        case List of
                []          -> [];
                [Head|Tail] -> reverse(Tail) ++ [Head]
        end.

rev(List, Rest) ->
        case Rest of
                []          -> List;
                [Head|Tail] -> rev([Head|List], Tail)
        end.

revs(List) -> rev([], List).

erlで起動。sample.erlを読み込んでみる。

yhara@meteor:~/src/erlang % erl
Erlang (BEAM) emulator version 5.5.2 [source] [64-bit] [async-threads:0] [kernel-poll:false]

Eshell V5.5.2  (abort with ^G)
1> c(sample).
{ok,sample}

とりあえずreverse。

2> reverse([1,2,3]).

=ERROR REPORT==== 3-May-2007::02:17:18 ===
Error in process <0.30.0> with exit value: {undef,[{shell_default,reverse,[[1,2,3]]},{erl_eval,do_apply,5},{shell,exprs,6},{shell,eval_loop,3}]}

** exited: {undef,[{shell_default,reverse,[[1,2,3]]},
                   {erl_eval,do_apply,5},
                   {shell,exprs,6},
                   {shell,eval_loop,3}]} **

エラーメッセージが絶望的に意味不明だが、「{undef,」の部分から未定義変数のなんからしいと分かる。

そうか、モジュールを指定しないと。

3> sample:reverse([1,2,3]).
[3,2,1]

こうね。

4> sample:revs([1,2,3]).
[3,2,1]
5>

うまく動いているようだ。

SDLバインディングもあるので(esdl) ゲームも作れる模様。 全てのキャラが並列に動作するゲームとか格好よくね!?

[erlang] SPOJに入ってないと思ったけどanagolにあるのか

新しい言語覚えたいけど何書いたらわからん〜って時はonline judgeはいいよね。 動作が合ってるかどうか自動で判定してくれるし。


2007-05-03

[scheme] SICPはじめました

http://sicp.g.hatena.ne.jp/yhara/

なんとなく勢いでSICP(日本語版)を買ってしまったので、淡々と問題を解いていこうかなと思います。 ユニットテストが書けそうなものはgauche.testを使ってテストファーストで。

[ruby] Ruby/AnarchyGolf

Hpricotを使って、AnarchyGolfのスクレイパを書いてみました。

使用例。

yhara@meteor:~/HTML/anagol % irb -r lib/anagol.rb
>> anagol = AnarchyGolf.new
=> #<AnarchyGolf:0x2aaaac15e9f0 @html={}>
>> langs = anagol.languages
=> [#<struct AnarchyGolf::Language name="Ruby", short_name="rb">, 
    (中略),
    #<struct AnarchyGolf::Language name="x86", short_name="out">]
>> probs = anagol.problems
=> [#<AnarchyGolf::Problem:0x2aaaacf21600 @name="hello world">, 
    (中略),
    #<AnarchyGolf::Problem:0x2aaaacf1dd70 @name="128 bits">]
>> hw = probs.first
=> #<AnarchyGolf::Problem:0x2aaaacf21600 @name="hello world">
>> hw.name
=> "hello world"
>> hw.url
=> "http://golf.shinh.org/p.rb?hello+world"
>> hw.description
=> "say "Hello, world!""
>> hw.deadline
=> nil
>> hw.revealed?
=> false
>> hw.ranking["Ruby"].first
=> #<struct AnarchyGolf::Problem::Score rank=1, lang="Ruby", user="eban", size=19, score=nil, time=0.1226, date="07/01/30 16:37:51", stat="?B / ?B / ?B">
>> hw.language_ranking.first
=> #<struct AnarchyGolf::Problem::Score rank=1, lang="PHP", user="konbu", size=13, score=10000, time=nil, date=nil, stat=nil>
>> hw.has_language?("Befunge")
=> true

problemsを呼んだときに各問題に対応するProblemのインスタンスが生成される……のですが、 problemsを呼ぶだけで全問題のURLにアクセスするとサーバに負荷がかかりすぎるので、 Problem#descriptionやProblem#rankingといったプロパティは「実際にアクセスされたときに初めて値を取りに行く」 ようになっています。

実装はこんな感じ。

module CachedAttribute
  def cached_attr_reader(*syms)
    syms.each do |attr|
      module_eval <<-EOD
        def #{attr}
          if defined? @#{attr}
            @#{attr}
          else
            @#{attr} = update_#{attr}
          end
        end
      EOD
    end
  end
end

class AnarchyGolf
  class Problem
    extend CachedAttribute
    cached_attr_reader :description, :deadline, :revealed
    cached_attr_reader :ranking, :language_ranking
    ...
    def update_ranking
      # 最初にProblem#rankingが呼ばれたときだけ実行される

さて、何がやりたかったかというと、UnlambdaとかErlangとかマイナーな言語の簡単なサンプルコードが欲しかったのでした。 *1 とりあえずanagol tableを作って目的は達成された…のですが、 実際にコードを見たところでgolfされてるから意味不明という罠が。しまった!

*1 最近の問題は一定時間で回答が公開されるようになってたりする

[ruby] twitter gemのソースを読んでみたんだが

%w(uri net/http yaml rubygems hpricot active_support).each { |f| require f }

そんなとこ省略すんなよw

[ruby] twitter gemのソースを読んでみたんだが(2)

rescue のあとに何も書かないのはエラーを見逃す可能性があるのでおすすめできない。

ちゃんと rescue ArgumentError とか、どの例外をキャッチするのか書きましょう。


2007-05-04

[ruby] zipメソッドって何に使うの?

http://d.hatena.ne.jp/seiunsky/20070425/1177522397

複数の配列を同時にイテレートしたいときとか。

例:

a = ["foo", "bar", "baz"]
b = [1,2,3]
ab = a.zip(b)  #=>  [["foo", 1], ["bar", 2], ["baz", 3]]
ab.each do |s, i|
  p [s, i]
end

出力:

["foo", 1]
["bar", 2]
["baz", 3]

例えば、今のRubyにはmap_with_indexがないですが

a = ["foo", "bar", "baz"]
a.zip((0...a.size).to_a).map{|s, i|
 "#{s}:#{i}"
}
#実行結果: ["foo:0", "bar:1", "baz:2"]

のようにzipで代用することができます(ちょっと長いけど…)。

他にも有用な使い道があったら教えてください。

#ちなみに僕もHaskell触るまでzipとかどう使うのか知りませんでした

[Ruby/SDL] SFontについて調べる

  • 1枚の画像をフォントとして使う
  • 半透明が使える(PNGの場合)
  • 文字幅が可変(文字と文字の間に紫の線が入る)

いま試したんだが、紫の線の幅には意味がないらしい。

こういうフォントを作ってみたけど

{  |     }

普通に表示された。

画像の説明

うーん、SFont 2.03のREADMEによれば 紫の線が文字幅に影響するのが正しい仕様のはずだが。

環境はRuby/SDL 1.3.0のWindows版バイナリ配布を使ってます。

[Ruby/SDL] "SFontとか簡単に自動生成できるだろ?"

そう思ってた時期が俺にもありました…。 要するに何も書いてない部分に紫の線を引けばいいんだろ?と思ってたんだが、これだと「"」の間にも線が引かれてしまう。

どうすりゃいいんだ。

デザインによっては「"」がひとつながりになってる場合もあるしなぁ(3Dっぽいやつとか)。 あとステンシルみたいに全部の文字に隙間があるデザインだったりすると壊滅的なことに(笑)。 まぁ最後は人間の手修正に頼るんだろうな。


2007-05-05

[erlang] ESDLが始まらない件

ESDL(Erlang/SDL)をちょっと触ってみようと思ってWindowsであれこれしてたんだが、 触る以前にインストール方法がわからない(苦笑)。

まず http://erlang.org/download.html からErlangのWindows用バイナリを落としてきてインストールして パスを通す。ここまでは良いよな。 次に http://esdl.sourceforge.net/ からESDLのWindows用バイナリ*1をダウンロードする。

んで、include/*.hrlをtest/以下にコピーして、priv/ (ここにdllが入ってる)にパスを通して…

[D:\research\Erlang\esdl-0.96.0626-win\test]erl -pa ../ebin/
Eshell V5.5.4  (abort with ^G)
1> c(testsprite).
./testsprite.erl:30: Warning: variable 'Server' is unused
./testsprite.erl:173: Warning: variable 'Palette' is unused
./testsprite.erl:194: Warning: variable 'SpriteH' is unused
./testsprite.erl:194: Warning: variable 'SpriteW' is unused
./testsprite.erl:194: Warning: variable 'WinH' is unused
./testsprite.erl:194: Warning: variable 'WinW' is unused
./testsprite.erl:233: Warning: variable 'PFormat' is unused
{ok,testsprite}

おおっ。

2> testsprite:go().
Driver Failed {error,driver_incorrect_version}

=ERROR REPORT==== 6-May-2007::03:10:14 ===
Error in process <0.29.0> with exit value: {einval,[{erlang,open_port,[{spawn,"s
dl_driver"},[binary]]},{sdl,init,1},{testsprite,go,1},{erl_eval,do_apply,5},{she
ll,exprs,6},{shell,eval_loop,3}]}

** exited: {einval,[{erlang,open_port,[{spawn,"sdl_driver"},[binary]]},
                    {sdl,init,1},
                    {testsprite,go,1},
                    {erl_eval,do_apply,5},
                    {shell,exprs,6},
                    {shell,eval_loop,3}]} **

(´・ω・`)

*1 ってのがそもそも良く分かってない。.dllのことなのか.beamのことなのか


2007-05-10

[scheme][event] gauche.night

  |l、{   j} /,,ィ//|     /‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
  i|:!ヾ、_ノ/ u {:}//ヘ     | 
  |リ u' }  ,ノ _,!V,ハ |    < 『Gaucheのイベントを見に行ったと思ったら
  fト、_{ル{,ィ'eラ , タ人.   |  喫茶店でdankogaiと徹夜していた』
 ヾ|宀| {´,)⌒`/ |<ヽトiゝ     | 
  ヽ iLレ  u' | | ヾlトハ〉.  \____________________
   ハ !ニ⊇ '/:}  V:::::ヽ.    
  /:::丶'T'' /u' __ /:::::::/`ヽ 

何を言ってるか(以下略

danさん、masa_edwさん、Theoriaさん、黄さん、松村さん (あとshiroさん、ruiさん) お疲れ様でした。

Gauche Night本編はなんとも風変わりなイベントでした(笑)。会場がライブハウスな時点で既に「その発想はなかった」。 座談会もデモもそのあとも非常に面白かったです。スタッフの皆様(gauche.knightっていう名前だったのか)に感謝。

Schemeとプログラミングについていろいろ考えたよ。

座談会の内容に関してメモを取ったのであとで書く予定。でも量が多いんだよなぁ(B5にして2枚半)。めげそう。


2007-05-19

[event][haskell] Haskell勉強会#4

ブログを書くまでが勉強会らしいので書きます。 (あれ、そういえば氏久さんのブログってないのかな)(5/26追記:あった!)

今日は6.1から6.6まで進みました。

4797336021

関数の型宣言

(&&) :: Bool -> Bool -> Bool

という感じで a && b という演算子の型が定義されるんだけどこれHaskell知らん人から見たら意味不明だよね。 毎回型宣言だけは必ず復習したほうが良さそうだ。

演算子が自分で定義できる

Haskellでは演算子を自分で好きに定義できる(a +++ b とか、a .+. b とか)。 というか記号だけでできた関数名にするとちゅうち記法(←なぜか変換できない)で使えるようになるらしい。

というわけで顔文字演算子を定義してみた。

(^-^) :: String -> String -> String
(^-^) x y = x ++ " love " ++ y

main = print $ "I" ^-^ "Haskell"
yhara@meteor:~/tmp % runhugs lovehaskell.hs
"I love Haskell"

もしくは

main = print $ (^-^) "I" "Haskell"

でも可。

基本的に演算子は中置記法(例:a + b)、普通の関数は前置記法(例:f x y)なのだが、 カッコを付けると演算子も前置記法にできるし(例:(+) a b)、バッククオートでくくると普通の関数も中置記法に できる(例:x `f` y)。

表にしてみる。

表記演算子普通の関数
中置記法a + bx `f` y
前置記法(+) a bf x y

後置記法はHaskellにはない…ですよね。

上の「ちゅうち記法」っていうのはもちろん中置記法のことなんだけど「ちゅうち」ではなく「なかおき」 と書かないとMS-IMEは変換してくれない。じゃあ「なかおききほう」という読み方が正しいのか!?と一瞬思ったのだが、 実は茶道の用語に「なかおき」というものがあるらしいのであくまでも「ちゅうちきほう」が正しい…と思う。

とか言ってる間に辞書登録しろよっていう話だな。

整数型

HaskellにはInt型(32bitなやつ)とInteger型(任意の大きさが扱えるやつ)の2種類の整数がある。 RubyでいうFixnumとBignumか。 RubyだとFixnumとBignumの区別は特に考えない(勝手に変換される)んだけど、Haskellだとそれらは明確に区別されるようだ。

hugsで実験してみよう。

IntとIntを掛け算すると、オーバーフローして負数になる場合がある。

Prelude> (20000000 :: Int) * (2000000000 :: Int)
-1090256896

Integer同士だとオーバーフローはしない。

Prelude> (20000000 :: Integer) * (2000000000 :: Integer)
40000000000000000

型を何も書かないと自動的にIntegerとして扱ってくれるみたいだ(どうなってるんだろう?)

Prelude> (20000000 * 2000000000)
40000000000000000

片方がIntで、片方がIntegerだとType errorになる。

Prelude> (20000000 :: Int) * (2000000000 :: Integer)
ERROR - Type error in application
*** Expression     : 20000000 * 2000000000
*** Term           : 20000000
*** Type           : Int
*** Does not match : Integer

こういう場合はtoIntegerという関数でIntな整数をIntegerに変換してやればいいんだけど、 それもちょっと面倒だよねってことでHaskellの時期仕様ではいろいろ検討されているらしい(ikegamiさん情報)。

zipの話

zipっていうのはこういう風に2つのリストを「横に繋げる」関数。

Prelude> zip [1,2,3] [4,5,6]
[(1,4),(2,5),(3,6)]

返り値はタプルのリストになる。

ちなみにRubyにもArray#zipというメソッドがある。

>> [1,2,3].zip([4,5,6])
=> [[1, 4], [2, 5], [3, 6]]

RubyにはタプルがないのでArrayのArrayになるけど。

id:ha-tanさんが「Haskellを知るまでなんでこんなメソッドがあるのか分からなかった」と言ってて、激しく同意(笑)。

リスト内包表現

数学で集合を表現するときに { x | ∀x ∈ {1,2,3,4,5,6}, x mod 2 = 0} みたいに書くけど、それがそのまま

Prelude> [x | x <- [1,2,3,4,5,6], x `mod` 2 == 0]
[2,4,6]

みたいに表記できる。

もちろんmap関数とfilter関数を使えば書けるんだけど、より数学っぽく掛けて良いよね。という。

打ち上げ:インデアンカレー

やばい。

甘いのに辛いよ。

卵がないと無理。

来週は

るびま読書会#2です。

お疲れ様でした。

[misc] 最近調子が悪いもの

周辺機器がいろいろヤバい。

HHKB

ゲームをプレイしてるとときどき「→」キーが勝手に入力される。ゲームにならん。

これはハック以外はするなというHHKBの意思か…?

外付けHDD

こいつをUSBで繋いでるとWindowsがレジュームに失敗する。というかマシン起動時のメモリチェックで固まるので Windowsは関係ない気もするが。

仕方ないので毎回起動時だけUSBケーブルを外している。ダサい。

プリンタ

100%の確率で紙が詰まるので終了。これでは単なるでかいスキャナだ。


2007-05-20

[ruby][Ruby/SDL] るびまに記事を書きました

先日リリースされたRubyist Magazine 19号と、2月にリリースされた18号にRuby/SDLの入門記事を書かせていただきました。

編集の方々には記事のチェックをしていただいたり、催促を頂いたり^^; いろいろとお世話になりました。 ここで改めて感謝したいと思います。どうもありがとうございました。

ブログに書くのと、るびまに書くのはどこが違うか

  • るびまの方が多くの人に読んでもらえる。
  • ブログより長い時間をかけて一つの記事を書くことになる。
  • 締め切りが発生するので、記事が完成する確率が高くなる。
  • いつもより人目を意識するので、調査にかける時間が長くなる。*1

さあ、次は君の番なんだぜ?記事の申し込みはまで。

*1  特に今回はフォント関係の調査がいろいろ進んだ。(締め切りがないとなかなかやらないんだよね、こういうの)

[misc] というわけで

それを書いているyharaさんだったのでした。こんにちはこんにちは!!

そうか、「KMCのyharaです」と名乗れば良かったのか。KMCは大抵「よく知られているか、全く知らないか」の どっちかだからなぁ。名前の影響範囲の分布が未だに謎です。

言い残したことがあればブログに書いてもらえれば読みますんでよろしくどうぞ。

[prog][event] 琵琶湖あたりでコーディング合宿しようぜ

最近、関西では毎週のように何かの言語の勉強会があって幸せ(笑)です。

が、勉強するだけではものは生産されないわけで…

あとは、モノをガンガン作ることでしょうか。

[ryan’s blogより引用]

ということで、そろそろコーディング合宿とかどうですかね? :-)

とりあえず、週末のHaskell勉強会ではこべさんを誘ってみました。 (6月あたりに実行すると、こう、未踏ユースの追い込み時期と重なって良いんじゃないかとw)

IRC(wide)に #biwako-dev というチャンネルがあるので、興味のある方はお越しくださいませ。

[prog] ある処理の途中にデバッグプリントを突っ込みたい

JavaScript の関数を「引数そのまま返す化」を見て、 Ruby 1.9に入るとか入らないとかの Object#tap とか、HaskellのDebug.Traceを思い出した。

やりたいこと:

obj.method  # <= このobjをデバッグプリントしたい。 (p obj; obj.method って書くのはなんか面倒じゃん?)

Ruby: (Object#tap)

obj.tap{|o| p o}.method

Javascript: (リンク先の手法)

alert.s(obj).method();

Haskell: (Debug.Trace)

main = trace (show x)) $ f x  -- showはいろんなものを文字列化する関数
  • Object#tapがオブジェクト側に仕掛けを組み込むのに対し、function sはメソッド側に定義されているのが面白かった。
  • RubyやJavascriptでは単に「手間を省くための手法」だが、Haskellでは「print x; f x」みたいな書き方ができないので有り難味が増している。

2007-05-21

[scheme] unfoldの使い方がわからない

from http://d.hatena.ne.jp/rui314/20070521/p1

なんかfoldの逆を行う関数(unfold)があるらしい。

  • fold → リストを順番に畳みこんで値にする
  • unfold → 値を順番に並べてリストにする

google code searchにこんなコードが

(define (fontset->list-of-patterns fs)
  (let ((count (xft-fontset-count fs)))
    (unfold
     (lambda (x)
       (equal? count x))
     (lambda (index)
       (xft-pattern-duplicate
	(xft-fontset-ref fs index)))
     (lambda (x)
       (+ x 1))
     0)))

なんか、do の代わりに使えそうな感じか?

iotaでも作ってみるかな。

(use srfi-1)

(define (my-iota to from)
  (unfold
    (lambda (i) (> i to)) ;終了条件
    identity              ;種から値を作る
    (lambda (i) (+ i 1))  ;種から次の種を作る
    from))                ;最初の種

(display (my-iota 10 1))
yhara@meteor:~/HTML/gauref % gosh sample-unfold.scm
(1 2 3 4 5 6 7 8 9 10)

わーい iota できたよー。

[scheme] unfoldでstring-tailsを作ってみた

例えば "hoge" という文字列から ("hoge" "oge" "ge" "e") というリストを作りたいとしよう。

これはunfoldを用いて以下のように書ける。

(define (string-tails str) 
  (unfold (cut = (string-length str) <>)
          (cut string-drop str <>) 
          (cut + 1 <>) 
          0))

(なんとなくlambdaの代わりにcutを使いまくってみました)

試してみよう。

gosh> (string-tails "hoge")
("hoge" "oge" "ge" "e")

うまく動いている模様。

しかし「それiotaとmapでできるよ」と言われそうな予感も。

(define (string-tails str) 
  (map (cut string-drop str <>) 
       (iota (string-length str)))) 

うーん、こっちの方が短いし分かりやすい気がしてきた^^;

余談1 : リストのtails

Haskellだとimport Listしてtailsで一発である。Schemeでもリストのtailsは下のように簡単に書けるのだが、 Schemeでは文字列はリストではないのでこれを文字列に適用することはできない。

(use srfi-1)
(define (tails ls) (pair-fold cons '() ls)) ;pair-foldはcdrに対してfoldするやつ

余談2 : 部分適用

あと (+) 1 の方が (cut + 1 <>) より格好いい。よってHaskellは格好いい。

と思ったが、Schemeにもpa$というのがあるらしい。(pa$ + 1)とかか。

pa$を使ってtailsを書き直してみよう。

;unfold版
(define (string-tails str) 
  (unfold (pa$ = (string-length str))
          (pa$ string-drop str) 
          (pa$ + 1) 
          0))
;iota+map版
(define (string-tails str) 
  (map (pa$ string-drop str) 
       (iota (string-length str)))) 

短くはなったが、こんなコード、慣れてないと絶対読めんな(笑)。


2007-05-23

[kmc][event] Binary Hacks読書会

Binary Hacksをみんなで読もうというイベントをやってみた。予習一切なし。本が一冊しかないので、Extream Readingですらない(笑)。 各節ごとに担当を決めて、その人が本を読む。で、サンプルコマンドをみんなで打ち込んで試してみる。

おおよそ2時間で#1〜#5まで進んだ。

面白かったので次回も続けてやるつもり。

[kmc] プロジェクタ始まったな

KMCの部室にプロジェクタが導入された。

一応、講座のときに便利だろうというのが主な目的なのだが、 *1 既にWii Sportsやレースゲーなどいろいろと活用されているようだ(^^;。昨日は大画面で変愚をやってみた。 人のプレイをだらだら見ながらツッコミを入れるのはなかなか楽しい。

そう、部室の壁にスクリーンが設置されているので、本当に大画面なのだ。72インチだっけ。なんかそれくらい。 Binary Hacks読書会でも担当者のノートパソコンを投影したのだが、 なんと、プレゼンのためにputtyの文字サイズを大きくする必要がない(笑)。これは便利だ。

あと、プロジェクタとスクリーンの間に腕を伸ばせば(スクリーンに手の影が映るので)レーザーポインタの代わりになる。これは非常に面白い。直感的なUIという意味ではWiiリモコン以上だ。

この手法を用いてウィンドウ移動とかドラッグ&ドロップとかできないかな?という話が出た。未踏で、レーザーポインタでパワポを操作するやつがあったよね。 あれの応用でできないだろうか。

*1 KMCでは週に2回ミーティングがあって、そのときに上回生が持ち回りで15〜20分程度の短い講座をする。


2007-05-24

[haskell] できるのが重要なのではなく、簡単に使えることが重要

この前の勉強会の補足。

遅延評価の利点に「無限リストが使える」ってのが挙げられていた。でも正確に言えば、これはHaskellだけの特徴ではない。 クロージャが用意されている言語ならRubyだろうとPerlだろうとJavascriptだろうと、遅延したい処理をクロージャとして渡してやることで (面倒ではあるが) 無限リストのようなものが作れるからだ。

じゃあHaskellの特徴は何かっていうと、それは遅延評価がデフォルトであることだ。[1..]のような超簡単な記述で無限リストが使えて、それは 普通のリストと同じようにmapしたりfilterしたりn番目の要素を取ってきたりできる。そこにはもう有限と無限の区別がない。

無限リストが「ふつうに」使える世界では、きっと見たこともないやり方で問題を解いたりするのだろう。後半の章が楽しみだ。


2007-05-25

[event][ruby] るびま読書会#2 (ログ)

あとで書くあとで書いた。

氏久さんからcuzicさんに主催がバトンタッチされたるびま読書会。2回目は4章のTropyを読みました。 関西○○勉強会は学生がけっこう多いのですが、今日はなんと学生は僕だけでした。(学生の方が平日忙しい???)

今回は誤植も間違いも見つかりませんでした。:-)

僕がロガーをしたのでログを貼っておきます。長いです。

128〜140

  • require "cgi"を毎回書くべきか?
    • 使うところではrequireしよう(何回requireしても一回しか読み込まれないんだし)
    • どっちかというと、CGI.newを渡しているのが問題(→後ほど添削?)
    • 青木さんの添削は原型をとどめてないことが(同じ仕様の別のプログラムを作っている)
      • たまに仕様も変わる(笑)
  • rdefsって何?
    • 青木さん作のプログラム、Rubyスクリプトの定義を全部拾ってくれる
  • Marshalって何?
    • オブジェクトを文字列化するもの(PHPのSerialize, PerlのStorable, JavaのSerializableのような)
    • Deep Copyに使ったりするよね(dup, cloneは浅いコピー)
      • "dup, cloneは浅いコピーです" と言ってしまうとちょっと正確ではない
      • (ObjectやArrayのdup/cloneが浅いコピーであるだけで、自前のクラスのdupを深いコピーとして実装することは可能)
  • dupやcloneっていつ使うの?
    • 破壊的メソッドの影響をほかに与えたくないとき
    • 破壊的メソッドを使わない(オブジェクトを一度作ったら変更しない)プログラミングスタイルでは、浅いコピーも深いコピーもあんまり気にしなくていい
    • StringやArrayの「<<」は破壊的、「+=」は非破壊的
  • msgって駄目?OK?
    • あとで添削される
  • Tropyとは
    • RandomしかないWikiみたいなもん
      • Wikiに認証がないのは普及に重要だったよね
  • Tropy::Tropyという名前は駄目か
    • Rinda::RindaはOKだよね(笑)
    • 名前重要(呼びたくなる名前ならOK?)
    • ITベンチャーの人とカラオケ行くとブルーハーツ/尾崎豊率が高い(らしい)
  • コンポジションって何?
    • 継承(is_a) / コンポジション(has_a, 継承の「親」にあたるクラスのインスタンスを持っておく)
    • Rubyでは実行中にメソッドを付け加えられる(全てが実行時)
  • 委譲
    • コンポジションを利用して、呼ばれたメソッドを別のインスタンスにそのまま受け流す
    • 「既存のクラスに機能を追加したクラス」が作れる(Arrayを利用してスタックを作るとか)
    • require 'delegate'とかrequire 'forwardable'とか(るびま参照)
    • delegateは全部委譲する。forwardableは指定したものだけ委譲する。
  • 継承をいつ使う?(Ruby vs Java)
    • Rubyだとあまり継承は使わない(継承が必要ないことが多い)
    • Rubyだと、クラスを気にせずに多態できる [a, b, c].each{|x| x.hoge}
    • 継承の種類→インターフェイスの継承(Rubyでは継承不要)、実装の継承(delegate,forwardableでできる)、メソッドコールの厳密化(Rubyではそもそも不可能^^;)、多態(Rubyでは継承不要)
    • ひとくちにオブジェクト指向といってもそのやり方は言語によっていろいろ
      • JavaにはJavaの、RubyにはRubyのBest Practiceがある
  • RubyはJavaよりRTTI(実行時型情報)の仕様に寛容だと思う(cuzicさん)
    • case obj when String ... when Array ... みたいな
      • でも青木さんはこれ嫌いだよね
    • Rubyのクラスは型というか、メソッドの集合?
  • 例えばTemplate Methodパターン
    • Rubyなら、親クラスを作らずにTemplate Methodすることができる(そういう選択肢もある)
    • (Java) 設計の段階で継承するべきところは決めておきたい.(実装/テストphaseで継承を追加とかは怖いしやりたくない)
    • 仕様変更の影響度を小さくしたい.
  • 集合のクラスを作るか、クラスメソッドで済ますか?
    • 複数の果物(class Fruit)からミックスジュースを作る関数が欲しいとする。
    • 案1: 果物の集合を表すクラスを作る
class FruitsBasket # Arrayを継承するか委譲する
  def to_juice
    @fruits.inject{(果物を潰してジュースにする)}
  end
  ...
end
    • 案2: Fruitのクラスメソッドにする
class Fruit
  def self.make_juice(fruits) # fruitsはFruitの配列
    fruits.inject{ ... }
  end
  ...
end
    • 実際Ruby on Railsで案2のようなクラスメソッドの使い方がされているらしい。
    • どっちがいい?
    • "集合として" 何かしたいなら案1?
    • 集合の種類が複数あって、種類ごとに違うことをするなら案1 (Personの集合→Friends, Rivals, Family とか) (Rivalsには戦うというメソッドがあって、Friendsには友情を確かめ合うメソッド(?)があって…みたいな)
    • (このへん良くわかんなかったのでログ取れず)
  • Javaのinterface
    • 「このメソッドは絶対実装しないといけない」
    • 共通してる部分と共通してない部分が混じってるときにどうするか
      • 委譲する
      • 一段増やす(implementしてるやつをextendする)
  • デザインパターンが自然に(意識せずに)実装できる
  • 継承や多態があればifや分岐を全て取り除ける
    • まぁ適材適所では?(分岐が向いているところもある)

141〜145

  • インスタンス変数の濫用について
    • インスタンス変数が多いと、irbでinspectしたときに表示が長くなって面倒ですよねw
      • それ ;1 で (例 > obj.method ; 1) (参考)
    • C-x r t rectangle-insert
    • 矩形(くけい)
    • 業界最大手・月極駐車場
  • newの中でinitializeが呼ばれる

[ruby][event]るびま読書会#2 (KPTと感想)

K

  • ちゃんと開催できた:-)
  • ネットワークが使える会場
  • 継承の話、オブジェクト指向
  • 浅いコピーと深いコピー
  • delegateとforwardable(→るびま参照)
  • ホワイトボード重要

P

  • 会場が見つけづらい(水道局の建物の中です。)
  • 脱線が長すぎたかも
  • LANハブがない

T

  • LANハブを用意する。ペン、電源、LANケーブルは借りられる
  • ロガーが複数いてもいい
  • ブログに書こう
  • タイムキーパー(あんまり脱線したら止める人)

感想

JavaとRubyでのオブジェクト指向の比較が面白かった。Javaで真面目に開発とかデザインパターンとかやったことないしなぁ。 Javaだと継承を頻繁に使うっぽい。

良くなかった点としては、ちょっとRuby初心者の方を置き去りにしたかなぁ…というところ。後半からほとんど喋ってる面子が固定されてたし。

個人的には、「早く読み終わった人は続きを先に読んでもいい」というルールは無くした方が良いと思う。 先読みアリだと速い人はどんどん先に進んでしまうし、初心者はそんなに早く読めないので。

なんか、みんな読み終わってるとプレッシャーなんですよね(笑)。僕も、ログを書いてて読むのが遅れてたときに、読み終わってないのに名札を立てたりしちゃったし。いかんな。

早く読み終わった人はログを書くといいと思います。

おまけ

dupってどう読むのが一般的なんでしょうか?だっぷ?でゅぷ?

本日のツッコミ(全3件) [ツッコミを入れる]

cuzic [あとで書くの内容待っているよんっ。]

yhara [あとで書いた! 遅くなってすみません。催促ありがとうございます。]

cuzic [いえいえっ。急かしてしまったようで、すいませんでしたっっ。 こうまとめて書いてもらえると思い出しますね。 ありがと..]


2007-05-29

[softs] Firefoxの許せないところ

  • about="_blank" が新規ウィンドウで開く。お前はそれでもタブブラウザか。
  • C-hで履歴が開く。いやWindows版は仕方ないとしても、せめてLinux版はBackspaceとして振舞ってくれよ。

いやまあTab Mix Plusを入れればいいんですけど、 「新規ウィンドウを開かない」くらいデフォルトでできてほしい。

[ruby] それany?で

link_exist = (doc/:a).any?{|a| a[:href] == 'http://example.com:3000'}

最初「それfindで」というタイトルにしてて、書いてる途中でany?のことを思い出したのは秘密。

あとEnumerable any?で検索するるりまが一番上に 来ますね。リプレースはすでに始まっているのだ。

[Ruby/SDL] 等幅フォントじゃないと点数表示がぐらぐらして鬱陶しいんじゃね?という指摘

http://blawat2015.no-ip.com/~mieki256/diary/200705274.html#200705274S1

その発想はなかった!確かにそうだなぁ。

「"」の分割問題については、ご指摘の通り「ひとつ多かったら " が分かれているものと見なす」という方針にしました。 というか、頑張ってアルゴリズムを考えるよりも、簡単に確認を行えるようにしておいて人間に判断してもらうというアプローチの方が良さそうです。

1文字ずつ画像を作るのは面倒だから駄目です(笑)。いや、そういう仕様にしても 人によっては使ってくれると思うんだけど、それはその人の時間を無駄に消費させている気がしてやだ。

とか書いてる暇があったらリリースしないと…。[たぶん明日やる]

[ruby] いまさらFizzBuzz

puts (1..99).map{|i|
  fizzbuzz = (i%3==0 ? "Fizz" : "") + (i%5==0 ? "Buzz" : "")
  fizzbuzz.empty? ? i.to_s : fizzbuzz
}

面接で「学生時代に力を入れたことは何ですか」だの聞かれるより、FizzBuzzのコードを書かされる方が100万倍いい。

[prog] 関数型プログラマはプログラムを木だと思ってるらしい

gauche.nightで出た話題だけど、関数型プログラマはプログラムを木だと思ってるらしい。

(car (string-split
       (string-reverse (string-upcase str))
       "\n"))

うん、これは木だ。

head $ lines $ reverse $ upcase str

Haskellだと $ があるから見た目はネストしてないけど、実際には関数に関数の返り値を渡している。

そう、関数型プログラマは関数呼び出しの中に関数を書くことに抵抗がない。でもC言語とかだとさ、 関数呼び出しの中に関数って書かないじゃん、普通。すごく短いやつを除けば、だいたい一旦変数に代入するでしょ。

そのへんの違いが関数型言語を学ぶときの抵抗になってるのかなぁと思った。

そういう目で見れば、Rubyのメソッドチェーンは 「木構造を使わずに関数的な処理を書くための発明」っていう風に見えてきませんか?

str.upcase.reverse.to_a.first

[befunge] befunge-wiki

これはやべぇwwwwwwwwwwwwwww思わずbefungeカテゴリを新設した。

ていうかBefungeで書かれた実用的なアプリケーションという意味では世界初だったりしないすかね?

[net] 自宅サーバの台数

えーと、その母集合だと明らかに平均は1未満かと(笑)。

ていうか、自宅サーバを2台以上持つっていう発想が無かったよ。 KMCでも何人かサーバ立ててるけど、みんな1台だと思う。

ちなみにうちのサーバはMac miniですけどまだ何も動かしてないし外から見えません(それを人はサーバと呼ばない)。

[net] LDR

登録フィード数: 497件

あと3つで500。っていうかさっき4件ほど追加したからもう500超えたか。

僕はPCかMP3プレーヤーでしか音楽を聴かないので、聴きたかったCDがCCCDだと非常にがっかりする。 CCCDで発売するっていうのは、僕にとっては発売しないのと同じだ。

…っていうのと同じで、SubscribeしようとしたブログがRSSを出力してないとがっかりするようになりつつある(はいはいそれPlaそれPla)

[scheme] 熟練したScheme使いは再帰を書かない

いや書かないは嘘だけど、リストを扱う関数が充実してるので自分で再帰してどうこう…っていうのは あまりしなくていいことが最近分かってきた。例えばfoldとか。

あとGaucheには何をするにも低水準(高パフォーマンス)と高水準(使いやすい)のAPIが用意してあって、 「LispはもうひとつのC」を連想した。

[ruby] 継続についての記事を書こうと思って早3ヶ月

人はこれを[あとで書かない]と呼ぶ。

じゃなくて、えーと、YARVに継続が入った記念に概略だけ書くと

  • 継続は「プログラムの残りの部分」のこと。
    • すごく直感的に言うと、RPGにおけるセーブポイントみたいなのを想像するといい。宿屋の主人に話しかけると「現在の状態」をセーブできる。ダンジョンを探索中に「ロード」すると、セーブした瞬間からゲームをやり直せる。
  • 継続ってSchemeとかRubyでしか使えないんでしょ?
    • →これは誤解。「プログラムの残りの部分」なんだから、「プログラムあるところに継続あり」。

バトー、忘れないで。あなたがプログラムを書くとき、継続は必ずあなたの側にいる。

[http://tsukimi.agusa.i.is.nagoya-u.ac.jp/~sydney/ocaml/index.php?%B7%D1%C2%B3より引用]

  • じゃあSchemeやRubyは何が違うのよ?
    • →call/ccがあるのが違う。これはcall-with-current-continuationの略で、RPGで例えると どこでもセーブできる みたいなもん。宿屋でもダンジョンでも戦闘中でも。
    • call/ccを呼ぶと、「call/ccを呼んだ瞬間」をセーブした継続オブジェクトがもらえる。この継続オブジェクトを実行すると、セーブしたところからプログラムが再開される。
  • call/ccがあると何ができるんでしょうか
    • 関数的setjmpというか、λ計算的gotoというかなんというか
    • 実行順序を好きなように蹂躙できる。メソッドを超えてジャンプできる点でgotoより遙かに凶悪。諸刃の剣。
    • 代表的な使い方としては、「プログラムをちょっとだけ止めてあとで再開する」ってのがある。
      • ザ・ワールド
    • Rubyのyieldが自前で実装できる。とか。
  • 「継続渡し」っていうのはcall/ccと関係ある?
    • ありません。別物です
    • 任意の再帰関数は「プログラムの残りの計算」を引数にとるように書き換えることで末尾再帰にできる。という定理があって、この書き換えがCPS変換と呼ばれています*1。CPSは「Continuation Passing Style(継続渡し形式)」の略ね。
  • 継続のRubyでの利用例
    • 時を止めるやつ
      • コルーチン (ゲームのイベント部分の記述に使ったことあり。効果大。)
      • Webアプリ
    • 実行順序を操作するやつ

継続の弱点はやっぱり慣れないと非常に読みにくいっていう点だと思う。変数名を工夫するとかメソッドにラップするとかしないとな。

あと継続を理解するにはjsSchemeのソースを追っかけるのが良かった。内部構造を見れば、「ああこれが継続か」って思うよ。たぶん。

*1 合ってます?


2007-05-30

[idea] 動作コンビネータ

関数型らしいゲームプログラミングってないかなぁという話について。

パーサコンビネータみたいに「動作」をつなげて記述するというアプローチはどうだろうか。

move_square = move_right 10 <+> move_down 10 <+> move_left 10 <+> move_top

[prog] コーディングって呼ばないで

コーディングってプログラミングのかっこいい言い方だと思ってました。

[prog] おまいらは「scanf=セキュリティホール」で思考停止していないか

scanf("%s", &buf); が危険なのは分かるんですけど、scanf("%d", &a); って危険なんですかね?

(追記:aをchar型で宣言してたりすると危険ですね。)