3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Yokohama.rb #54 memo

Last updated at Posted at 2015-03-15

レシピブック雑談

内部エンコーディングと外部エンコーディング

  • 内部エンコーディング
  • 外部エンコーディング
  • ソースコードのエンコーディング

と、3つエンコーディングがあってわかりにくい。
3つばらばらなことはあまりないんだけど、あえてバラバラにするとこんな感じ:

# coding:euc-jp
Encoding::default_internal="Windows-31J"
Encoding::default_external="GB18030"

# ソースコード内にある文字列は、そのソースコードのエンコーディング。
p "あ".encoding.name #=> "EUC-JP"

# デフォルトに従い、GB18030 だと思い込んで読み、"Windows-31J" に変換してから文字列にする。
p File.open( "somefile.GB18030" ).read.encoding.name #=> "Windows-31J"

# 引数に従い、euc-jp だと思い込んで読み、デフォルトにしたがって "Windows-31J" に変換してから文字列にする。
p File.open( "somefile.euc-jp", "r:euc-jp" ).read.encoding.name #=>"Windows-31J"

# 引数に従い、euc-jp だと思い込んで読み、"UTF-16LE" に変換してから文字列にする。
p File.open( "somefile.euc-jp", "r:euc-jp:utf-16le" ).read.encoding.name #=> "UTF-16LE"

普通は

  • ソースコードのエンコーディングは utf-8。
  • 内部エンコーディングも utf-8。
  • 外部エンコーディングもできるだけ utf-8 にしたいけど、エクセルが吐いた CSV を読むから "Windows-31J" とか、そういうことはある。

という対応にすると思う。

リテラル

ruby 2.2.0 には、レシピブックにないリテラルがある。

1i #=> (0+1i)
1r #=> (1/1)
1ri #=> (0+(1/1)*i)
%i( foo bar baz ) #=> [:foo, :bar, :baz]

二種類の比較スペースシップと不等号

<=> があれば <, > は論理的には存在可能なのでありそうな気もするんだけど、

[1]<=>[2] #=> -1
[1]<[2] #=> undefined method `<' for [1]:Array

と、スペースシップがあっても不等号があるとは限らない。

文字の出現頻度と itself

レシピブックのレシピ34で、文字列に含まれる文字の出現回数を数えてるけど、ruby1.9 を使ってよければこう書くよ、という話。

def char_count_list(str)
  str.chars.group_by{|c|c}.map{|k,v|[k,v.size ]}.sort_by{|x| -x.last}
end

そうそう。2.2 だと itself が使えるから

def char_count_list(str)
  str.chars.group_by(&:itself).map{|k,v|[k,v.size ]}.sort_by{|x| -x.last}
end

と書ける。
当日は思いつかなかったけど、これが itself の期待されている使い方だと思う。

hex, to_i, to_f

数を表す文字列を数値に変換するときにひどい目に合うことがある。

有名なのは JavaScript の parseInt だよね。
と思ったら、0 で始まっても8進数にならなくなったらしい。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/parseInt
によると、Firefox は 21 ( 2013 年 5 月 )から。

実行結果は以下のとおり(Node.js v0.10.35):

Node.js
parseInt("012") // => 12
parseInt("0x12") // => 18
parseInt("12") // => 12
parseInt("12e8") // => 12
parseInt("12.99") // => 12
parseInt(".99") // => NaN
parseInt("0.99") // => 0
parseInt("+2") // => 2
parseInt("-2") // => -2
parseInt(" -2 ") // => -2
parseInt(" +2 ") // => 2
parseInt("-+2") // => NaN
parseInt("++2") // => NaN
parseInt(" 2 ") // => 2
parseInt(" + 2 ") // => NaN
parseInt(" - 2 ") // => NaN
parseInt("-0x12") // => -18
parseInt("0y12") // => 0
parseInt("0xx") // => NaN
parseInt("0yy") // => 0

"0xx" が NaN になるのが意外だった。

ruby の to_i もちょっとおもしろい動きをする。
下表の通り。

receiver .to_i .to_i(16) .to_i(8) .to_i(2) .hex .to_f
0d12 12 3346 0 0 3346 0.0
0x12 0 18 0 0 18 0.0
0o12 0 0 10 0 0 0.0
012 12 18 10 1 18 12.0
0b101 0 45313 0 5 45313 0.0
1e23 1 7715 1 1 7715 1.0e+23
0xx 0 0 0 0 0 0.0
0yy 0 0 0 0 0 0.0
.1 0 0 0 0 0 0.1
0x1.2 0 1 0 0 1 0.0
+1 1 1 1 1 1 1.0
+ 1 0 0 0 0 0 0.0

ruby には 0d という 10 進数を表す記号があって、16進数との混乱がある。
実用上困るシーンは思いつかないけどね。

JavaScript の parseInt と異なり、to_i は、0x12 の先頭を 16進数の prefix とはみなさない。

0xx のようなおかしい入力を、JavaScript の parseIntNaN にするけど、ruby は 0 にする。私としては ruby の方が自然な感じがする。

その他の話題

Yosemite + QuickTime Player で、iPhone の画面を Mac 上に表示できる。
ああそんな機能あったっけ、と思った。

3
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?