コンパクトなRubyのREPLを作ったよ!
コンパクト。悪く言ったら低機能。
irbやpryとシェルの相性が悪かったので。
github.com (作ったよ!って言う割には別リポジトリに数か月前からあるのは内緒のお話)
対応してるもの
- ローカル変数
- マルチバイト文字
対応していないもの
- 定義途中の改行(Enter押下)
- ドキュメント等の読み込み
- ステップ実行とか
- などなど
23行のコンパクトなREPLです!
あ、最後に。
requireし直したい時は一回REPLを閉じてから開きます。
コマンドの引数にrequireするパスを指定できるのでうまく使ってくださいな。
Rubyのヒアドキュメントの配列の書き方
普通のヒアドキュメント
<<-EOS なんかいろいろ EOS
メソッドがついたヒアドキュメント
<<-EOS.length なんかいろいろ EOS
・・・配列のコンマはどこに置くんだ・・?
2回目のEOSの後ろ、2回目のEOSの次の行、3回目のEOSの前・・どれもうまくいかない
メソッドをそこに置くんだよな・・?もしや・・
ヒアドキュメントの配列
[ <<-EOS, なんかいろいろ EOS <<-EOS なんかいろいろ EOS ]
できた!
Ruby いろんなループ(トリッキーなもの含む)
ループと言いつつ、やっているのは1から10の整数の乱数を作って、そこから6以上の値はもう一度やり直す。というもの
言い換えると、途中脱出が可能な無限ループ
です。え?スタックオーバーフロー?・・・
多分、最初のと最後(2018年11月24日追記分)がいいと思います。はい
puts "loopを使ったもの。多分これが一番メジャー" a = loop{ n = rand(1..10) break n if n<=5 } p a puts "再帰を使ったもの" def f n = rand(1..10) return f if n>5 n end a = f p a puts "ラムダ式を使ったもの。関数使ったやつとほぼ同じ" f = ->{ n = rand(1..10) (n<=5)? n : f.call } a = f.call p a puts "ただのwhile。他言語ならdo-whileを使う" a = nil while a.nil? || a>5 a = rand(1..10) end p a puts "whileとbreakを使ったもの" a = while true n = rand(1..10) break n if n<=5 end p a puts "例外のretryを使ったもの。速度的にも例外的にもあまり良くない気がする" a = begin n = rand(1..10) raise if n>5 n rescue retry end p a puts "いい感じのやつを自分で定義したもの" def loop1 yield end a = loop1{ n = rand(1..10) redo if n>5 n } p a puts "Integer#timesを使ったもの。" a = nil 1.times{ n = rand(1..10) if n>5 redo else a = n end } p a puts "Enumerable#mapを使ったもの。eachとかでもできるよね" a = [nil].map{ n = rand(1..10) redo if n>5 n }.first p a puts "無限リストを使ったもの。loop使ってるじゃんとか言わないで。selectで表現できるのは加点" a = Enumerator.new{|y|loop{y<<rand(1..10)}} .lazy .select{|n|n<=5} .first p a puts "関数に囲ってきれいに書けるようにしたもの" def infinite_list Enumerator.new{|y|loop{y<<yield}}.lazy end a = infinite_list{rand(1..10)} .select{|n|n<=5} .first p a # 2017年11月21日追加 puts "Rangeからの無限リスト" a = (1..Float::INFINITY) # 1/0.0で無限が作れるので、そっちでもいいのかも .lazy .map{|_|rand(1..10)} .select{|n|n<=5} .first p a puts "デフォルト引数を使ったもの" def f n=(n=rand(1..10);(n>5)? f : n) n end a = f() p a # 2018年11月24日追加 puts "loop+lazy+with_index 一年間の成長が詰まってる感じがする" a = loop .lazy .map{rand(1..10)} .select{|n|n<=5} .first p a
JavaScriptならイベントを使う方法があるらしい。
メモ Ruby対数正規分布の乱数
(2017/11/16)あああタイトル間違ってましたぁ・・更新前に見た方申し訳ないです・・
合っているかは自信ないです・・
ゲームの乱数くらいにお使いください。
require "random_bell" # http://pmsl.planet.sci.kobe-u.ac.jp/~seto/?page_id=316 # をRubyに移植 def lognormal mu, sigma return Float::NAN if (mu <= 0) bell = RandomBell.new( mu: Math.log(mu*mu) - Math.log(mu*mu + sigma*sigma) / 2.0, sigma: Math.sqrt(Math.log(1 + (sigma / mu) * (sigma / mu))), range: -10..10) Math.exp(bell.rand) end
分布確認用
require"./lognormal" puts (1..10000).to_a.map{|n|lognormal(平均,分布).to_i}.inject({}){|r,n|r[n]||=0;r[n]+=1;r}.sort_by{|n,v|n}.map{|n,v|"#{n} #{"*"*v}"}
C++(標準ライブラリ)にもPython(NumPy)にもC#(Math.net)にもあるのに
Rubyにはない悲しみ
gem install random_bell
random_bellを使用しています。
random_bell (0.1.1)
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
Ruby 呼び出せないメソッド
define_method("!bar", ->{"foo"}) p method("!bar") p method("!bar").call # 呼び出し方 !bar #< 呼び出せない
こんなことができるとは思ってなかった
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
にて確認