2015年12月17日木曜日

Smalltalk ではどれくらいまで長いクラス名が標準で使われているものなのか

Smalltalk Advent Calendar 2015 #Qiita の 12月16日の記事になります。

仕事で結構長いクラス名ついてるなー、っていう感じのヤツが Seaside にふくまれてい
て、コードを書くなどしていました。まあ、それはそれとして「標準で配布されているイメージで定義されているクラスの名前のうち、いちばん長いものってどれくらいの長さなの?」って気になっちゃったんですよ。

気になったら調べてみよう。ということで、やってみました。
環境は Smalltalk Pharo 5 です。



コードとしてはこんな感じ。
| allClasses |
allClasses := Smalltalk allClasses collect:  [ :each |  each name ].
allClasses sort: [ :a :b | a size < b size ].
allClasses inspect.
はい。他の処理系で試してみると違う結果が出るかもしれませんね。

Pharo 5 での結果は以下のようになりました。

どうやら
RBLiteralArrayContainsSuspiciousTrueFalseOrNilRule
というクラスがいちばん長いクラス名のようです。50文字です。2位は48文字で2文字差でのトップとなりました。

上の方だけみていると、フォントがプロポーショナルなためか、これより横幅が長く表示されているものがあって、ほんとうにこの結果あってるの?と思いましたが、下位の方をみてみると確かにきちんとソートできている模様ですね。



こういったシステム全体を俯瞰してすべてに対しての見通しがよいというのも Smalltalk のよさですね。

みなさんも「どんなメソッド名がいちばんよく使われているか」など気になったら調べてみると面白いかもしれません。

2015年12月15日火曜日

Smalltalk でシステムの基幹部を作っている会社に転職した話

pyspa Advent Calendar 2015 の 12月14日のエントリでありつつ、Smalltalk Advent Calendar 2015 の12月22日のエントリです。

「pyspa のこと、ナニ書こうかな?」って思ってたんたけど、よく見たら自分の好きなことでよかった。

こんなワタクシは数学における四択問題の解答欄に数式を細かく書いて不正解となるようなバカでした。人の話はちゃんと聞く、見る。大切ですね。はい。

そして、記事を書き終え、クリスマスを迎えた本日12月25日に Smalltalk の話でもあったな、ということで Smalltalk Advent Calendar 2015 12月22日のエントリとしました。

転職

わたくしの今年のトピックはなんといっても転職ですね。
今年の8月まで水色の六角形の会社で働いておりましたが、実際のところ、一昨年の夏くらいから、紫色の楕円をみると痙攣しそうになる病気になってましたね。いま思うと。

しかし、全部丸投げしてもらったものは赤い宝石で大勝利できたり、今年の頭くらいからちょくちょく赤いコードのレビューもしていたんですよね。さすがに紫の楕円だけではみな痙攣するようになってきたか、と思ったんですがレビューすると赤い世界では `SomeObject#true_or_false?` 的なものが `SomeObject#isTrueOrFalse` とか書いてありまして、クソ真面目にレビューで「これはなんか赤くないので治せってば」ってマサカリ投げてみたりすると「移植性を優先します」みたいなコメントが返信されてきちゃったりなんかして、クソワロスでした。

はー、もう。人海戦術の世界では何かがおかしくても、みなおかしいと分かりつつ、自分の船だけ前に進めようとして、全体として前に進んでいなくてもいいっていう雰囲気になるんだなぁって思ったんですよね。意思統一が計られていて、きちんと郷に入れば郷に従えを守るメリットを知ったるステージで仕事したいなぁと思うようになったんですよ。

そんなときに、 Smalltalk 界隈の重鎮から Smalltalk-er が不足していて困っている、という連絡をいただくことができまして、そのまま Smalltalk で仕事している会社に転職してしまいました。
ちなみに、誘っていただいた方とは15年くらい前にはじめて知りあった感じです。大学生時代にアルバイトしていたソフトウェアハウスが自社製の Smalltalk の処理系を作成し、それを用いて Linux 向けや Windows 向けのアプリケーションを動作させ、高速化させる必要のあるリリース版の作成には各プラットフォーム向けに C言語 のコードを生成するっていうヤツ作っていたんです。そんなもんで、たぶん自分がプログラミングしてはじめて給金してもらった仕事は「独自 Smalltalk 処理系向けに GTK のバインディングと Win32 API のバインディングを書きながら、 Smalltalk VM の修正した」というヤツになりますね。我ながらクレイジーですね。これは。

そうそう、15年前ほどの付き合いという話でしたね。まあ、そのクレイジーな大学時代に、独自 Smaltalk 処理系によるプロジェクトについてのコンサルというような感じでわたしがアルバイトしていたソフトウェアハウスにきてくれていたのが尊敬する師、というわけでした。その師に誘われて断る理由もなく引きこまれていったという感じてす。
しかも、ちょうど自分が悩んでいた「郷に入れば郷に従えを守るメリットを知ったるステージ」がほとんど Smalltalk という処理系が保証していますよ。だって、 Smalltalk って鎖国してガラパゴス化してるもん。

いま、うちの会社はまだ開発環境とかも「これでなんとかなるのでやってきた」という状態なので、ガンガンと「ごくある普通の近代的な開発」になるようにバシバシやってます。上にあまり人がいないし、自分がいちばんインフラとか暗黒UNIXテクノロジーに詳しいようなので、すんなり意見が通るのがラクですね。マルバツ表みたいなの書かなくても仕事できる!!!
ちなみに、エンジニアも採用しているので興味のあるヤツらはなんか連絡するといい。

来年

よくわかんないけど、年末だし最後に来年についてとか書くといいのかなってふと思ったので「来年」って書いてみたんだけど、とりあえずいまの仕事について期待されているくらい、あるいはそれ以上の成果を求めて仕事していくっていうのと、落ち着いたらコミュニティ活動とかも積極的に顔出せるようになるかなって思います。

あれ?

主にみどり色のトグロについてのアドベントカレンダーだった気がするのだが、でできたのが紫色の楕円と赤い宝石と気球ですね。
気球といえば、わたしは中田さんとかアラン・ケイとか梅澤さんを勝手に自分の師として尊敬しているんですが、うまい具合に気球つながりで弟子入りできた気がします。いや、まだ公式に弟子にしてもらってないし、リアル気球しないと中田さんの弟子にはなれない!まだまだやることはたくさんあるな!!!

ということで、これからもヨロスク!

2015年12月6日日曜日

BlockClosure の引数の数に対してことなる引数の数を与えてよしなに呼び出す

Smalltalk Advent Calendar 2015 - Qiita の 12月5日の内容です。
Smalltalk のブロッククロージャについて書きます。
このエントリで使用している Smalltalk は Pharo Smalltalk ですが、他の処理系でもだいたい同じのはずです。

BlockClosure をみてみる

Smalltalk では [ と ] で囲まれている部分がブロッククロージャとなります。



[ ] を inspect it してみました。
BlockClosure の詳細をみたい場合はどうすればいいんでしょう。っていうときに、 Smalltalk が他の言語と大きく異なる動的な評価という特徴を生かすことができます。

BlockClosure のインスタンスに対して browse というメッセージを送ってみましょう。


BlockClosure のインスタンスを inspect している下のペインで self browse と打ち込んで do it します。

システムブラウザに BlockClosure を表示することができました。ラクチン。

BlockClosure に引数を与えてみる

Ruby のブロックのように BlockClosure も引数を受け取ることができます。
たとえば、ふたつの引数を受け取って、ふたつの引数を Transcript に出力してみましょう。

BlockClosure にふたつの引数を設けて、ふたつの引数を与えるには BlockClosure でふたつの引数を受け取ることを明示的に記述して、BlockClosure>>#value:value: を使います。

出力できました。

BlockClosure が受け取る引数の数とはことなる数の引数を与えてみる

ちょっと意地悪をしてみましょう。
ふたつの引数を受け取る BlockClosure に BlockClosure>>#value: でひとつの引数を与えるとどうなるんでしょうか?
ありゃりゃ、 Error が発生してしまいました。
Ruby ではこういった意地悪をするとふたつめの引数には nil が入って例外が起こらないという挙動をするので、わりと適当に書きたいときは便利な挙動だったりします。
% ruby -e '[1,2,3].each{|i,j| p i; p j}'
1
nil
2
nil
3
nil
うーん、厳密なのもよいけれど、柔軟に受け取る引数の数より少ない引数を与えて呼び出したときにエラーが出ないのも魅力的ですね。
BlockClosure で受け取る引数とはことなる数の引数を与えてもエラーが発生しないようにできないものでしょうか。

BlockClosure の受け取り引数をよしなに処理するためのメッセージ

cull: というメッセージを使うと BlockClosure が受け取る引数の数よりも多い引数を与えても平気な挙動になります。

cull も万能ではないです

この cull: を使えばブロックの引数の数と不一致な数の引数を与えて呼び出すことができるわけですが、欠点もあります。
それは何かというと、組み込みの状態からいじっていない BlockClosure では、よっつの引数までしか扱えないのです。
原因は単純によっつまでしかメソッド定義がないからです。まあ、よっつ以上の引数なら別の方法を使った方がよくないか?という気もしますので、自然な気がします。

多くの引数をブロックで受け取りたい場合はどうすればいいのか

value: メッセージを送信して、引数に OrderedCollection とかを与えればいいんじゃないですかね。

おわりに

今回の話のネタ、ほとんど梅澤さんにアドバイスしてもらったことをまとめただけだったりします。
すみません。すみません。すみません。

2015年12月5日土曜日

Ruby でブロックを使ったメソッドを定義してみよう

Ruby Advent Calendar 2015 - Qiita の 12月5日の内容です。

Ruby のブロックとかについて書きます。

毎年アドベントカレンダーがある言語だし、同じような内容がたぶんあると思うんですけど、全部の内容を見直してかぶってないか確認するのとかしんどいので、ブロックのネタ書きます。

普通の使い方


みなさんもよく使うのは Array#each とか Range#each あたりでの使い方ですかね。
たとえば、 1 から 10 の数字を画面に表示するコードとかは下のような内容になります。

(1..10).each do |i|
  puts i
end

このときに使ってる do と end の間にある部分がブロックと言うヤツです。

わりとコイツは便利なんですが、組み込みのクラスや用意されたメソッドなどに対してのブロックは使えるけれど、自分でブロックを与えるメソッドを定義するということに慣れていないユーザが多いような気がするので、今日はその方法について書きます。

ブロックを受け取るメソッド


結論から言ってしまえば、  block_given? というメソッドと yield という式を使えば扱うことができます。
たとえば、整数について偶数か奇数の集合ということを意識したクラスを作ってみます。
名前は EvenOrOddNumbers とします。

class EvenOrOddNumbers << Array
end

ちょっと横着して EvenOrOddNumbers は Array のひとつ、という関係があるとしました。

偶数と奇数を判別する


さて、この EvenOrOddNumbers の Numbers に 偶数がふくまれているかを調べるメソッドと奇数がふくまれているかを調べるメソッドを追加してみましょう。

class EvenOrOddNumbers << Array
  def include_even?
    each do |i|
      return true if i.even?
    end
    false
  end
  def include_odd?
    each do |i|
      return true if i.odd?
    end
    false
  end
end

こんな感じで書くことができます。
利用例は以下のような感じです。


eoon = EvenOrOddNumbers.new
eoon << 1
eoon << 3
eoon << 5
p eoon
puts "include even: #{eoon.include_even?}"
puts "include odd:  #{eoon.include_odd?}"
puts
eoon = EvenOrOddNumbers.new
eoon << 2
eoon << 4
eoon << 6
p eoon
puts "include even: #{eoon.include_even?}"
puts "include odd:  #{eoon.include_odd?}"
puts
eoon = EvenOrOddNumbers.new
eoon << 1
eoon << 2
eoon << 3
p eoon
puts "include even: #{eoon.include_even?}"
puts "include odd:  #{eoon.include_odd?}"



実行結果はこんな感じになります。

[1, 3, 5]
include even: false
include odd:  true
[2, 4, 6]
include even: true
include odd:  false
[1, 2, 3]
include even: true
include odd:  true

ここまでは普通にブロックを使うとこんなメソッドが作れて便利ですよ、みたいな感じで別にブロックを渡すメソッドは作ってないです。

偶数のみや奇数のみを扱うメソッドを作ってみる


本題ですね。偶数のみの each や奇数のみの each を定義してみましょう。

普通はひとつの定義にまとめますが、ブログ的に面倒なので先ほどのクラス定義のあとに以下のコードを記述してもメソッド定義できるので、こんな感じに書いてみました。

class EvenOrOddNumbers
  def each_even(&block)
    each do |i|
      yield i if i.even?
    end
  end
  def each_odd(&block)
    each do |i|
      yield i if i.odd?
    end
  end
end

使い方はこんな感じです。

eoon = EvenOrOddNumbers.new
eoon << 1
eoon << 1
eoon << 2
eoon << 3
eoon << 5
eoon << 8
eoon << 13
puts "EvenOrOddNumbers: #{eoon}"
evens = []
eoon.each_even do |i|
  evens << i
end
odds = []
eoon.each_odd do |i|
  odds << i
end
puts "evens: #{evens}"
puts "odds:  #{odds}"

出力はこんな感じ。

EvenOrOddNumbers: [1, 1, 2, 3, 5, 8, 13]
evens: [2, 8]
odds:  [1, 1, 3, 5, 13]

上の定義の例ではブロックが渡されなかったときの挙動を考えていないのですが、ブロックが渡されなかったときの挙動を記述するには block_given? を使います。

class EvenOrOddNumbers
  def each_even(&block)
    raise 'No block given' unless block_given?
    each do |i|
      yield i if i.even?
    end
  end
  def each_odd(&block)
    raise 'No block given' unless block_given?
    each do |i|
      yield i if i.odd?
    end
  end
end

超適当なんですが、ブロックが渡されなかったとき、いきなり Exception を発生させるという処理を入れるとこんな感じです。

each という名前がつくメソッドだとブロックがなかったときの挙動というのは、どんなものか考えるのか面倒なんで、マネしちゃだめです。

所感


ブロックの扱いについて、複数の引数を受け取るブロック、たとえば Hash#each_with_index とかはどうやって作るか?とか考えると面白いと思います。

今日の内容はこんなところで。

っていうか、最後まで書いて気づいたけど、数年前に同じネタをアドベントカレンダーに書いた気がしてきた・・・まあ、気にしない方針で。

2015年に参加する Advent Calendar

Ruby と Smalltalk と Pyspa のカレンダーに参加しています。
今日、余裕あると思って Ruby と Smalltalk のカレンダーの内容を書くことになっているんだけど、わりと余裕なかった。

これから書きます。