単項マイナスと構文解析
単項マイナスとは 単項マイナスと括弧 括弧なし単項マイナスを許容する場合のBNF calcの場合
モジュールには名前空間とミックスイン(Mix-in)の2つの機能があります。 ここではミックスインについて説明します。
モジュールの定義とクラスの定義は似ています。 クラスの定義にはclassキーワードを使いますが、モジュール定義ではその代わりにmoduleキーワードを使います。
module Abc
def abc
print "abcdefg\n"
end
end
モジュール名はAbc
です。
モジュール名は定数で、最初の文字は大文字でなければいけません。
モジュールはクラスと違い、インスタンスを作ることはできません。
もし、Abc.new
としてインスタンスを作ろうとするとエラーになります。
先程の例ではインスタンスメソッドabc
をモジュールAbc
の中で定義しました。
しかし、モジュールではインスタンスを作れないのですから、このメソッドは使いようがないように見えます。
メソッドを使うには、includeメソッドでモジュールを取り込む必要があります。
include Abc
abc
実行すると
abcdefg
と画面に現れます。 つまり、モジュールのメソッドabcを実行できたのです。
モジュールをインクルードすることにより、モジュールのメソッドを引き継ぐことができます。 通常はクラス定義の中でモジュールをインクルードしてメソッドを引き継ぎます。
class Xyz
include Abc
def xyz
abc
end
end
x = Xyz.new
x.abc
x.xyz
これを実行すると、クラスXyzでモジュールAbcがインクルードされることにより、モジュールのメソッドabcがクラスXyzのインスタンスをレシーバとして呼ぶことができるようになります。 プログラムを実行するとabcdefが2つ表示されます。
abcdef
abcdef
x
を生成abc
はXyz
のインスタンスメソッドになったから、x.abc
によってabcdefが表示されるxyz
の中でインスタンスメソッドabc
を呼び出せる。
def xyz〜endでは、selfが指すのはxyzが呼び出されたときのレシーバ(インスタンス)である。
そして、メソッド定義の中でメソッド呼び出し(abc
)があり、そのレシーバが省略されたときは、selfをレシーバとする。
プログラムリストの最後の行で、x.xyz
が呼び出されたとき、その中で呼び出されたabc
のレシーバはx
になる(selfはxになっている)なお、includeはメソッド定義の中では使えません。 クラス定義の中で、メソッド定義の外でインクルードしてください。
これまでのところをまとめておきましょう。
このことから、モジュールの目的(のひとつミックスイン)はクラスのインスタンスメソッドを提供することです。 しかしここで次のような疑問が浮かびます。 最初からクラス内でメソッドを定義すればインクルードなど必要ないのに、なぜわざわざモジュールのメソッドを取り込むのでしょうか?
モジュールは特定のクラスのためにメソッドを定義しているのではなく、複数のクラスに提供するためにメソッドを定義しているのです。 例えば、Comparableという組み込みのモジュールがあります。
<=>
メソッドをもとに、==
、>
、>=
、<
、<=
、between?
、clamp
というメソッドを定義している<=>
メソッドが定義されていなければならないComparableは比較可能なオブジェクトである整数、実数、文字列などに適用されています。
また、ユーザが比較可能なクラスを作るとき、<=>
メソッドを定義し、Comparableをインクルードするだけで、==
などの7つのメソッドが使えるようになります。
例として、江ノ電の駅のオブジェクトを作り、Comparableをインクルードしてみましょう。 駅には駅番号があり、藤沢のEN01から鎌倉のEN15までとなっています。 この駅番号の大小で駅の大小を決めることにします。
class Enoden
include Comparable
attr_reader :station_number, :name
def initialize station_number, name
@station_number = station_number
@name = name
end
def <=>(other)
self.station_number.slice(2..3).to_i <=> other.station_number.slice(2..3).to_i
end
def to_s
"#{@station_number}: #{@name}"
end
end
station_number = (1..15).map{|i| sprintf("EN%02d", i)}
name = "藤沢 石上 柳小路 鵠沼 湘南海岸公園 江ノ島 腰越 鎌倉高校前 七里ヶ浜 稲村ヶ崎 極楽寺 長谷 由比ヶ浜 和田塚 鎌倉".split(/ /)
enoshima = Enoden.new(station_number[5], name[5])
inamuragasaki = Enoden.new(station_number[9], name[9])
kamakura = Enoden.new(station_number[14], name[14])
print enoshima, "\n"
print inamuragasaki, "\n"
print enoshima < inamuragasaki, "\n"
print [kamakura, enoshima, inamuragasaki].sort.map{|a| a.to_s}, "\n"
これを実行すると次のようになります。
EN06: 江ノ島
EN10: 稲村ヶ崎
true
["EN06: 江ノ島", "EN10: 稲村ヶ崎", "EN15: 鎌倉"]
プログラム中のattr_reader
メソッドは読み出しのみサポートするインスタンス変数を定義します。
次のプログラムと同等です。
def station_number
@station_number
end
def name
@name
end
プログラムを説明します。
@station_number
と@name
を定義<=>
は駅番号文字列の3〜4文字目を(sliceは0から数えるので2..3
となっている)整数に直して比較to_s
メソッドは駅番号と駅名を文字列として返す<=>
が定義してあるので、ソートが可能。
to_sで駅番号、駅名の文字列に直して表示今回の例では江ノ電だけを対象にしましたが、一般に日本の駅には駅番号(駅ナンバリング)が用いられるようになってきました。 駅ナンバリングは3字以内の英字(路線)と番号でできています。 これから、Enodenクラスをより一般的な駅を表すStationクラスに格上げすることも可能だと思います。 駅の比較は(1)英字をアルファベットで大小をつけ(2)番号で大小をつけるという2段階で実現できます
さて、具体的にComparableモジュールがクラスにインクルードされ、その実態(オブジェクト)を手に入れるのを見てきました。 比較可能なクラスは様々あり、それらすべてにComparableモジュールが適用できます。 このように、クラス共通のメソッドを定義したモジュールを、各クラスに適用することをミックスインといいます。
Comparableは既存のモジュールですが、ユーザが独自にモジュールを作り、複数のクラスに適用することもできます。 また、Comparable以外にもEnumerableという非常に有用なモジュールがあります。 このモジュールはeachメソッドのあるクラスに適用できます。 eachメソッドを作るにはブロック付きメソッドの定義を知らなければならないので、今回は解説しませんでしたが、別の記事で取り上げられればと思っています。
単項マイナスとは 単項マイナスと括弧 括弧なし単項マイナスを許容する場合のBNF calcの場合
パーサ・ジェネレータとは 少し複雑な文法 四則(加減乗除)計算のBNF Racc で実装 クラス定義、BNFの記述部分 ヘッダー、インナー、フッター コンパイルと実行 演算子の優先順位と結合における左右の優先順位 まとめ
StrScanライブラリのドキュメント 字句解析とは StrScanライブラリ StrScanライブラリを使った字句解析 実例
lbtというgemを作って公開してみた lbtはどんなgemか ファイルの配置 lbt.gemspec Rakefile gemのビルド RubyGems.orgへのアップロード 補足・・rake/gempackagetaskサブライブラリについて
文字列のエンコーディングに頭を悩ませることはほとんどなくなりました。 なぜなら、どのアプリ、システムもUTF-8を使うようになったからです。 Rubyでもエンコーディングの問題が起こることはまず無いでしょう。 ですが、今回はエンコーディングの考え方を整理してみたいと思います。
Fiberを書いたときから、次はスレッドを書こうと思っていましたが、時間がかかってしまいました。 その理由は、期待したとおりのスレッドの効果がなかったためです。 今回はそのことを書きますが、これはRubyのスレッドの抱えている問題なのか、自分のやり方が悪いのかははっきりしていません。
Fiberは「ノンプリエンプティブな軽量スレッド」とRubyのマニュアルに記載されています。
今回はRubyプログラムから自動的にドキュメントを作成するRDocについて書きたいと思います。 私はこのことについて、エキスパートではありません。 この記事も、初心者の体験談だと考えてください。
Ruby/Gtkの記事を先日書いたときに、「これはかなり使える」という手応えを感じたので、WordBook(Railsで作った単語帳プログラム)のGTK 4版を作りました。 プログラムは「徒然なるままにRuby」のGitHubレポジトリに置いてあります。 レポジトリをダウンロードし、ディレクトリ_example/...
今回はGTK 3とGTK 4をRubyで使うライブラリについて書きたいと思います。
今回もRubyとGUIのトピックです。 Glimmerを取り上げます。
Rubyはグラフィックについて弱い印象があります。 しかし、グラフィックはデバイスに関することなので、言語そのものには直接の関係はないはずで、あるとすればライブラリです。 今後グラフィック関係のgemが開発されることに期待しましょう。
Rails7におけるシステムテストについて書きます。
前回作ったWordbook(リソースフル)のテストを書いてみます。 RailsのテストはminitestをRails用に拡張したものです。
今回はRailsの慣例に沿った形でWordbookを作り直します。
今回はWordBookの検索と削除についてです。
今回はRailsにおけるデータの作成と保存、そして変更について説明します。 そのベースになるモデルとデータベースの話から始め、appendとchangeの動作について詳しく説明します。
一般に、HTMLは文書の構造を表し、CSSはその体裁(見栄え)を表します。 Railsは最終的にCSSを含むHTML文書を出力するので、この2つについての理解が必須です。 この記事ではとくにCSSの人気ライブラリであるBootstrapを紹介します。 BootstrapはJavascriptも含んでいます。
Rubyの最も人気のあるアプリケーションであるRuby on Railsを取り上げようと思い、書き始めました。 予想してはいましたが、相当な分量になってしまいました。 そのため、何回かに分けて記事にすることにします。 また、対象となる読者のレベルをどうしようかと考えましたが、「徒然Ruby」が基礎的な内容から始ま...
Rubyのライブラリ管理システムのRubygemsとコマンドgemおよびbundlerについて説明します。
minitestについて連続して2回書いてきました。 「minitestはドキュメントが少ない」という人がいますが、私も同感です。 例えば、モックとスタブの説明も少ないです。 そこで、今回はmock.rbのソースコードを参考に、モックの私的ドキュメントを書いてみました。 あくまで私個人の考えであり、minites...
今回もminitestの話です。 mockとstubに焦点をあて説明します。
アプリ作成の記事でminitestを使いました。 今回はminitestについて、また一般にテストについて、私の考えを書こうと思います。
今回はメソッドの呼び出し制限ついて説明します。 呼び出し制限にはpublic、private、protectedの3つがあります。
今回は特異メソッド、特異クラス定義、名前空間、モジュール関数について説明します。
2023/10/29 追記:この記事は新しく書き直しました。 古い記事で使っていたGitHubのCalcが大幅にアップデートされたためです。 そこで、この記事に合うようなプログラムsimple_calcを新たに作りました。 このプログラムは本レポジトリの_example/simple_calcにあります。
if〜elsif〜・・・〜else〜endは皆さん良く使うでしょうか? これは場合分けで良く使われる方法です。 これと同様の制御構造にcase文があります。 Cのswitch文に似ていますが、より強力な機能を持っています。 if-else-endよりも高い能力があるといえます。
Procオブジェクトを生成するメソッドlambdaについて説明します。
今回はブロックを一般化したオブジェクトProcを説明します。
ブロック付きメソッドの作り方を説明します。
モジュールには名前空間とミックスイン(Mix-in)の2つの機能があります。 ここではミックスインについて説明します。
クラスの親子関係
Rubyの演算子とその再定義について書きます。
今回からクラスとインスタンスを定義、生成する方法を説明します
Kernelモジュールのメソッドはどこでも使うことができます。 そのメソッドの中には便利で有用なものが多いです。
ここでは私が便利だと思ったメソッドを紹介します。
実数
今回はシンボルとハッシュについて説明します。
文字列は最も使うオブジェクトのひとつです。 特にウェブ・アプリケーションでは、コンテンツだけでなくHTMLのタグやCSSを含めすべてが文字列です。 Rubyは文字列オブジェクトのメソッドが充実しており、またパターンマッチのための正規表現も充実しています。
配列は、どのプログラミング言語にもあると思います。 複数の要素を一括して扱うことができるのが配列です。 Rubyの配列はメソッドが充実しているので、プログラムを効率的、機能的に書くのに役立ちます。
今回の目標はインスタンスです。 インスタンスを説明するために、ローカル変数と文字列オブジェクトを事前に扱います。
今回はメソッド定義です。 メソッド定義はRubyの核心ですが、今回はトップレベルに限って説明します。 この限定によって、内容はかなり易しくなっています。
ブロックはRubyの特長です。 ブロックのおかげで記述が非常にすっきりと分かりやすくなります。 今回はブロックをイテレータの本体として使う方法を説明します。
ここではRubyの最も基本的なオブジェクトである整数について説明します。
「徒然なるままに」をネットで調べてみると、「することもなく、手持無沙汰なのにまかせてという意味」とありました。 まさに、自分の現状を言い当てた言葉。 しかも、ブログに書くネタもなかなか思いつかない日々。