或るプログラマの開発日記

日々の勉強したことの備忘録なんかに使っていきます

2017年5月の目標

どうも、パイソンです。

 

本日から5月。先月に引き続き月間の目標でも立ててみようかなーと思います。

 

とはいえ、先月は毎日更新を目指すとか息巻いてみたものの結局挫折したんで、今月は普通に達成出来る感じのものにしようかと。(^^;

 

というわけで、立ててみた5月の目標。

 

1.rubyでなんか作る

先月来からrubyの勉強を進めているが、やはりcuiのプログラムだけ作ってても退屈なもんです。

 

なので、今月はrubyを使って少し規模の大きなソフトを書いてみようかと思います。何作るかは検討中ですが、早い内に決めて、ブログに作成過程なんかを残して行こうかと思います。

 

2.記事更新は10記事程度を目処に

1カ月ブログやってきて、さすがに毎日更新はしんどいと実感したので、今月は少し控えめな目標にしてみましたw

 

とはいえ、数値目標を立てて置かないと更新しないまま放置になるので、一応少なすぎるという事は無い程度の規模感で。

 

 

というわけで、5月はマイペースで更新していきます。

 

ブログ開始から1カ月経過しました

どうも、パイソンです。

 

ブログ開始からちょうど1カ月経過しましたので、これまでの振り返りをしてみようと思います。

 

月初の目標

一応、今月の初めに2点ほど目標を立てておりました。

1.毎日更新を目指す事

2.rubyの勉強を頑張る事。

 

んで、1の目標ですが、結局毎日更新はできませんでした。(´・ω・`)

 

理由としては、飲み会があって帰りが遅くなった日があったり、そもそもネタが全然浮かばなかったりというのがありますが、まあ、これらのことは言訳にしかなりません。(^^;

 

つか、毎日更新とかキツイわ。本当、毎日更新してるブロガーのひとは凄いと思います。

 

次に、2の目標。

 

rubyのほうは、ブログ続けてきた効果か、大分理解が深まったかなーと個人的には思います。やはり、わからない事を調べつつ、その内容をブログにアウトプットしていくことで、学んだ事が頭に定着しているという実感はあります。

 

とはいえ、まだまだ基本的な部分しか理解出来てないという自覚があるので、来月以降も継続して勉強は続けていこうかと思います。

 

まとめ

というわけで、

1.毎日更新は無理ゲーだった

2.今後も勉強した事はブログに残して行こう

 

以上が今月の感想です。

5月もブログは継続していきます。

 

 

Rubyにはインクリメント演算子(++)が無い

Rubyを書いてて、いつも疑問に思ってた事項なので自分用にメモ。

CやJava、またはPerl等のプログラム言語では、整数の値に1を加算する時にインクリメント演算子++を使用します。しかし、Rubyではインクリメント演算子を使うことは出来ません。

インクリメント演算子が無い理由

Rubyの開発者であるMatzさんが、過去この件について言及されておりました。

3) 記号的な記法

これは単なる私の趣味ですが, 単項インクリメントとかがたまに欲しく
なります. i += 1 でいいわけですが. i++ と書いて怒られる (^^;


すんません.この件は以前から指摘されているのですが(演算子はC
に似ているのに++と--は対応する演算子が無い),++の動作が本質
的に「変数を操作する」ものであるため,変数がオブジェクトでな
Rubyでは導入できないでいます.++や--の「オブジェクト指向
意味」がRubyの他の部分と整合性を保ったまま定義できれば採用し
たいのですが….

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/5323

以下、自分なりの解釈。

Rubyでは整数値はオブジェクトであるためインクリメント演算子を実現しようとすれば変数が参照しているオブジェクトそのものに作用する必要がありますが、++演算子が変数に対して作用するものであるため実現が困難であるということですかねぇ。

また、RubyのFixnumクラスはimmutableですので、さらに実現は困難ですね。

Ruby の Fixnum クラスは immutable です。 つまり、オブジェクト自体を破壊的に変更することはできません。 Bignum も同様です。

https://docs.ruby-lang.org/ja/latest/class/Fixnum.html

インクリメントメソッド

尚、Fixnumクラスにはnextsuccという値に+1するメソッドはあります。しかし、前述の通りFixnum自体がimmutableである為、

num=10
num.next

としてもnumの値は変化しません。

結論

Rubyでは、整数をインクリメントする場合はおとなしく+=1を使いましょう。

Rubyで乱数生成

Rubyの乱数生成メモです。

rand関数

Rubyで乱数生成をするにはrandメソッドを使います。

10.times do
  puts rand(1000)
end

このプログラムは、0~999までの範囲の乱数を10回出力します。

ただ、この乱数は擬似乱数と呼ばれるものであり、乱数生成に使われる種(シード)を元に算出されている数になりますので、純粋にランダムな数が生成されているわけではないということに注意が必要です。

擬似乱数の偏りについて説明しだすと長くなりすぎるので詳細はWikipediaのほうを参照。

擬似乱数 - Wikipedia


因みに、srandメソッドを使うことで乱数の種を明示的に与える事が可能です。

srand(3)
10.times do
  puts rand(1000)
end

実行結果

874
664
249
643
952
968
256
789
659
714

種を指定した方のプログラムは何回実行しても同じ結果を返します。

SecureRandomクラス

所謂、安全な乱数を生成したい場合はSecureRandomクラスを使います。

require 'securerandom'
p SecureRandom.random_number(10000)
p SecureRandom.hex(16)
p SecureRandom.base64

乱数以外にも、ランダムな文字列、base64文字列の生成に使えます。

ただし、実行速度は擬似乱数のほうと比べると結構遅いです。

Rubyで書式付き出力を行う

Rubyの書式付き出力に関するメモ。

Rubyの書式付き出力

C言語なんかでもみるsprintfメソッドを使うやり方と、%演算子を使うやり方があります。先ずは%演算子を使う例を見てみます。

プログラム

(1..10).each do |n|
  puts "%03d" % n
end

実行結果

001
002
003
004
005
006
007
008
009
010

このプログラムの"%03d" % nは、sprintf("%03d", n)と同じ意味になります。

個人的には、%の演算というと、どうも剰余を求めている様な感じがするので違和感ありまくりでしたが、演算子が文字列にかかっているか、数値にかかっているかの違いと理解すれば良いのでしょうか。

因みに、複数の書式を一度に扱う例は以下の通り。

puts "100 to bin ->%b  ,oct->%o  ,hex->%X" % [100,100,100]
#=>100 to bin ->1100100  ,oct->144  ,hex->64

puts sprintf("100 to bin ->%b  ,oct->%o  ,hex->%X", 100,100,100)
#=>100 to bin ->1100100  ,oct->144  ,hex->64

雑感

CやJavaに慣れてるとRubyのプログラムは%:とか@が普段見慣れない使われ方をするので混乱しがちです。ま、丁寧に個々の意味を読み解いていくしかないのでしょうな。

Rubyのsortメモ

Rubyのsortに関するメモです。

sortメソッド

配列をソートするには、sort(もしくはsort!)メソッドを使います。後ろにブロック処理を記述することで、比較方法を定義する事が出来ます。ここでは昇順でソートする方法と降順でソートする方法を記載します。

p [5,3,7,4,9,0,1,8,2,6].sort
#=>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

p [5,3,7,4,9,0,1,8,2,6].sort{|a, b| a <=> b }
#=>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  
p [5,3,7,4,9,0,1,8,2,6].sort.reverse
#=>[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

p [5,3,7,4,9,0,1,8,2,6].sort{|a, b| b <=> a }
#=>[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

因みに、ブロックの中で出てきた<=>は比較演算子と呼ばれるもので、左右の項の大小関係により、0,1,-1が返却されます。

p 1 <=> 1 #=> 0
p 1 <=> 0 #=> 1
p 0 <=> 1 #=> -1
p 2 <=> 0 #=> 1
p 0 <=> 2 #=> -1

sort_byメソッド

ブロック処理の戻り値を元にソートすることを前提としたのがsort_byメソッドです。以下の例のように、アルファベット順でなく、文字数でソートしたい時などに使えます。

langs = ["Java", "C", "Python", "C++", "Ruby", "Basic"]
p langs.sort_by{|s| s }
#=>["Basic", "C", "C++", "Java", "Python", "Ruby"]

p langs.sort_by{|s| s.size }
#=>["C", "C++", "Java", "Ruby", "Basic", "Python"]

Rubyでhashから値を取る方法のメモ

Rubyでhashを使ってて、Javaとかとは勝手が違っていたところで結構ハマッたので、調べた情報をメモ。

keyが文字列かシンボルか?

Rubyのhashはkeyとして文字列はもちろん、シンボルをkeyとして使うことも出来ます。例として、文字列、シンボルそれぞれをkeyとしたhashから値を取得するプログラムを書いてみます。

strhash={"key1" => "value1", "key2" => "value2", "key3" => "value3"}
symbolhash={key1: "value1", key2: "value2", key3: "value3"}
p strhash["key1"] # => "value1"
p strhash[:key1]  # => nil
  
p symbolhash["key1"]# => nil
p symbolhash[:key1] # => "value1"

もちろん、文字列とシンボルは中身が全然異なるので、それを混同するとおかしなことになります。keyが何の型かを認識しておかなければなりません。

fetchメソッドの仕様

先の例では[]を使って値を取得していましたが、fetchメソッドを使って値を取得することも出来ます。[]を使うのと、fetchを使うのとでは、hashから値が取れなかった時の扱いに大きな違いがあります。

単純なfetchメソッド

keyのみを引数とするfetchメソッドは、値が取れなかったときに例外が発生します。

symbolhash={key1: "value1", key2: "value2", key3: "value3"}
p symbolhash.fetch(:key1) # => "value1"
p symbolhash.fetch(:key4) # => `fetch': key not found: :key4 (KeyError)

値が絶対に取得できる前提で使うにはいいのかもしれませんね。

デフォルト値付きfetch()

第2引数にデフォルト値を渡すと、値が取れなかったときにデフォルト値が返却されます。

symbolhash={key1: "value1", key2: "value2", key3: "value3"}
p symbolhash.fetch(:key1, "not found") # => "value1"
p symbolhash.fetch(:key4, "not found") # => "not found"

[]で取るのと、fetch(key, nil)とは同じということですね。

ブロック付きfetch()

ブロックを渡すと、値が取れなかったときにブロックの値を評価した値が返却されます。

symbolhash={key1: "value1", key2: "value2", key3: "value3"}
p symbolhash.fetch(:key1){|key| key.to_s + " not found"} # => "value1"
p symbolhash.fetch(:key4){|key| key.to_s + " not found"} # => "key4 not found"

うーん。。正直使いどころが良く分からんが、まーこういう使い方も出来るということですね。

参考URL

stackoverflow.com