こちらruby説明が良かったですが読み辛いのでまとめてみた。
若手エンジニア/初心者のためのRuby 2.1入門:
http://www.atmarkit.co.jp/ait/kw/ruby_nyumon.html
他入門に参照になるもの:
Ruby 2.1 / Rails4.1 の意外に忘れられている便利なメソッド:
http://ruby-rails.hatenadiary.com/entry/20150101/1420049679
Ruby基礎文法最速マスター:
http://route477.net/d/?date=20100125
2.Ruby 2.1の基本構文/基本文法
定数
大文字から始まれば「定数だ」と認識される
QUEEN = 42
#or
#Queen = 12
freezeを入れることでjavaのfinal的役割をする認識は間違い。
なので
Stringなど定数はfreezeをつけるべきだが
int定数はfreezeしなくでもいい
冗長になりがち
TEAPOT = "tea".freeze
#TEAPOT = "coffee"は警告があるだけで変更ができてしまう。
#TEAPOT.capitalize!のようなことができないようにするだけだ。
ifも戻り値がある
teapot = if ARGV[0].to_i == 42
"tea"
else
"coffee"
end
puts teapot
case
最後のelseで他の場合に実行するが、javaのdefaultに似ている
case ARGV[0].to_i
when 0
puts "zero"
when 1
puts "one"
when 2, 3
puts "two or three"
else
puts "other"
end
###コメント
# コメント
=begin
こちらもコメント
=end
3.Rubyの配列、ハッシュテーブル
Array
#オブジェクト作成
array = []
array = Array.new
#追加,push,<<
array.push(1)
array << 2
array << "3"
#逆参照
array[-1]
#範囲指定
array[1..2]
# => [2,"3"]
#削除
array.delete(1) #指定した値を検索して削除
array.delete_at(0) #指定した位置の要素を削除
array.clear #全部削除
#pop,push,shift,rotate省略
#arrayを逆順にする
array.reverse #swift言語のreverse()と同じ
array.reverse! #自身も変更
#sort,sort_by,できれば高速なsort_byを使おう
array.sort_by
#「宇宙船演算子」
1 <=> 2
# -1など
#配列をランダムに
array.shuffle
#ランダムに二つの要素を取り出す
array.samle(2)
#要素を検索して位置を返す
array.index(3)
array.rindex(3) #後ろから数得る
#重複要素取り除く
array.uniq # or array.uniq!
#nilを取り除く
array.compact #or compact!
#二つの配列を結合
#push,<<はそのまま結合されてしまうが、こっちがほうがarrayのflat化できる->平滑化
array1.concat(array2)
#zip省略
#map あとで説明
上記 !が付いたメソッドを「破壊的メソッド」と呼ぶ
Hash
#初期化
hash = {}
hash = Hash.new
#hashオブジェクト作成
hash = {"jack" => 11, "queen" => 12, :king => 13}
#シンタックスシュガー」(糖衣構文、プログラミング言語において、読み書きのしやすさのために導入される構文)
#これで =>が省略できる
hash = {jack: 11, queen: 12, king: 13}
#アクセス
hash["queen"]
hash[:king]
#キー、値一覧
hash.keys
hash.values
#追加
hash[:ace] = 1
hash["child"] = 12
#削除
hash.delete["jack"]
#clear
hash.clear
#hashを配列に
hash.to_a #[[:jack, 11], [:queen, 12], [:king, 13]]
4.RubyのRangeクラスと範囲オブジェクト、範囲演算子、イテレーター
Array
puts ".."
# 5を含む、すなわち<= 5
for i in 1..5
p i
end
puts "..."
# 5を含まない、すなわち < 5
for i in 1...5
p i
end
Range
Range.new(1, 3) #=> 1..3
文字範囲
# a, b, c, d
puts "alphabets"
for alphabet in "a".."d"
puts alphabet
end
# $, %, &
puts "symbols"
for symbol in "$".."&"
puts symbol
end
# 0, 1, 2, 3
puts "numbers"
for number in "0".."3"
puts number
end
# あ, ぃ, い, ぅ, う
puts "hiragana"
for hiragana in "あ".."う"
puts hiragana
end
出力結果が面白!!!
alphabets
a
b
c
d
symbols
$
%
&
numbers
0
1
2
3
hiragana
あ
ぃ
い
ぅ
う
for string in "aa".."cc"
puts string
end
$ ruby range_04.rb
aa
ab
ac
: (中略)
az
ba
bb
bc
: (中略)
bz
ca
cb
cc
検索
(0..5).include?(5) #true
#cover省略
要素
(1...5).first #1
(1...5).first(2) # [1,2]
#lastは同じ
#他step,n個おきに処理
(0..10).step(3) {|i| puts i}
loop
#配列
["alice", "in", "wonderland"].each do |term|
puts term
end
# index付き
["alice", "in", "wonderland"].each_with_index do |term, index|
puts "#{index}: #{term}"
end
#逆
["alice", "in", "wonderland"].reverse_each do |term|
puts term
end
# Hash
{jack: 11, queen: 12, king: 13}.each do |key, value|
puts "key: #{key}, value: #{value}"
end
##5.RubyのString/Regexpクラスによる強力な文字列操作/正規表現
teapot = "tea"
#先頭文字だけ大文字に,他は小文字
teapot.capitalize #=> "Tea"
#大文字,小文字
teapot.upcase
teapot.downcase
#大文字・小文字を入れ替え
teapot.capitalize.swapcase
#=> "tEA"
#String#strip/#lstrip/#rstripで空白文字の除去
[1] pry(main)> teapot = " tea "
=> " tea "
[2] pry(main)> teapot.strip
=> "tea"
[3] pry(main)> teapot.lstrip
=> "tea "
[4] pry(main)> teapot.rstrip
=> " tea"
#each_char,一文字ずつしょる
#each_line, 一行ずつ処理
#分解して配列にする
"Alice".chars
#行ごと分解して配列にする
"Alice found\na bottle".lines
#結合
#+,効率悪い
str = "111" + "headers"
#代わりに効率の良いconcat,<<効率良い
teapot.concat("coffee")
teapot << "juice"
#insert挿入省略
#reverse逆転省略
#正規表現省略
##6.RubyのNumericとTimeで数値と時間をさまざまな操作・演算・判定
[省略]
##7. Rubyのオブジェクト指向におけるクラスとモジュール、継承、Mixin、アクセス制御の使い方
コンストラクター、インスタンス変数、キーワード引数
class Rabbit
attr_accessor :name #外からread,write可能
attr_reader :color, :length_of_ears #外からreadだけ
#コンストラクター
#name:などはキーワード引数である、デフォルト値を設定しているので、引数を省略できます。
#また引数の順番に関係ない
def initialize(name: "usachan", color: :white, length_of_ears: 10)
@name = name
@color = color
@length_of_ears = length_of_ears
end
def jump
puts "pyon! pyon!"
end
def pound_steamed_rice_into_rice_cake
puts "pettan! pettan!"
end
def say_name
puts "Hello, I'm #{@name}!"
end
def print_ears
puts "∩_∩"
end
#クラスObjectクラスを継承していますのでそのto_sをoverrideすることも可能
def to_s
"名前: #{@name}, 毛の色: #{@color}, 耳の長さ: #{@length_of_ears}"
end
end
継承,override
class LopEar < Rabbit
def print_ears #メソッドをうわ書きしている
puts "∪ ̄∪"
end
end
アクセス制御
public: どこからでもアクセス可能
protected: クラス内、同一パッケージ、サブクラスからアクセス可
private: クラス内のみアクセス可能
private破れることが簡単
A.new.send(:private_method)
Comparable moduleによるオブジェクト比較
Comparableモジュールは、ComparableモジュールをMixinするクラスに「<=>」メソッドが定義されていることを期待しています。
class Rabbit
include Comparable
def <=>(other)
@length_of_ears <=> other.length_of_ears
end
end
継承とMixin(module)の使い分け――is-a関係とhas-a関係
is-a:「ウサギやアヒルは動物である、ニンジンは野菜である」
has-a: 何らかの共通点
8.Rubyの面白さを理解するためのメソッド、ブロック、Proc、lambda、クロージャの基本
メソッドにdefault値を入れることができる
def parrot(word="yack-yack")
puts word
end
かっこが省略できる、ただ推奨しない
def parrot2 word
puts word
end
parrot2 "oink"
メソッドはreturnを書かないのが基本
def sum(x, y)
x + y
end
可変長引数は[*(アスタリスク,asterisk)」を
def sum(*args)
puts args.class
args.inject(:+)
end
p sum(1, 2, 3, 4, 5)
p sum(1)
p sum
キーワード引数
引数は順番を守らなくでもいい
def basic_form(a: "a", b: ["b", "b", "b"], c: :c)
puts "a(#{a.class}): #{a}"
puts "b(#{b.class}): #{b}"
puts "c(#{c.class}): #{c}"
end
def complex_form(a, *b, c: "c", d:)
puts "a(#{a.class}): #{a}"
puts "b(#{b.class}): #{b}"
puts "c(#{c.class}): #{c}"
puts "d(#{d.class}): #{d}"
end
basic_form(a: "meow", b: "oink", c: :bowwow)
basic_form(a: "meow")
complex_form("oink", "bowwow", d: "meow", c: "quack")
complex_form
block
{ puts "pyonpyon" }はブロック、yieldはそのブロックを実行するだけ
def repeat(n)
for i in 1..n
puts "#{i} =>"
yield
end
end
repeat(3) { puts "pyonpyon" }
def sum_and_exec_block(x, y)
z = x + y
z = yield z if block_given?
z
end
sum_and_exec_block(10, 20) do |value|
value + 10
end
結果は50
分かりにくいが便利なProcとlambda(ラムダ)
どちらもブロックを実行するだが "&" 付きでそのブロックが取得できる
手続きそのものをオブジェクト化して引き回す
def repeat2(n, &procedure)
procedure.call
end
クロージャ
例1:
do...endの間はクロージャになる
prefix = "@"
["a", "b", "c"].each do |s|
puts prefix + s
end
出力
$ ruby block06.rb
@a
@b
@c
例2:
def increase
n = 0
-> { n += 5 }
end
3.times { p increase.call } #実行のたびにProcオブジェクトが生成されている
puts "=================="
increase_proc = increase
3.times { p increase_proc.call } #生成したProcオブジェクトを変数increase_procに代入し、3回callしています。
出力
$ ruby block06.rb
5
5
5
==================
5
10
15
##9.Rubyの例外とその捕捉――基本のbegin~rescue~endからensure、else、retry、後置rescueまで
基本的StandardErrorのエラーメインである
RuntimeException発生させる
raise "something wrong"
カスタムerrorとNotImplementedError
class UnacceptableRequidError < StandardError
attr_reader :obj
def initialize(obj)
@obj = obj
end
end
class Vessel
def pour_out
requid = @requid
@requid = nil
requid
end
def pour_in(requid)
if requid.to_s == acceptance
@requid = requid
else
raise UnacceptableRequidError.new(requid), "unacceptable"
end
end
def acceptance
raise NotImplementedError.new, "#acceptance is not implemented!"
end
end
class Teapot < Vessel
def initialize(requid)
pour_in(requid)
end
def acceptance
"tea"
end
end
class Decanter < Vessel
def initialize(requid)
pour_in(requid)
end
def acceptance
"wine"
end
end
class Kettle < Vessel
def initialize(requid)
pour_in(requid)
end
end
例外catch
begin
raise "something wrong"
rescue => e
puts "An exception is occurd!"
p e
p $!
end
- 例外クラスを指定して捕捉する,javaと同じくerrorはできれば細く分割して処理する仕組みですね。
- まずカスタムrescueに引っかかりか
- どの例外クラスにも合致しない場合プログラムはその場で停止し、エラーメッセージが出力されますので最終的に処理するrescue StandardError => e (rescue => eと同じ)でcatchする
- 例外の有無にかかわらず処理する「ensure」と例外が発生しなかった場合の「else」
- ensureはjavaのfinallyに似ている。
require_relative "exception01"
begin
teapot = Teapot.new("coffee")
puts teapot.pour_out
rescue UnacceptableRequidError => e
puts "Rescued in 'UnacceptableRequiedError => e'"
p e
p e.obj
rescue NoMethodError, ZeroDivisionError => e
puts "Rescued in 'rescue NoMethodError, ZeroDivisionError => e'"
p e
# 上記catchできない場合はこっちで全部catch
rescue StandardError => e # rescue => e でもOK
puts "Rescued in 'rescue StandardError => e'"
p e
else
puts "There are no errors."
ensure
puts "Ensure"
end
###例外が発生してもリトライする「retry」
「省略」
###後置rescue
minimumに使えそう
Teapot.new("coffee") rescue nil
##10.RubyのFile/IOクラスで入力と出力、ファイルの読み取りと書き込み、フィルター作成
putsで標準出力で流したものをrabbit.txtにファイル書き込む
$ ruby -e "puts 'pyon'" > rabbit.txt
$ cat rabbit.txt
書式付き出力を行うメソッド「printf」
print "fsdaf"
puts "fsadfasff" #printより改行が後ろに付く
[4] pry(main)> printf("%.2f", 3.14159)
3.14=> nil
[5] pry(main)> printf("%#b", 42)
0b101010=> nil
[6] pry(main)> printf("%+d %d", 42, 42)
+42 42=> nil
キーボードから入力された文字列を得るメソッド「gets」
print "please input a string here > "
p gets
#p gets.chompにすると改行をなくしてくれるので嬉しい
結果
$ ruby io01.rb
please input a string here > Alice↵
"Alice\n"
テキストファイルを標準入力として使った場合のgetsの動作
[略]
###ファイル読み込む
file = File.open("wonderland.txt", "r")
file.each do |line|
puts "** #{line.chomp} **"
end
file.close
もしくはopenはブロックを引数として使えるので下記の方法もできる
この場合プログラマーは明示的に「close」メソッドを呼ぶなどの作業をしなくてもよくなります。
File.open("wonderland.txt", "r") do |file|
file.each do |line|
puts "** #{line.chomp} **"
end
end
###Fileクラスを使ってファイルに書き込む
File.open("teapot.txt", "w") do |file|
file.print("darjeeling tea\n")
file.puts("assam tea")
file.printf("%s\n", "ceylon tea")
end
###他STDOUT,STDIN
[省略]
##11.RubyのThread、Fiber、Kernel、forkで並列処理やプロセスの深淵
[省略]
##12.Rubyのメタプログラミング、self、特異クラス/メソッド、オープンクラスとモンキーパッチ
[省略]
実行時までわからないdefine_method
method_name = ARGV[0]
define_method method_name do
puts "This method is named #{method_name}."
end
alice
###オブジェクト固有のメソッド「特異メソッド」
array = []
def array.append_randomized_number
self << rand(10)
end
p array.respond_to?(:append_randomized_number)
p Array.new.respond_to?(:append_randomized_number)
10.times { array.append_rondomized_number }
p array
$ ruby meta_programming_05.rb
true
false
[1, 6, 7, 6, 4, 9, 7, 7, 1, 3]
###クラスメソッドと「特異クラス」
class Rabbit; end
def Rabbit.colors
[:black, :brown, :white, :mixed]
end
p Rabbit.colors
上記、実際はよく使う下記と同じことをやっています
下記のやり方が良いと思います。
class Rabbit
def self.colors
[:black, :brown, :white, :mixed]
end
end
p Rabbit.colors
また、同じく下記のような下記書き方もできるますよね
class Rabbit
class << self
def colors
[:black, :brown, :white, :mixed]
end
end
end
オープンクラスとモンキーパッチ
- *を再定義しているが何が特別なのか?
class Fixnum
def +(v)
self - v
end
def *(v)
self / v
end
end
puts 42 + 42
puts 42 * 42
$ ruby pattern_01.rb
0
1
###ruby で動的にクラスを作る
self.class.const_set :'Creature', Class.new
=> Creature
Creature
=> Creature
以下と同じ
class Creature
end
もう1つの例:Hashをloopして動的にクラスを作成するとともにdefine_methodでmethodを追加する
{Cat: "meow", Dog: "woof", Owl: "hoot-hoot", Rabbit: "boo"}.each do |animal, roar|
Object.const_set animal, Class.new
Object.const_get(animal).class_eval do
define_method :speak do |count|
count.times { puts roar }
end
end
end
Cat.new.speak(2)
Dog.new.speak(2)
Owl.new.speak(2)
Rabbit.new.speak(2)
###他メタプログラミング
「send」メソッド
「eval」メソッド
「instance_eval」メソッド
「method_missing」メソッド
「alias_method」メソッド
遅延評価のための「Proc」オブジェクト
##13.Rubyで逆ポーランド変換機を作りgem作成&コマンドの使い方
省略