Yokohama.rb #54 memo


##レシピブック雑談

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

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

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

```ruby
#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 には、レシピブックにないリテラルがある。

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

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

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

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

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

### 文字の出現頻度と itself

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

```ruby
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` が使えるから

```ruby
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)：

```JavaScript: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 の `parseInt` は `NaN` にするけど、ruby は `0` にする。私としては  ruby の方が自然な感じがする。

## その他の話題

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