Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

ruby

inject内部で条件付きな式を使う場合注意すること

inject内部で条件付きな式を使う場合、 かならず初期値*1を返すようにしないと エラーを吐きます。 実例を挙げると、 ary.inject("") {|ary, item| ary << item if item > 'e'; ary}といったように初期値を吐き出すようにしないといけません。 実際のところ …

Comparbleモジュールを組み込んで比較メソッドを楽に定義する

""メソッドを定義し、Comparbleモジュールを読み込むと、 "", ">="といったメソッドを追加することができます。 実際のところ 前のコードを改造して、以下のようにします。 require 'pp' class Rarity include(Comparable) attr_reader :rarity def initiali…

Comparebleを使って自前クラスにsortの挙動を実装する(その2)

大分間が空きましたが、Comparebleを使って自前クラスにsortの挙動を実装する - Bye Bye Mooreshuzo-kino.hateblo.jp の続きです。メソッドを定義すると、希望通りにソートしたり比較できたりするようになります。 #実際のところ カードのレア度でソートする…

一定値以下の値を固定値で返したい場合、配列とArray#maxでちょっと楽しく書くことができる

その発想がなかったのでメモ。一定値以下の値を固定値で返したい場合…… 例えば、値がマイナスの時、0にしたいというようなケースでは、 配列とArray#maxでちょっと楽しく書くことができます。Rubyだと ary = Array.new(10) {rand(0xf)} #=> [9, 4, 5, 6, 7,…

Integerにinstance_evalによるメソッド追加は不可能

お急ぎの方へ Integerをはじめ、数値オブジェクトはfreezeされて変更を受け付けません。 よって、instance_evalのような破壊的メソッドは適用不能となります 本文 Integerにinstance_evalによるメソッド追加は不可能らしい……という話の記録メモです。文字列…

String#internで文字列をシンボルに変換できる

String#internで文字列をシンボルに変換できます。 "ZZ".intern #=> :ZZ シンボルのまま演算するのが面倒な処理は 一旦文字列化して後でinternでシンボルに戻してあげるといった処理が可能となります。 たとえば、公式によればSynbol#nextは :ZZ.to_s.next.i…

配列をfreezeする時は、ちゃんと中身もfreezeしとく

配列をfreezeする場合は mapにfreezeメソッドを渡し中身を定数化 配列自体をfreezeし、本体も定数化 という手順を取ります。ためしに、最初の手順だけで止めると str_frozen = %w(foo bar buzz).map(&:freeze) #=> ["foo", "bar", "buzz"] str_frozen[0].fro…

リテラル系記述を何度も呼び出す場合はObject#freezeで定数化してしまうと幸せになれる

%wリテラルは微妙に遅い…? - Bye Bye Mooreshuzo-kino.hateblo.jp 以前書いたこの記事。速度面での改善を図りたい場合はObject#freezeで定数化してしまう方法が有効です。 一度定数にしてしまえば一々再生成しないのでGCにも速度にも優しくなります。 ため…

procのcurry化や部分適用とcase判定文との合わせ技で似た条件判定をスマートに書く

case文、便利ですよね。 フラグ管理なんかだと重宝します。 が、ちょっと複雑な事をやろうとすると そんな時はProcを渡してあげると良くなるかもしれません 実際のところ あまり適正な例では無いのですが…… ビットフィルタかけて、任意のビットが立ってるか…

EnumerableにProc渡すなら外で作ってからにしましょう

Enumrableにprocオブジェクトを渡すとメソッドを渡した時のように実行してくれます。 このとき、procオブジェクト自体は外に出すか、素直にブロックを使うようにしないと、かなり遅くなります。 実際のところ 0を渡すと「A:1」、5なら「F:6」という感じの文…

String#[substr]でパターンに一致する場合そのパターンを返す

一致していれば文字列を返し "hoge fuga"['hoge'] #=> "hoge" 一致しなければ、nilを返します "hoge fuga"['foo'] #=> nil つかいどころと性能比較 require 'benchmark/ips' Benchmark.ips do |x| x.report("['substr']") { "hoge fuga"["fuga"]} x.report("…

"string contains null byte (ArgumentError)"と出たら、ヌル文字が入ってるので消す

たとえば、シリアルポートから数値をゲットしようとすると hoge.rb:32:in `system': string contains null byte (ArgumentError) てな感じでエラーを吐いて止まる事があります。 ヌル文字は"/000"とにして認識されており、表示はされませんが文字列に格納さ…

Structクラスを継承してはいけない(戒め

以前書いたStructで構造体なデータを扱う - Bye Bye Mooreという記事で class Point < Struct.new(:x, :y) def +(other_object) Point.new(x + other_object.x, y + other_object.y) end end とか書いていました。 が、公式リファレンスには 無名クラスのサ…

Rubyで標準エラーに出力するにはSTDERR

Rubyで標準エラーに出力するにはSTDERR puts "stdout" STDERR.puts "stderr" 実際のところ $ ruby error.rb stdout stderr $ cat buff.txt stdout $ ruby error.rb > buff.txt stderr $ cat error.rb puts "stdout"

Gem「railroady」でモデルを図表化する

Railroadsはgraph bizを利用し Railsのモデル関係をグラフ化してくれるgemです つかいかた gemリストに group :development, :test do gem 'railroady' end …and then run the master rake task… としてbundleした上で、必要な時に rake diagram:allとやって…

ZigbeeパケットをRubyで送ってみる

Digiから XCTU Software - Digi International てなツールは出ているのですが。 LinuxのGUIなしで送信しないといけない等々、そういった事情に合わせたものです。幸いにして、API2にも対応したruby-xbeeというgemがあるのでこれを使ってみましょう。 gem ins…

caseによってビミョーに違うメソッドを呼び出している場合の別実装

たとえば、次のようなタイプと値を指定すると特定の処理をしてくれるメソッドがあったとします。 def sortMethod(type,val) case type when :name then val.upcase when :val then val.next end end sortMethod(:name, "name") #>> "NAME" sortMethod(:val, …

「Ruby-Graphviz」で図表を楽に作る

Ruby-Graphvizは名前の通りGraphizをRubyから扱う事ができるgemです。 導入法 Graphvizを導入した上で gem install graphviz……とやればいいのですが。 OS X環境ではうまい事読んでくれないらしく require 'rubygems' gem 'graphviz require 'graphviz' と、…

until修飾子でloop系構文が不要になるケースがある

until修飾子は後置きのifみたいな感じで使える構文です。 違いは、フラグが立つまで延々と読み続けてくれること。 StringIOやSerialPortみたいな読みに行く系ライブラリでは重宝します。 実際のところ たとえば、以前扱ったN進数リテラルが混在している文字…

StringIO#eachには、FSっぽい感じで文字列を切り分ける機能がある

SringIOは標準添付でありながら、あんまり使われる所を見かけないライブラリ*1です。 これは文字列にIOクラスの挙動を持たせる便利なものです。このクラスのうち、StringIO#eachはちょっと特別な挙動をします。 引数に切り分け文字を指定してあげると、それ…

Enumerable#any?は条件が一致するか判定する

単純に、何か入っているか確認する用途にも使えますし (1..9).map.any? #>> true あるいは、ブロックを渡して条件が一致するメソッドがあるか調べることも可能。 (1..9).map.any?(&:odd?) #>> true これを応用したメソッドが、例のactive_supportに実装され…

(0xff - ...)みたいなことをやるなら、排他的論理和(XOR)を使うとメソッドチェインにできる

ZigBeeのチェックサム等々、結果から0xffを減算する処理があります。 とはいえ、一回の減算のためにメソッドチェインを崩すのも気が引けます。 こういう場合、排他的論理和(XOR)を使えば引き続きメソッドチェインできます。 XOR 0xff - 0x12 #=> 237 これは…

ZigBeeパケットのチェックサムを計算するRubyスクリプト

Zigbeeパケットのチェックサムはちょっとヤヤコシイです。手順としては 接頭辞0x7eとパケット長2バイトの合計3バイトを削る 末尾1バイトも削る 残った物を一バイト毎に分けて足し合わせる 0xff - さきほどの結果 ……これがチェックサムです。 死ぬほどヤヤ…

Rubyで標準出力からデータをとる

Rubyで標準出力からデータを取る場合、STDINをよみにいけば良いです。 実際のところ パイプ経由で受け取ったデータをCurlコマンドでherokuのアプリにpushする簡単なアプリを考えてみます。 STDINからデータを読むにはgetsメソッドを使えば良いので url = %Q(…

N進数リテラル混ざった文字列を配列に切り分ける場合、scanを使ってはいけない

リテラルが混在しているものから文字を一個ごとに切り出したいとします。 この場合、ぱっと思いつくのはscanですが…… "\u0012aga\x98ga987HH".scan(/.{1}/) #=> ["\x12", "a", "g", "a", "枠", "a", "9", "8", "7", "H", "H"] と、変に気を利かせて\x98gを"…

8進数リテラルや16進数リテラルが混在した文字列を元の16進数な文字列に置換する

SerialPortなどで16進数のパケットを受けると、 こんな感じの文字列が返ってくる事があります。 "~\u0000\u0018\x91\u0000\u0013\xA2\u0000@u" もとは16進数の数値がズラズラと並んでいるはずなのですが。 8以内の数値は8進数リテラル 9〜Fが含まれて…

PC版のSerialPortアプリで動いて組み込み機器で動かない場合、timeoutまわりを疑ってみる

とある案件で、組み込み機器で通信を受けて彼是するアプリを開発した事があります。 いわゆる組み込みLinux関係でしかもdebianだったので楽勝だろーとrubyのSerialPort系gemをつくってチャッチャッとつくってみました。……ところが。 いざ、本番環境の機器で…

何らかの事情でgemのリストを確認できないときは「GEMNAME::VERSION」で参照してみる

人様から譲り受けた環境で、かつ固定環境のため焼きこまれているgemのバージョンが確認し辛いときがあります。 そんなときは GEMNAME::VERSIONとやればバージョンが出てきます。 少なくとも、rubugemに公式で公開されている真っ当なgemならこれで値がでてき…

Enumerable#findにProcオブジェクト等々を渡して一致ナシの場合を楽に実装する

Enumerable#findにProcオブジェクトを渡してあげると、一致ナシの場合呼び出してくれます。 実際のところ findの引数にcallをもつオブジェクト……Procクラスとかlambdaとかを渡せばよいです。 (1..10).to_a.find( Proc.new { :none } ) {|i| i > 11} #=> :non…

Enumerable#drop_whileで、条件に一致したもの以降を捨てる

こんな配列があったとします。 buff = [2,6,7,1,2] これを、ある特定条件以降で切り捨てたい場合……drop_whileが使えます。 使い方 なんらかの都合で順番通りに処理したい場合も使えますが*1 buff.drop_while{|i| i < 5} #>> [ 6, 7, 1, 2 ] 順当な使い方から…