MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSA Developer News[MOSADeN=モサ伝]第249号

2007-04-24

目次

  • 「りんご味Ruby」       第2回  藤本 尚邦
  • 藤本裕之のプログラミング夜話   #113
  • 高橋真人の「プログラミング指南」  第111回
  • 書籍紹介      入門UNIX for Mac OS X

りんご味Ruby   第2回  藤本 尚邦

前回の記事を読んで、RSSリーダプログラムをファイルに保存して実行したら

 

/tmp/print_mosa_rss.rb:1: syntax error
 rss.items.each { |item| puts item.title }

というエラーになった方はいらっしゃるでしょうか? すみませんでした。書き忘れていたことがあります。ポイントは

 「Rubyプログラムをファイルに保存するときは改行文字をLFにすべし!」

これだけなのですが、記事の最後に少し詳しく説明を書き加えました。前回はまった方や気になる方はぜひお読みください。

それでは本題に入りましょう。今回は、RSSリーダプログラムの最初の2行、ライブラリのロードについて説明しようと思います。

■ ライブラリのロード — requireメソッド

今回は、RSSリーダプログラム

 require 'rss/2.0'
 require 'open-uri'
 url = 'http://www.mosa.gr.jp/?feed=rss2'
 rss = open(url) { |io| RSS::Parser.parse(io.read, false) }
 puts "-- #{rss.channel.title} (#{rss.items.size} entries) --"
 puts
 rss.items.each { |item| puts item.title }


の最初の2行、添付ライブラリのロードについて説明します。

RSSリーダプログラムでは、URLで指定されたRSSデータをネットワークからGETして、そのRSSデータを解析する必要がありますが、Ruby (1.8.1以降)にはこれらの目的に便利なライブラリがすでに添付されているので、それらをロードして使うことにします。

添付ライブラリ、あるいは別途インストールしたライブラリをロードするときは、通常requireメソッドを使います。ロードしたいライブラリを表わす文字列を引数にしてrequireメソッドを呼び出すと、そのライブラリがロードされます。

 require ロードしたいライブラリを表わす文字列

このRSSリーダでは

 'rss/2.0'  -- 「RSS 2.0パーサ」ライブラリを示す文字列リテラル
 'open-uri' -- 「HTTP/FTP高レベルAPI」ライブラリを示す文字列リテラル


をrequireメソッド呼び出し時の引数として渡しています。

requireメソッドは、指定されたライブラリをロードした場合には真(true)を、すでにロードされていた場合には偽(false)を返します。また、指定されたライブラリが見つからなかった場合には、LoadErrorという例外を発生させます。

 

irb(main):001:0> require 'rss/2.0'
 true                                        # ロードした
 irb(main):002:0> require 'rss/2.0'
 false                                       # すでにロード済み
 irb(main):003:0> require 'vista'
 LoadError: No such file to load -- vista  # そんなライブラリはない!
         from (irb):3:in `require'
         from (irb):3

■ 添付ライブラリはどこに置いてあるの?

Tigerに付属しているRuby 1.8.2など、バージョン 1.8.1 以降のRubyには、以前のバージョンと比較して多くのライブラリが添付されています。

/usr/lib/ruby/1.8とそのサブディレクトリの中を見ると、`.rb’ や`.bundle’
(Macの場合)という拡張子を持ったファイルがたくさんあるのですが、これらはみなRubyに添付されてきたライブラリです。`.rb’はRubyで書かれているライブラリで、`.bundle’ はCなどの言語で記述されコンパイルされた拡張ライブラリです。

自分でインストールしたライブラリは、通常、/usr/lib/ruby/site_ruby以下のどこかに置かれます。また、rubygemsというネットワークベースのライブラリ管理システムを導入している場合(Leopardからは標準的に付いてくるかも。本連載でもいずれ取り上げたいと思います)には、rubygemsで管理されているライブラリは/usr/lib/ruby/gemsの下に置かれます。

ところで、requireメソッドはどうやってロードするライブラリのファイルを探しているのでしょうか? これを説明するためには、グローバル変数$LOAD_PATH (Rubyでは名前の前に`$’がついているものがグローバル変数になります)について言及しなくてはなりません。requireメソッドは$LOAD_PATHに格納されているディレクトリパス名を順番に検索し、各ディレクトリの中から指定されたライブラリを探します。

(グローバル変数を含め、Rubyにおける変数の意味、種類、オブジェクトとの関係については、いずれ詳しく説明するつもりです)

■ まとめ

2回目にして、requireという地味でやや面白みにかけるメソッドについて説明してしまいました、うむむ。しかし、かなり使用頻度が高く、またプログラムの最初の方で使うことが多い重要なメソッドではあるので、まあ良しとさせてください。

実は、今回の記事では、requireが構文ではなく「メソッドである」ことをさりげなく強調したつもりです。いわゆる伏線を張ったってやつです。張った伏線は忘れず活かしたいものですが果たしてどうなることやら...

さて、今回の説明の中に

 irb(main):001:0> require 'rss/2.0'
 true                                        # ロードした


というようなものがありましたが、このirbとは一体なんでしょうか?

これはRubyに付属のコマンドirbを使って、対話的にRubyプログラムを入力・実行して結果を確認している様子です。このirbコマンド、私にとっては、これがあるからRubyが便利・楽しい・やめられないと言っても過言ではない、それくらい重要なコマンドです。

次回は、このirbコマンド、および前回紹介したCocoaReplを使って、Rubyインタープリタと対話する方法について書こうと思います。

■ [補足] Rubyプログラムをファイルに保存するときは改行文字をLFにすべし!

Macでは、テキストファイルの改行文字としてCR(0x0D)が使用されることがありますが、Rubyプログラムが解析(parse)されるとき、改行として扱われるのはUNIX系OSで一般的なLF(0x0A)のみで、CRは単なる空白文字の一種として扱われてしまいます。

したがって、Rubyプログラムをファイルに保存するときには、改行文字をLF(もしくはWindowsで使われているCRLF)にする必要があります。Xcodeの場合は、形式メニューの行末コードでUNIX(LF)を選択しておくと、編集中のファイルを改行文字がLFで保存することができます。

また、Rubyプログラムでは、セミコロン`;’だけではなく、改行文字LFにも「文(式)の区切り」という意味が含まれています。C,Java,Perlなどと異なり、行末にセミコロンを置かない(置く必要がない) のがRuby流のプログラミングなのですが、改行文字をCRにしている場合、それは行末として解釈されないため、意図した文(式)の区切りが抜けてしまい、RSSリーダにおいては前述したような文法エラーとなってしまうわけです。

藤本裕之のプログラミング夜話 #113

 白状する。実はワタシ、前回のでシステムサービスについては全部書いた、もうおしまいで今回から違う話を始めるつもりでありました。ところがふと気がついてみると、「プロバイダー型」(#110で出てきた分類、覚えてますか?)についてはあれでいいが、サービスの結果としてなんらかのデータを返す「プロセッサー型」の場合のその「返し方」についてなんも説明してないではないか……と、#110を読み返して驚いた。これの記述、プロバイダー型とプロセッサー型が逆です。データを受け取りそれを元になんか処理して戻すのがプロセッサー型(単語の意味を考えりゃ当然だな)、そのデータを受け取ってアプリケーションがなんかやるだけ、戻さないのがプロバイダー型であります。おわびして訂正。

 で、そのプロバイダー……ぢゃなかったプロセッサー型の処理なんだが(どっちもプロナントカなのがいけないのだ)、実を言えば別にそんなに難しいことをしなくちゃならんわけぢゃないので、このまましらばっくれてスルーしちゃおうか、と0.68秒(アンドロイドには永遠の長さ)ほど考えた。が、その瞬間、脳裏にコイケさんが現れて「今年からMOSAは学生会員と研究室会員の会費を無料にしてもっと初心者や若い人に参加してもらう方針なんですよ」と言ったので、判ってるヒトには言わずもがなかも知れぬがそのプロセッサー型の場合にどうやって「プロセスしたデータ」をリクエスター・アプリケーショ
ンに返すかを以下に示す。

(void) processThisString:(NSPasteboard*) pboard
               userData:(NSString*) userData
                   error:(NSString**)error ;

 これは前回作った(名前だけだけど)サービスを実行するメソッドの名前だけプロセッサー型風に変えたものである。前回のは確かsearchThisStringByYahoo とかいう名前だったので pboard から文字列を引っ張り出してそれをYahooで検索する処理を書けばOKだったんだが、今度は受け取った文字列を例えば……そうだな、逆さにしてみようか。 pboard から文字列タイプのデータを引っ張り出して逆さにする(なければエラーね)。

  

  if([[pboard types] containsObject:NSStringPboardType] != YES){
         *error = @"文字列が入ってねぇぢゃねぇかこのアンポンタン";
         return;
    }
    NSString* reverseThis = [pboard stringForType:NSStringPboardType];
    NSMutableString* reversed = [NSMutableString stringWithCapacity:0];
    int  cc = [reverseThis length];
    do{
         --cc;
         [reversed appendString:[reverseThis substringWithRange:
                                                 NSMakeRange(cc, 1)]];
    }while(cc > 0) ;

 あとはこれを ペーストボードにセットして戻るだけ。

    [pboard declareTypes:
         [NSArray arrayWithObject:NSStringPboardType] owner:nil];
    [pboard setString:reversed forType:NSStringPboardType];
    return;


 もちろん error にセットする文字列はできればローカライズ可能にしておくこと。上の例はサンプルならではの手抜きであります。

 最後になったけど、このサービスメニュー、プログラムから呼び出すことも可能(まぁそれがサービスメニューに存在することが前提だけどね)。方法も簡単で、呼び出すサービスの名前と受け渡すデータをセットしたペーストボードをパラメータにして、以下のファンクションをコールするだけ。

BOOL NSPerformService(NSString* serviceItem, NSPasteboard* pboard);

 これ、NSAppとかのメソッドにあるかと思ったら Appkit にファンクションとして定義されているだけだった。アップルは「Leopard (10月に延期になってしまったねぇ)で追加される機能の多くはCocoaでしか提供しません」とかアナウンスしてるけど、その前にこういうコワザみたいなのをできるかぎりCocoaの体系の中に取り込んで欲しいもんである。
                            (2007_04_19)

高橋真人のプログラミング指南  第111回

プログラマのためのオブジェクト指向再入門(19)

〜XcodeによるPowerPlant X入門(3)〜

 こんにちは。高橋真人です。
 今回は、前回のコードの簡単な説明をします。今回のプログラムはコード自体も極めて単純ですが、これだけで一応れっきとしたCarbonアプリケーションが動くのですから、当然内部では「それなりのこと」をやっているわけです。
 短いですので再掲します。

#include <PPxApplication.h>

int main()
{
    PPx::Application app;
    app.Run();

    return 0;
}

 まず、PPxApplicationとい

うヘッダをincludeしていますが、ここでPPxのヘッダについてちょっと予備知識を。
 PPxでは、前にもお話ししたようにCarbonイベントの仕組みをかなり利用した形でフレームワークを形成しています。そのため、フレームワークを構成するクラスには大きく分けて二つの種類があるのです。
 まず、システムが標準で持っているものに関しては、”Sys”というプレフィックス(頭辞子=先頭に付く識別子)が付きます。例えばCFStringというCoreFoundationの“型”がありますが、通常のC/C++のプログラムでこれを利用する場合は、

#include <CoreFoundation/CoreFoundation.h>

と、他のCoreFoundationの“型”をひっくるめて、まとめて取り込んでしまう
方法もありますが、個別に取り込む場合には、

#include <CoreFoundation/CFString.h>

なんてやるわけです。
 で、PPxにおけるCFStringはこれをくるんだラッパクラスが用意されていて、CFStringを直接呼び出して使うよりは多少メモリ管理などがラクになっているのですが、これを利用するために取り込むヘッダファイルは、SysCFString.hという名前です。
 勘違いしそうなのですが、このSysというのはヘッダの名前の先頭に付くプレフィックスなのであって、決して名前空間の名ではないということです。CFStringのラッパクラスも、PPxにおいてはやはりPPxという名前空間に属していますので、お間違えなく。
 つまり、システムが標準で提供しているクラス(というか、型なのですが)をラッピングしたクラスはSysというプレフィックスが付き、それ以外のもの、つまりPPxが独自に提供しているクラス群についてはPPxというプレフィックスが付くということです。
 繰り返しますが、あくまでヘッダの名前の話であって、名前空間ではありません。PPxにおける名前空間は、基本的にすべてがPPxです。

 さて話は戻りますが、ヘッダの取り込みが終了すれば、あとは単にmain()だけのプログラムで、main関数の中身でやっていることは、アプリケーションクラスのオブジェクトを一つ作って、それを走らせているだけです。
 ApplicationクラスのRun()というインスタンス関数は、Carbonイベントでおなじみのメインのイベントループを走らせるための関数であるRunApplicationEventLoop()を呼び出しているだけです。
 さて、今回の冒頭で「内部ではそれなりのことをやっている」と言いましたが、Carbonを多少ご存知の方であれば、単にプログラムの中でRunApplicationEventLoop()を呼び出すだけで今回と同じアプリケーションが動作することはご存知でしょう。実は、「それなり」の中身は実質的にこの関数を呼んでいるのとほぼ同等です。
 もっとも、本当にそれだけだったら面白くも何ともありません。あえてアプリケーションのために専用のクラスを用意するのには、もちろんですが理由があります。そのためにはこれを拡張していかないと始まりませんので、早速次のステップに進みましょう。

 今度は、メニューもウインドウもあるアプリケーションに挑戦します。
 前回のものを流用して作業をしますので、まずは、FinderでPPxForXcode01フォルダを複製し、名前をPPxForXcode02とします。このフォルダを開き、

PPxForXcode01.xcodeproj
PPxForXcode01_Prefix.pch
PPxForXcode01Proj.xcconfig
PPxForXcode01Target.xcconfig


の01をすべて02に変更したいのですが、この作業をFinder上で行ってしまうと、プロジェクトがこれらのファイルを見失ってしまうので、Finderで名前を変更するのは.xcodeprojだけにします。念のため、ついでにbuildフォルダをゴミ箱に捨てておきましょう。
 次にプロジェクトファイルを開き、残りのファイルの名前を変更していきます。
 やり方ですが、プロジェクトウインドウ内でファイルを選択し、ツールバーの「情報」ボタンをクリックして、表示されたダイアログで、「一般」タブが選択された状態であれば、ファイル名の変更ができるはずです。
 ついでに、他にもいくつか「01→02」の変更作業を行います。
 まず、「ターゲットグループ」(前回参照)の左端の三角をクリックして開き、ターゲット名を変更します。(やり方は上記と同様)
 ターゲットの情報ウインドウを閉じる前に、ついでにプロパティタブに切り替え、「識別子」のところも変更します。
 あともう一つ、これは重要ですが、上記で名前を変更してあったPPxForXcode02Target.xcconfigをダブルクリックで開き、2行目の

GCC_PREFIX_HEADER = PPxForXcode01_Prefix.pch;

の01のところも02に変更しておきます。

 以上でプロジェクトの複製作業は完了です。次回はこれを元に新たに機能を組み込んでいくところをご説明します。

書籍紹介                  入門UNIX for Mac OS X

 解説担当:高橋政明

入門 Unix for Mac OS X 第4版
  Dave Taylor 著
  酒井 皇治 訳
  オライリー・ジャパン ISBN 4-87311-274-5  2,625円

 虎の表紙でTiger(Mac OS X 10.4)対応とわかるUNIXの入門書です。原著はLearning Unix for Mac OS X Tigerです。
 モサ伝読者諸氏にはUNIXの入門書など不要の方も多いことでしょう。ただ必要に迫られてターミナル.appは使うけれどUNIXにあまりなじみがなければ(あるいはコマンドライン操作にアレルギーがあれば)このような入門書を一冊手元に置くのも良いかも知れません。

 本書のまえがきにあるように、この本はMacintoshユーザーのために書かれています。(ですので開発者向けの情報には期待しないでください)
 この本が読者にとって必要かどうかは出版社のwebに目次がありますのでご自身で確認してください。

 Macintoshユーザーのために書かれて内容も現在のところ最新ですので、これからUNIXを学ぶ方にはおすすめです。コラムや注釈にMac独自の部分に対する解説もあります。

▼出版社のweb(詳しい目次と正誤表があります)
http://www.oreilly.co.jp/books/4873112745/

▼原著のweb(目次・索引・サンプル本文を確認できます)
http://www.oreilly.com/catalog/ltigerunix/index.html

◇MOSAからのお知らせと編集後記は割愛します◇

   

 MOSA Developer News   略称[MOSADeN=モサ伝]
        配信停止 mailto:mosaden-ml@mosa.gr.jp
 記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
      記事投稿受付 http://www.mosa.gr.jp/?page_id=850
Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
はそれぞれ各社の商標ならびに登録商標です。
このメールの再配信、および掲載された記事の無断転載を禁じます。
特定非営利活動法人MOSA  http://www.mosa.gr.jp/
Copyright (C)2007 MOSA. All rights reserved.