9月 29

Rubyのinstance_evalメソッドについて分かってきたような気もするが疑問も増えた

 Rubyのinstance_evalがブロック内のテキストを評価してレシーバーであるインスタンスの元で実行するメソッドであるということは、irbを叩いてなんとく理解できつつあるような気がします。しかし、逆に「何故そうなるのか?Why?」という疑問も増えてきました。

 

メソッド

 以下のように定義したメソッド”aaa”はStringクラスのインスタンス”str”の特異メソッドになるようです。

str = "hoge"

str.instance_eval{def aaa; puts "a";end}
str.aaa
⇒"a"

 しかし、このインスタンスメソッド”aaa”で返された”a”は文字列であるはずなので、Stringクラスかと思いきや、NilClassらしくて、この理由がよくわからないんですよね。 

str.class
⇒String

str.aaa.class
⇒NilClass</del>

 
  ちなみにFixnumクラスを返すはずのインスタンスメソッド”bbb”でも同じ結果です。 

str.instance_eval{def bbb;puts 1;end}
str.bbb
⇒1

str.bbb.class
⇒NilClass</del>

追記
「putsの戻り値がnilだからでは」というコメントをいただきました。試してみると確かにその通りでした。失礼しました。

str = "hoge"

str.instance_eval{def aaa;"a";end}
str.instance_eval{def bbb;1;end}
str.aaa.class
⇒String
str.bbb.class
⇒Fixnum

 

定数

  インスタンスの中で定数を定義してみます。正直、インスタンスの中で定数を定義することの意味がまだよくわかりませんが、一応可能なようです。これは特異定数というか、インスタンス定数という感じになるのでしょうか・・・?
 

str.instance_eval{AAA = "ccc"}

 

この定数”AAA”はどこで定義されてだろうか?
どうやって参照するのだろうか?
 疑問が次から次へと出てきて止まりません。 

クラス – class_evalとの違い –

 さらにこのインスタンス”str”の中でクラスを作ってみたいと思います。
 

str.instance_eval{class BBB;end}

BBBクラスのインスタンスはつくることができます。

b = BBB.new
b.class
⇒BBB

Objectクラスのすぐ下にクラスが作られるんですね。Stringクラスのインスタンス”str”の中で作られるので、Stringクラスのサブクラスとして生成されるかと思っていました。

BBB.ancestors
⇒[BBB,Object,Kernel]

 

 もう少し深く考えるとこの辺の挙動が理解できそうなのですが、今のところ???状態です。

 ちなみにクラスはClassクラスのインスタンスでもあるので、instance_evalを用いるとこんな感じになります。

CCC = Class.new
#これでCCCクラスの生成。
CCC.class ⇒Class
#CCCはClassクラスのインスタンス

 Classクラスのインスタンス、”CCC”にメソッドと定数を定義しています。

CCC.instance_eval{def ccc;puts "123456";end}
CCC.ccc
⇒"123456"

CCC.instance_eval{EEE = "789101112"}
CCC::EEE
⇒"789101112"

 

 それぞれクラスメソッドとクラス定数として定義されているようです。クラスメソッドに定義されるのはClassクラスのインスタンス”CCC”の特異メソッド(=クラスCCCのクラスメソッド)として定義されているからです。Classクラスのインスタンスをレシーバーにする限り、instance_evalとclass_evalと違いは無いような気がする。どうなのだろう?  
 
 

9月 29

Kindle 4が出た(Fire君には興味ないよ)

 出ましたね、新しいKindle。

 でも、話題のFireはiPadを持っているのであまり食指が動きません。どちらかというとAmazonタブレットばかりが話題になって、次のが出るのか心配していたE Ink端末のKindle4が出たほうがむしろ嬉しい。ローエンドのKindleは広告スクリーンセーバー付きとはいえ、79ドル!! この価格はもはや衝動買いの領域です。United Statesにいたら赤子でも衝動買いしてしまうで。

Kindle

 もっとも残念ながら日本では広告付き端末は購入できないので、日本で買おうとすると109ドルになってしまうようです。まあ、日本で広告つきを販売してもあまり意味がないですからね。

Kindle, Wi-Fi, 6″ E Ink Display – for international shipment

 実はKindle3が名を変えて、Kindle Keybordとして販売が継続されるそうです。こちらは広告付き99ドルですが、おそらく日本からは広告付きは購入できないので139ドルでしょう。


Kindle Keyboard, Wi-Fi, 6″ E Ink Display

 まあ、私、すでに・・・

Kindle 2持ってますのでKindle 4も特に興味ないんですが!


 
 

 ところで、今もなお販売され続けているのに、AmazonのKindle一覧では紹介されず、検索してようやく顔を出す状態になっているKindle DX君がややかわいそうです。買って上げてください。


Kindle DX, Free 3G, 3G Works Globally, Graphite, 9.7″ Display with New E Ink Pearl Technology
 

 

9月 28

「書籍」と呼ぶには短い電子書籍というコンテンツと従来よりちょっと長くなったWebというコンテンツの相対的な関係

 10月にリリースされるというAppleのiOS5のアップデート、噂されるiBooksのEPUB3対応は当然すごく期待するところですが、それに加えてSafariのリーダー機能、結構面白いのではないかと思います。

さらに快適なネットサーフィンを。
iOS 5は、iPhone、iPad、iPod touchでのネットサーフィンにさらなる新機能を加えます。例えば、Safariのリーダー。広告や不要なものが表示されないので、ウェブの記事だけに集中できます。リーディングリストは、あとでじっくり読むために記事を保存できる機能で、iCloudにはすべてのデバイスから集めた最新のリーディングリストが保存されます。iPadではタブを使うこともできるようになったので、複数のウェブページを開いて、思いのままに切り替えていけます。さらにiOS 5では、どのiOSデバイスでもSafariのパフォーマンスが向上しました。

 リーダーという機能はPC版のSafariですでに実装された機能ですし、iPad上でもすでにInstapaperが同じような機能を実現していますが、PCよりも「読む」という行為に適したインターフェイスであるタブレット端末の標準のブラウザで実装されることに意味があるのかと思うのです。

 Webコンテンツは、これまでこんな感じでこれまで垂直に立てられたモニター上で読むことを前提に作られてきたわけです。

 目とコンテンツの距離姿勢(特に首の角度)に注目してほしいのですが、この上のようなインターフェイスは「読む」というよりも「作業をする」、もしくは「見る」という行為に適したインターフェイスではないかと。このインターフェイスはWebというコンテンツの有り様を大きく規定してきたのではないでしょうか。

 タブレットPCはこんな感じでコンテンツと目の距離といい、読むときの首の角度といい、書籍にインターフェイスが近いですから、Webというコンテンツの有り様を規定する前提が崩れてしまうかもしれません。

 タブレットPCで標準で搭載されているブラウザに「リーダー」のような「読む」ことに集中できる機能を実装されるようになると

 

Webが、より「読む」コンテンツに

 

 となるかもしれません。つまり、少々長くなっても読むことが苦にならなくなるので、コンテンツが少し長くなるかもということです。 

 一方で・・ということで今度は電子書籍という器に話を移します。同じ端末で電子書籍を読むためのiBooksを利用できるわけですが、同じインターフェイス上で「読む」コンテンツである以上、Webと「書籍」はどういう関係になっていくのでしょうか。

 電子書籍という器はWebよりも長く、本より短いサイズのコンテンツに強みを発揮するような気がします。電子書籍のメリットとして上限がないことはよくいわれることです。量が増えても物理的サイズがふえるわけではないので、そういった制約はほとんどないと。

 しかし、逆に量の少ないコンテンツはどうでしょうか。紙の本でも数ページから数十ページという量の少ない冊子を作ることは可能です。無料冊子では普通にありますね。しかし、商業ベースにのせようと思った場合、流通コストを考えるとある程度のまとまったサイズにならないとコスト的に採算がとれないという制約があります。1つのコンテンツで流通コストを賄えない場合、複数のコンテンツをバンドルして単価を上げる必要が出てくる。このあたりは出版界にいる人間ではないので想像するだけになりますが。

 電子書籍は流通コストを低く抑えることができる(という前提でとりあえず今回は書く)。だから、単価を低く設定することができる。そして、だから、紙の書籍よりも遙かに少ないサイズでコンテンツを販売することができる。つまり、マイクロ化したコンテンツでも売れるということです。。

 ※が、実際はどうなんでしょう?もしかすると物理メディアと比較するのそもそもの間違いで、電子媒体はコストのかかり方、傾斜が全く違うもののような気がします。一線超えるとコストがゼロに等しくなるとか。

 誤解されそうなので、一応、書きますが、「紙の本よりも電子書籍は物流コスト等がかからないから紙と全く内容のコンテンツでも電子書籍のほうが安くできる」ということをここで言いたいわけではないのです。従来の紙の本という器では経済的に載せることができなかったコンテンツを商業ベースで販売できるかもしれないということです。

 課金コストをゼロにできるわけではないので、ほとんど情報が無料で公開されているWebよりコンテンツを細分化することはおそらくできないだろうと。それでも、紙の本より単価を遙かに安く設定することができる。だから、コンテンツも小さくすることができる。

 すでに100ページ前後の電子書籍が1000円を切る価格で販売されていますが、50ページ、30ページ程度の雑誌記事サイズのコンテンツが100〜300円程度の価格で販売される日は遠からずくるだろうなと思います。課金コストがさらに下がればさらにコンテンツのマイクロ化が進むかもしれません。

 そうなると「書籍」と呼ぶには短いコンテンツである電子書籍と少し長くなったWeb。それを同じ端末で読むことになったら、その違いは有料か無料かの違いになってしまうのでしょうか。どちらにしても、これまでのように「紙の本 VS Web」という対立を前提とした比較はあまり意味がなくなり、相対的な関係になっていくのではないかと私は考えています。
 

 ・・・・・と書いた次第ですが、実際のところどうなんでしょうか。やはりキーは課金コストでしょうか。販売する側の金銭的なコストだけではなく、販売する側とそして、買う側の手間的なコストも考えなくてはならないかも。  
 

9月 25

Rubyがインストールされていない環境下でRubyのirbをなんとか使う方法

 Rubyのマニュアルを読んでいると、サンプルとして掲載されているプログラムを実行して挙動を確認したいということがままあり、そういう時にirbは非常に重宝しています。しかし、移動している時などいつも手元にRubyがインストールされている環境があるわけではありません。そんなときでもirbを使う方法をまとめてみました。
 

Web

 Webベースのirbです。ネットに接続された環境下ならブラウザ上でirbを使用することができます。

try ruby! (in your browser)
http://tryruby.org/

 

For iOS

 私はiPhoneユーザーですので、一番よく利用しているのが以下のアプリです。移動中にRubyのマニュアルを読みながらメソッドの挙動などを確かめるのに非常に重宝しています。これもネット経由でリモートにirbを利用するサービスです。

irb for iPhone
http://itunes.apple.com/jp/app/irb/id409540962?mt=8
irb for iPhone
 

 Googleで「irb for iPhone」で検索するとiOSでirbを使えるようにしようという試みはいくつもされているみたいです。ここういうのがどんどん生まれてくるといいですね。できれば、ローカルで実行できるものが欲しい。 

 

For Android

 これはもしかするとAndroidにJRubyをインストールするものなのでしょうか。ならば正確には「Rubyがインストールされていない環境下」とはいえませんが、趣旨としては同じなので紹介してみます。とはいえ、私はAndroidユーザーではないので使用したことがありませんが、対話的に実行するirbが使えるだけではなく、Editorも用意されているようですので、コピペなどを駆使すればローカルで書いたスクリプトを実行もできるんではないでしょうか。正直、これは非常にうらやましい。

Ruboto IRB : 過去最大の衝撃。これは凄い!!AndroidでRubyが動く!!Androidアプリ427

Ruboto (JRuby on Android)
http://ruboto.org/

 

9月 25

Ruby(1.8.7〜1.9.0)の配列の末尾には見えない要素があるらしい。

 少し細かい話を・・・・。

 『プログラミング言語Ruby』の「9.5.2.3 配列要素の書き換え」(p353)にsliceメソッドの解説に以下のようなサンプルコードが掲載されています。

# slice!で要素、部分配列を削除
a = [1,2,3,4,5,6,7,8]
a.slice!(0)
# => 1: 添字 0 の要素を削除: a は[2,3,4,5,6,7,8]
a.slice!(-1,1)
# => [8]: 末尾の部分配列を削除: aは[2,3,4,5,6,7]
a.slice!(2..3)
# => [4,5]: 範囲を受け付ける: aは[2,3,6,7]
a.slice!(4,2)
# => []: 末尾の位置にある空配列: a は変更されず
a.slice!(5,2)
# => nil: a は [2,3,6,7,nil]に

1行目から8行目まではよくわかるのですが、9行目と11行目がよく理解できませんでした。同じ配列の範囲外を指定しているのに、なぜ9行目が空の配列を返し、11行目がnilを返してくるのかと。

 当然ですが、クラスも異なります。

a.slice!(4,2).class
#⇒ Array
a.slice!(5,2).class
#⇒ Nilclass

 

 う~ん、よくわからん。配列の末尾には

[2,3,5,6,(nil)]

 

という感じで見えないnilの値でも入っているのだろうかと、眠れない夜が続いていた(嘘)のですが、Rubyに詳しい方にこの件についてお尋ねする機会があったので伺ってみると、配列には見えない形で末尾に配列の末端であることを示すデータが入っているらしいのだそうです。C言語で書かれているのでその実装上の問題とか・・。C言語はよくわかりませんが、そうなんですか・・・。

つまり、

a ⇒[2,3,5,6,(配列の末尾であることを示す見えない要素)]

であるので、

a.slice!(4,2)
# => []

 

 と、空の配列を返すのだそうです。なるほど!そして、以下の場合

slice!(5,2)

 

 以下の■の部分のような配列の外を第一引数が指してしまうので、nilが返ってくるということになるらしい。なるほどぉぉお。

a ⇒[2,3,5,6,(配列の末尾であることを示す見えないデータ)] ■←ココ!

 

ちなみに

 『プログラミング言語Ruby』では以下のようにa配列の5番目の要素に”nil”が追加されますが、

a.slice!(5,2)
# => nil: a は [2,3,6,7,nil]に

 

 私のMacでは以下のようになります。a配列に5番目の要素に”nil”が追加されたりはしません。ちなみに私はRuby 1.8.7を使用しています。『プログラミング言語Ruby』は1.9.0までフォローしています。

a.slice!(5,2)
# => nil: a は [2,3,6,7]に

 

 この辺はRubyの実装環境の違いなんでしょうか・・・。

 ちなみにWebベースのirbであるtry ruby!で試したRuby 1.9.2だとArgumentErrorを返すようです。バグとして修正されたのでしょうか。

a = [2,3,6,7]
=> [2,3,6,7]
>> a.slice[4,2]
ArgumentError: wrong number of arguments (0 for 1..2)
>> a.slice[5,2]
ArgumentError: wrong number of arguments (0 for 1..2)

 

9月 24

W3CのTracking Protection Working GroupとWeb Payments Group

W3Cでは最近、おもしろそうなWorking Groupいろいろと立ち上がっているようだが、先日、立ち上がった「Tracking Protection Working Group」と「Web Payments Community Group」は特に興味深い。とくに後者のCGで検討されるらしいWeb上での少額課金は、標準化が進めば特定のプラットフォームに課金を依存する必要がなくなる。どちらもおもしろそうなのでMLには加入して議論を追ってみることにした。

ところですいません、Working GroupとCommunity Groupの違いはよくわかっておりません・・・。

■W3C Tracking Protection Working Group

W3C Tracking Protection Working Group
http://www.w3.org/2011/tracking-protection/

W3C Tracking Protection Working Group public-tracking@w3.org Mail Archives
http://lists.w3.org/Archives/Public/public-tracking/

W3C Launches Work on “Do Not Track” Standards for the Web–W3C

■Web Payments Community Group

Web Payments Community Group
http://www.w3.org/community/webpayments/

Web Payments Group Launched at W3C! | Web Payments Community Group

 twiter上だと”#payswarm“というハッシュタグで関係者がやり取りをしているらしい。

以下のPaySwarmというものをベースに議論を進めていくらしい。私は「PaySwarm?、なにそれ?初めて知った」という段階で何も分かっていないのだがこういうものもあるんですね。Web上の課金について関心をもっていながら全く知らなかった。勉強不足だ。

PaySwarm @ Digital Bazaar
http://payswarm.com/

9月 24

RubyのClassクラスのインスタンスの定数はどこで定義されているのか

  RubyのクラスはClassクラスのインスタンスらしい。なるほど。

つまり、以下のようにABCクラスを作るとClassクラスのインスタンスが生成されるらしい。

Class ABC

end

ABC.class
=> Class

 そして、クラス名は定数なのだそうだ。上の場合だと”ABC”は定数でもあるらしい(だから、クラス名の最初は大文字)。Classクラスのインスタンスを定数ABCに代入しているということらしい。

上でクラスの作成は以下のように書くこともできる。

ABC = Class.new{ }

 より定数に代入しているっぽいですね。

 ならば、このクラス名の定数”ABC”はどこのクラスで定義されているのだろうかと。

 ちょっと調べたら簡単にわかりました。以下のようにObjectクラスの定数としてクラス名は定義されているようです。

p Object.constants.grep /ABC/
⇒ ["ABC"]

Rubyのその他の組み込みクラスのクラス名もObjectクラスに定数として定義されています。さきほど私が定義したクラス名ABCも含めて。

p Object.constants
=> ["ThreadError", "RUBY_PLATFORM", "Regexp", "Deprecate", "Numeric", "String",
"SLex", "Bignum", "IndexError", "SecurityError", "UnboundMethod", "Exception",
"Readline", "RubyLex", "NoMethodError", "FALSE", "Object", "RELEASE_DATE", "IRB",
"Range", "IO", "Integer", "Config", "TypeError", "RubyToken", "Dir", "RUBY_VERSION",
 "ZeroDivisionError", "Gem", "SystemExit", "NotImplementedError", "Hash", "RegexpError",
"Kernel", "TOPLEVEL_BINDING", "RUBY_COPYRIGHT", "GC", "TRUE", "STDOUT", "LocalJumpError",
"Binding", "Interrupt", "RUBY_FRAMEWORK", "ObjectSpace", "SyntaxError", "Marshal",
"Enumerable", "Struct", "Class", "Continuation", "IOError", "MAXHISTSIZE", "RangeError",
"Kconv", "Data", "Thread", "RUBY_PATCHLEVEL", "SystemStackError", "Array", "NoMemoryError",
 "FileTest", "MatchData", "ARGF", "ETC_IRBRC_LOADED", "NIL", "Comparable", "PLATFORM",
 "ArgumentError", "Float", "FloatDomainError", "RUBY_RELEASE_DATE", "RuntimeError",
"Precision", "ThreadGroup", "Signal", "Fixnum", "STDERR", "FalseClass", "VERSION",
 "Exception2MessageMapper", "RbConfig", "Errno", "StandardError", "Math", "EOFError",
 "LoadError", "NKF", "RUBY_FRAMEWORK_VERSION", "APPLE_GEM_HOME", "STDIN", "TrueClass",
 "NameError", "NilClass", "Process", "Proc", "RUBY_DESCRIPTION", "ARGV", "ABC",
"SystemCallError", "SignalException", "MatchingData", "File", "Time", "ENV",
 "ScriptError", "Symbol", "Module", "Method", "StopIteration",
"DTracer", "CROSS_COMPILING", "HISTFILE"]

 なるほど。なるほど。なるほど。