ruby 2.6 が出たので触ってみて、python と比較してみた

※ この記事はちょー長いです。垂れ流しアウトプットです。そして割とニッチなネタが多いです。
※ けどやって良かった。頭の整理と手を動かす良い機会になった。

## はじめに
### どうも
python 歴は 5-6 年ですが、ruby は 3 日のド素人です。

ruby ってなんか`put`とか`@`とか`| do |`とか出てくるやつでしょ？
みたいな状況からごにょごにょと 3 時間ほど書いて、たのしい Ruby を 2 時間くらいで流し読みして、そっから 12 時間くらいでまとめました。

前から ruby が気になっていて、[2.6 のリリースノート](https://www.ruby-lang.org/ja/news/2018/12/25/ruby-2-6-0-released/)が面白そうだったので休みに一気にやってみました。

ちなみに python は新人の半ばくらいの時に vim のプラグインを作りたくて python ruby perl からひとつ選ぶってなったときに、「プログラミングなんてなーんもわからん。とりあえずなんか名前がカッコイイ。」って理由で始めました。

### 向き不向きがあるので、選択肢を増やしたい
ruby と python のどちらが優れている！とかやる気は毛頭なくて、「〜〜するんならこっちの方が楽そう」ってのが理解できたら良いな、と思う。

例えば僕は「何か作ろ」ってなったとき、大体こんな感じで言語を決める。
（会社の制約や集団の経験言語も考慮しているので、ひとつの例として...）

まず                           | ざっと                                        | んで               
:--                            | :--                                           | :--              
大体どう作るか当たりが付いてる | 自分専用 and IO 少なめ                        | haskell          
                               | 他の人のローカルでも叩くことがある            | python           
                               | 思いついたクラス設計の検証をしたい            | scala            
                               | gradle 関係 and 文字列やリスト操作多め        | groovy           
                               | gradle 関係 and クラスや高階関数多め          | java (+ javaslang + lombok)            
                               | 会社の適当なインフラで web る                 | php              
                               | テキスト整形 and 他人がそれを再現しなくて良い | vim
                               | クソネタ作って Lightning Talk する            | js (+ github-pages)
悩みながらになりそう...        | チャレンジする気分                            | haskell          
                               | ちょっと大きい                                | scala          
                               | さっさと動かしたい                            | python           
else                           |                                               | python           

python に落ちることが多いし、得意で好きなんだけど、どうしても気にくわないことがある！

これ！！

```python:python
>>> lines = ['main.py', 'main.rb', 'readme']

>>> map(lambda line: 'python' if line == 'py' else 'ruby', map(lambda line: line.split('.')[1], filter(lambda line: '.' in line, lines)))
# => ['python', 'ruby']
```

辛い！！ネストすんの辛いわ！！別に書けるけど！！読むとき目線移動大変なんだよ！！最初に読むのここだよ！？

```python:python
#                                                                                               v ここ！！
>>> map(lambda line: 'python' if line == 'py' else 'ruby', map(lambda line: line.split('.')[1], filter(lambda line: '.' in line, lines)))
#                                                          ^ んで次ここ！！
```

そんなわけで変数に`@`とか`$`とかあってめんどそう、`&:`みたいな呪文怖い、`do |x|`？`| do | x`？って思って避けてた ruby を、チェインができるのでやってみることにした。

ちなみに、自分が ruby を使う状況で使わないだろうと思ったこととかは飛ばした。

+ 継承とか
+ mix-in とか extend とか
+ 例外
+ 特異メソッドとか
+ ブロックつきメソッドの自作（欲しくなったらやる）
+ ファイルモジュール（これはいつも linux コマンドの発行でやっちゃう）
+ 日付まわり

あ、ruby は 2.6.0 で python は 2.7.14 です。（なんとなくずっと 2.7 使ってる...）

あとはひたすら垂れ流します。

## 文字列
### 出力
まずはここから。

#### ruby
名前  | 特徴            | 1   | "1" | "foo\tbar"     | [1, 2, 3]   | 用途    
:--   | :--             | :-- | :-- | :--            | :--         | :--     
p     | .inspect + 改行 | 1   | "1" | "foo\tbar"     | [1, 2, 3]   | デバッグ
puts  | .to_s + 改行    | 1   | 1   | foo&#x0009;bar | 1<br>2<br>3 | 人間に見せる
print | .to_s           | 1   | 1   | foo&#x0009;bar | [1, 2, 3]   | 人間に見せる

`pp`はとりあえず要らないかな、って思って略。

`to_s`書いても自作クラスが`p`で使ってくれない、って思ったけど`inspect`なんてのがあるのか。

とりあえず開発中は`p`で良さげ。
haskell の`print`と`putStrLn`と`putStr`と似てる。

#### python
python は print しかないので特に迷うことはない。

改行したくなければ`print x,`ってやるって覚えてるとちょい便利、くらい。

### 組み立て
よく使うので個人的にはかなり大事なポイント。

#### ruby
（ここでは`p`じゃあなくて`puts`を使う）

変数や特殊文字が入らないなら、`'`も`"`も同じで、片方を中でそのまま使える。

```ruby:ruby
puts "I'm John."           # => I'm John.
puts '{"name": "John"}'    # => {"name": "John"}
```

特殊文字や式展開は`"`じゃあないと無効。

```ruby:ruby
name = 'John'

puts 'win path is doc\readme.md'    # => win path is doc\readme.md
puts "win path is doc\readme.md"    # => eadme.md is doc

puts 'my name is #{name}.'    # => my name is #{name}.
puts "my name is #{name}."    # => my name is John.
```

ってことは... json 作るのちょっとめんどい？？

```ruby:ruby
puts "{\"message\": \"I'm #{name}.\"}"    # => {"message": "I'm John."}
```

here document があるので、これなら良い？？

```ruby:ruby
puts <<EOS
{"message": "I'm #{name}."}               # => {"message": "I'm John."}
EOS
```

groovy と似てるかな。
式展開は素直に書けて良い感じ。

#### python
python は`'`と`"`に違いはない。どっちかを外側にしてもう片方を中で使えるのも ruby と同じ。

```python:python
print "I'm John."              # => I'm John.
print '{"name": "John"}'       # => {"name": "John"}
```

変数展開がどちらででもできるのが好きだけど、展開場所の指定は ruby の方がすっきりしてると思う。
（`.format`や`locals()`等の細かいことは略。）

```python:python
name = 'John'

print 'my name is %s.' % name    # => my name is John.
print "my name is %s." % name    # => my name is John.
```

ruby の`'`に相当するものは、`r''`（もしくは`r""`）になる。raw string の r だろな。

```python:python
print r'win path is doc\readme.md'    # => win path is doc\readme.md
print  'win path is doc\readme.md'    # => eadme.md is doc
```

here document は`"""`で囲う。１行でも可能。この場合は中で`"`と`'`が使える。

```python:python
print """{"message": "I'm %s."}""" % name # => {"message": "I'm John."}
```

json や linux コマンドを組み立てるときに便利。
`"""`は地味だけど python の好きなところのひとつ。

### 日本語
こりゃあ ruby の方が試すまでもなく楽だろね。

#### ruby
```ruby:japanese.rb
puts "仕様書.doc\nmain.rb\ntest.rb"
```

こんなスクリプトに対してコマンドラインから叩くと、当然予想通り動く。

```
$ ruby japanese.rb | grep rb
main.rb
test.rb
```

2.0 以降は標準で utf-8 らしい。

#### python
```python:japanese.py
# -*- coding: utf-8 -*-

print u'仕様書.doc\nmain.py\ntest.py'
```

```
$ python japanese.py 
仕様書.doc
main.py
test.py
```

問題ないと思いきや、怒られる。

```
$ python japanese.py | grep py
Traceback (most recent call last):
  File "japanese.py", line 6, in <module>
    print u'仕様書.doc\nmain.py\ntest.py'
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
```

コマンドラインに出力するときと、`|` に繋いだりして出力するときで挙動が違う。
あと vi の中から叩いたりしても同様。

```python:japanese.py
# -*- coding: utf-8 -*-

import sys, codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

print u'仕様書.doc\nmain.py\ntest.py'
```

こうする。妙に大変。知ってた。

## インタプリタ
### 型を調べる
#### ruby
```ruby:ruby
irb(main):001:0> 'foo'.class
=> String

irb(main):004:0> 'foo'.chomp.class
=> String

irb(main):010:0> 'foo'.start_with?.class
=> FalseClass
```

なんだけど、どうも思ってたのとちょっと違う...?? これ評価結果に`.class`してるよね...
メソッドか属性値なのか知りたくなったりしないのかな...??

#### python
```python:python
>>> type('foo')
<type 'str'>

>>> type('foo'.strip)
<type 'builtin_function_or_method'>

>>> type(os.path)
<type 'module'>

>>> type(os.path.join)
<type 'function'>
```

とりあえず混乱したら`type`して一息付く感じ。これだけで大分手がかりになる。

### 属性を調べる
#### ruby
```ruby:ruby
> class Foo
>   def name()
>     'foo'
>   end
> end

> foo = Foo.new()

> foo.methods
=> [:name, :instance_variable_defined?, .. 略.. :__send__]

> ''.methods
=> [:to_r, :encode, :encode!, :include?, :%, .. 略 ..]
```

これは python と似た感覚で使えそう。ちょっと長いけど。

#### python
```python:python
>>> class Foo:
...   def name(self):
...     return 'foo'

>>> foo = Foo()

>>> dir(foo)
['__doc__', '__module__', 'name']

>>> dir(str)
['__add__', '__class__', ..略.. 'upper', 'zfill']
```

`type`と合わせて使う。

### help
#### ruby
```ruby:ruby
> help String#match

(from ruby core)
------------------------------------------------------------------------
  str.match(pattern)        -> matchdata or nil
  str.match(pattern, pos)   -> matchdata or nil

------------------------------------------------------------------------

Converts pattern to a Regexp (if it isn't already one),
then invokes its match method on str.  If the second parameter is
present, it specifies the position in the string to begin the search.

  'hello'.match('(.)\1')      #=> #<MatchData "ll" 1:"l">
  'hello'.match('(.)\1')[0]   #=> "ll"
  'hello'.match(/(.)\1/)[0]   #=> "ll"
  'hello'.match(/(.)\1/, 3)   #=> nil
  'hello'.match('xx')         #=> nil
```

`help`でとりあえず起動してから色々探すってこともできる。

#### python
実は知らなくて、ruby の本読んでいて「へー、python にもあんのかな？」って思って叩いたら良いのがあったｗ

```python:python
>>> help(map)

Help on built-in function map in module __builtin__:

map(...)
    map(function, sequence[, sequence, ...]) -> list
    
    Return a list of the results of applying the function to the items of
    the argument sequence(s).  If more than one sequence is given, the
    function is called with an argument list consisting of the corresponding
    item of each sequence, substituting None for missing values when not all
    sequences have the same length.  If the function is None, return a list of
    the items of the sequence (or a list of tuples if more than one sequence).
```

良いことを知ったｗ

## file
### 読み込み
#### ruby
あんま自信ない...

```ruby:ruby
lines = File.read('foo.txt').split()
p lines                                 # => ["foo", "bar", "bla bla bla", "pon"]
```

これ、close してないことになる？
`.open`して`File`オブジェクトを一度手に入れて、`.read`したら`.close`するか、ブロックを渡す必要があるんだよね？
ブロックを渡す方は、要はローンパターンだよね。

これで確認できるのか自信ないけど、`.close`を書き換えて試してみた。

```ruby:ruby
class File
    def close;      puts 'close!!!';   end
    def write(str); STDOUT.write(str); end
end

f = File.open('foo.txt')
f.close                                                 # => close!!!

File.open('foo.txt', 'r') {}                            # => close!!!

lines = File.read('foo.txt') {}                         # =>

lines = File.read('foo.txt').split                      # =>

lines = File.open('foo.txt', 'r') {|f| f.read.split}    # => close!!!

lines = File.open('foo.txt', &:read).split              # => close!!!
```

ちゃんと close させるには`open`経由しないとだめなの？ならなんで`File#read`があるの？
ちょっとしたスクリプトならあんま気にしない感じなの？

#### python
こうとか。

```python:python
with open('foo.txt', 'r') as f:
    lines = f.read().splitlines()

with open('foo.txt', 'r') as f:
    lines = map(str.strip, f)
```

下のは最近教えてもらった。

慣れるまでちょい変な感じがしたけど、シンプルだと思う。慣れたからかな？

## モジュール
正直ここはそんなに興味ないので、ruby の`require`をちょっとだけ。

### 読み込み
#### ruby
```ruby:ruby
puts 'foo'

if 1 == 1
    require './japanese'
    require './japanese'
end

puts 'bar'
```

```
$ ruby import.rb 
foo
仕様書.doc
main.rb
test.rb
bar
```

冒頭じゃあなくても書けるし、２度は読み込まれないっぽい。python と同じ。

冒頭じゃあなくても良いのは地味に好きで、例えば`if`に落ちた時だけ`require`するとかができる。
そうすると影響が小さくしやすくて読みやすいし消しやすくて好き。（統合開発環境とか全く使ってないのでそこら辺も手作業。）

ただ、名前が競合したりするのは気にしないのかな？

```ruby:imported_one.rb
def n()
    'n (one)'
end

def one()
    'one'
end
```

```ruby:imported_two.rb
def n()
    'n (two)'
end

def two()
    'two'
end
```

```ruby:ruby
require './imported_one'
require './imported_two'

puts n                    # => n (two)
```

#### python
名前が被ったり、手元のローカル変数と被るのが気になるときはメソッド単位で`import`するか、モジュール名を略さない。

```python:python
from imported_one import *
from imported_two import *

print n()                 # => n (two)
```

```python:python
from imported_one import n, one
from imported_two import two

print n()                 # => n (one)
```

```python:python
import imported_one
import imported_two

print imported_one.n()    # => n (one)
```

python の方が融通が利くけど、この`import`の`.`とか`from`が難しすぎる面もあるので、どっちもどっちなのかな？ -> [Pythonのimportについてまとめる](https://qiita.com/suzuki-hoge/items/f951d56290617df4279e)

## 演算子
### overload
二項演算子はどっちも大体同じ。

#### ruby
```ruby:ruby
class Lines
    attr_reader :xs

    def initialize(xs)
        @xs = xs
    end

    def +(o)
        Lines.new(@xs + o.xs)
    end

    def -@()
        Lines.new(@xs.reverse)
    end

    def inspect()
        @xs.join(', ')
    end
end

lines1 = Lines.new(['foo', 'bar'])

p lines1 + Lines.new(['pon'])    # foo, bar, pon
p -lines1                        # bar, foo
```

これは`1 + 2`が`1.+(2)`に見えていれば理解は簡単。scala と同じ。

`String`に対しても可能で、単項演算子も可能ってのは面白いなって思った。

#### python
```python:python
class Lines:
    def __init__(self, xs):
        self.xs = xs

    def __add__(self, o):
        return Lines(self.xs + o.xs)

    def __str__(self):
        return ', '.join(self.xs)

print Lines(['foo', 'bar']) + Lines(['pon'])    # => foo, bar, pon
```

似た感じ。

## 条件分岐
これは正直大差ないだろと思ってたけど、かなり違った。

### 文か式か
#### ruby
```ruby:ruby
if 1 == 1
    p 'true'     # => true
else
    p 'false'
end
```

これは python を同じだけど、こいつ値返すらしいぞ！

```ruby:ruby
x = if 1 == 1
    'true'
else
    'false'
end

p x    # => true
```

こいつはすげぇ！

これを

```ruby:ruby
if 1 == 1
    foo = 1
    bar = foo + 2
    foo = Foo.new(foo + bar)
else
    pon = 1
    foo = Foo.new(pon * 2)
end

p foo.twice()
```

こうできる！

```ruby:ruby
p Foo.new(
    if 1 == 1
        foo = 1
        bar = foo + 2
        foo + bar
    else
        pon = 1
        pon * 2
    end
).twice()    # => 8
```

変数大嫌いだし、`if`が式なのは色々と便利で良い！
メソッドの最後に書いてもそのまま値返却にできる。式は良い。

まさかと思って適当に書いてみて良かった。scala みたいだ。

#### python
```python:python
if 1 == 1:
    print 'true'
else:
    print 'false'
```

python は文なんだ、ちょっと、いや結構悲しい。

### 三項演算子
#### ruby
他の言語と同じ。

```ruby:ruby
x = nil
p x.nil? ? 'x is nil' : x                    # => x is nil
```

#### python
特殊。他で見たことない。
英語的ってやつかしら。

```python:python
x = None
print x if x is not None else 'x is none'    # => x is none
```

`print x, if x is not None. else, 'x is none'.`みたいに一息つきながら読む感じ。

ちなみに ruby の if 修飾子と違って`else`は無くせない。

### switch
#### ruby
`if`がそうだったのできっとと思ったけど、こいつも式みたい。良い！

```ruby:ruby
p case x
when 'rb'
    'ruby'
when 'py'
    'python'
when 'hs'
    'haskell'
else
    'unknown'
end
# => ruby
```

式になってると`.collect`とかにすっきり収まるはず。

```ruby:ruby
xs = ['rb', 'py', 'hs']

p xs.collect {|x| case x
    when 'rb'; 'ruby'
    when 'py'; 'python'
    when 'hs'; 'haskell'
    else     ; 'unknown'
    end
}    # => ["ruby", "python", "haskell"]
```

良いねー！（スタイルが ruby っぽくないのはわかってやってる。自分専用コードの時だけに留める。）
scala みたい。

#### python
文は大嫌いなので、式になってる scala や haskell でしか使ったことない。
まぁ python にはそもそも switch 文もないけど。

５年くらい前に使い捨ての辞書を引くって方法を自分で閃いて天才かと思ったけど、調べたら常套手段だった思い出ｗ

```python:python
x = 'py'

print {
    'rb' : 'ruby',  
    'py' : 'python',
    'hs' : 'haskell'
}[x].capitalize()       # => Python
```

paiza みたいなのやるときはちょいちょい使う。

完全に余談だけど、python の boolean はただの`0`と`1`のエイリアスなのを知ってるとこんなことができる。

```python:python
print ['false!', 'true!'][x.startswith('p')]        # => true!

print 'true!' if x.startswith('p') else 'false!'    # => true!
```

三項演算子より極僅かだけど短いので、コードゴルフで使う。

### 優先度
#### ruby
`and`より`&&`が強いらしい。へー。

```ruby:ruby
p false && false || true     # => true
p false and false || true    # => false
```

上は`(f && f) || t`で、下は`f && (f || t)`に相当するから。
おもしろいけど、自分で使うかは微妙。とはいえ場面が多くて、かつ慣れたら多用すると思う。

#### python
python は`and`と`or`のみで`&&`と`||`はない。これも英語的ってやつかしら。

### 演算子の連結
#### ruby
逆に ruby はこれができない。

```ruby:ruby
x = 5

p 1 < x < 10
```

まぁちょっと考えれば`1.<(x).<(10)`だけど、`TrueClass`が前の条件覚えた`.<`を持ってるわけないしね。

#### python
```python:python
x = 5

print 1 < x < 10    # => True
```

案外ないと「んあ〜」ってなるので、できるのはうれしい。

## メソッド
ここが本題。

### 無名関数
#### ruby
```ruby:ruby
f = lambda{|x| x + x}

p f.call(3)    # => 6
```

`def`で作ったものと違い、`f.call(x)`みたいに呼ぶ。もしくは`f[x]`。

こういう時に`def`と`lambda`を比べたいから型が知りたくなるんだけど、これだとエラーなんだよなー。
もうちょっと慣れが必要っぽい。

```ruby:ruby
def f(x); x + x; end

p f.class                    # => error

p lambda{|x| x + 2}.class    # => Proc
```

それは置いといて、`lambda`で作った方は`Proc`と言うらしい。[2.6 のリリースノート](https://www.ruby-lang.org/ja/news/2018/12/25/ruby-2-6-0-released/)で見たぞ。

```ruby:ruby
p [1, 2, 3, 4].collect do |x|
    x + x
end
```

そんでここの`do ~ end`をブロックというらしい。置き換えられるふいんき。

```ruby:ruby
lamb = lambda{|x| x + x}

p [1, 2, 3, 4].collect(lamb)
```

...怒られた。どうやらブロックと`lambda`は別物らしい。
ruby lambda to block とかでぐぐったら出るわ出るわ。鬼門らしい？

要約すると、「ブロックはオブジェクトではない。ブロックをオブジェクトにするなら`&`で`Proc`オブジェクトにする。」ってことっぽい。
`proc`と`lambda`の違いはわかった気がするけど、`break`も`return`も使う気は全く無いので今は無視。

なので、こうだ。

```ruby:ruby
lamb = lambda{|x| x + x}

p [1, 2, 3, 4].collect(&lamb)    # => [2, 4, 6, 8]
```

`lambda`は`->`による略記があるみたい。

```ruby:ruby
lamb = ->(x) {x + x}
```

こっちの方が`f(x) {...}`と同じ形だからわかりやすいでしょって書いてあったけど、`x -> {...}`の方がわかりやすいと思うｗ
java とか scala とか haskell とか js とか、大体こうじゃあない？

#### python
```python:python
f = lambda x: x + x

print f(3)    # => 6
```

`def`製と`lambda`製に違いはない。

```python:python
print map(f, [1, 2, 3, 4])    # => [2, 4, 6, 8]
```

正直ここだけ見ると python の方がシンプル。
（`f = lambda x: ...`みたいにラムダ式を変数束縛するのは PEP 8 では非推奨です。これはあくまで個人用なので好みでやってるだけです。）

### メソッド参照
名前は不適切っぽいけど。なんて言うのかな。

#### ruby
シンボルを`Proc`オブジェクトにすることで、`x.f(arg)`を`:f.to_proc.call(x, arg)`にできるみたい。

```ruby:ruby
'foo'.include?('o')                   # => true
:include?.to_proc.call('foo', 'o')    # => true
```

引数がひとつならこんな感じでそのままはまる。

```ruby:ruby
['ruby', '', 'python'].collect(&:empty?)    # => [false, true, false]
```

たまに見る`&:f?`っていう呪文みたいなのはこいつだったんだな。
`&`は`.to_proc`で、`:`がシンボル。`?`はただのメソッド名の慣習。呪文をひとつ習得。

ところで、なんで`.collect(`の中とかじゃあないと`&`で怒られるんだ？

```ruby:ruby
f = :empty?.to_proc    # => #<Proc:0x00007f877b0cd960(&:empty?)>
f = &:empty?           # => unexpected &
```

その辺がまだわからん...

#### python
似た感じ。`.to_proc`とか`.call`がないのでスッキリしてる。

```python:python
'foo'.startswith('f')                 # => True
str.startswith('foo', 'f')            # => True

map(str.strip, ['foo\n', 'bar\n'])    # => ['foo', 'bar']
```

数年触ってて、これ先日まで知らなかったんだよね...

### デフォルト引数と名前付き引数
リスト渡しとか辞書渡しは使わないので無視。必要な場面に出くわしたら調べる。

#### ruby
```ruby:ruby
def f(a: 0, b: 0, c: 0)
    p [a, b, c]
end

f(b: 3, a: 1)      # => [1, 3, 0]
```

デフォルト引数がある引数は、名前指定で渡せる。

#### python
```python:python
def f(a, b, c = 0):
    print [a, b, c]

f(b = 3, a = 1)    # => [1, 3, 0]
```

デフォルト引数がなくても、名前指定で渡せる。
これは引数が多い場合に呼ぶ側の可読性が上がったりして地味に好き。

### 複数引数の無名関数
#### ruby
```ruby:ruby
p [['ruby', '2.6'], ['python', '2.7']].collect{|x| "#{x[0]}-#{x[1]}"}                   # => ["ruby-2.6", "python-2.7"]
```

これは多分`a, b = [1, 2]`みたいな代入ができるんだから、きっとこうできる。

```ruby:ruby
p [['ruby', '2.6'], ['python', '2.7']].collect{|name, version| "#{lang}-#{version}"}    # => ["ruby-2.6", "python-2.7"]

f = ->((name, version)) {"#{name}-#{version}"}
p [['ruby', '2.6'], ['python', '2.7']].collect(&f)                                      # => ["ruby-2.6", "python-2.7"]
```

できた。

`lambda`の方は、`->(name, version)`だと「引数の数あってねーよ」って怒られたので適当に`()`をもう一つ書いたら動いた。
あくまで１つの引数を受けて、受けた方がバラすのでこうなるってことかな。haskell みたい。

#### python
```python:python
f = lambda (name, version): '%(name)s-%(version)s' % locals()

print map(f, [['ruby', '2.6'], ['python', '2.7']])                                                   # => ['ruby-2.6', 'python-2.7']
```

ruby と同じ感じ。

```python:python
print ['%(name)s-%(version)s' % locals() for name, version in ['ruby', '2.6'], ['python', '2.7']]    # => ['ruby-2.6', 'python-2.7']
```

内包表記の`for`の部分は`,`でバラして受けられるのでよく使う。

### カリー化
#### ruby
```ruby:ruby
f = ->(name, version) {"#{name}-#{version}"}
python = f.curry.call('python')

p ['2.7', '3.3'].collect(&python)    # => ["python-2.7", "python-3.3"]
```

できるんだ！良さげ！

ただ、これが怒られるのがよくわからない。

```ruby:ruby
:+.to_proc.curry('result: ').call('Ruby-2.7')    # => 'result: '.+('Ruby-2.7') だから、result: Ruby-2.7 になると思った

:+.to_proc.call('result: ', 'Ruby-2.7')          # => これは result: Ruby-2.7 になるのになぁ
```

haskell の`("result:" ++)`みたいに演算子の部分適用できたらすげー便利だと思うのに...

#### python
できないんだよなー、残念。

### 関数合成
これが「良いな！」ってなって ruby を始めた。

#### ruby
```ruby:ruby
join     = ->((name, version)) { "#{name}-#{version}" }
cap      = ->(s)               { s.capitalize }
surround = ->(c, s)            { "#{c} #{s} #{c}" }
pipe     = ->(s)               { surround.call('|', s) }

f = join >> cap >> pipe

p f.call(['ruby', '2.6'])                                                                              # => | Ruby-2.6 |

p [['ruby', '2.6'], ['python', '2.7']].collect(&f)                                                     # => ["| Ruby-2.6 |", "| Python-2.7 |"]
```

`>>`と`<<`、良いなぁ！

メソッド参照とカリー化も出来るってことは...

```ruby:ruby
p [['ruby', '2.6'], ['python', '2.7']].collect(&join >> :capitalize.to_proc >> surround.curry['|'])    # => ["| Ruby-2.6 |", "| Python-2.7 |"]
```

できた！慣れてきたー！

`&(f >> g)`にしないで良いって事は、演算子の優先順位は`&`の方が弱いってこと？

#### python
自分で合成書けば...

```python:python
join     = lambda (name, version): '%(name)s-%(version)s' % locals()
cap      = lambda s              : s.capitalize()
surround = lambda c, s           : '%(c)s %(s)s %(c)s' % locals()
pipe     = lambda s              : surround('|', s)

comp3 = lambda f1, f2, f3: lambda x: f3(f2(f1(x)))

f = comp3(join, cap, pipe)

print f(['ruby', '2.6'])                              # => | Ruby-2.6 |
 
print map(f, [['ruby', '2.6'], ['python', '2.7']])    # => ["| Ruby-2.6 |", "| Python-2.7 |"]
```

あんまり恩恵感じないかな...

## リスト
### 連結
大半をメソッドのところでやっちゃったけど。
こいつが前置きにあった一番のポイント。

#### ruby
```ruby:ruby
xs = ['ruby', 'python', 'php', 'js']

f = lambda{|x| x % 2 == 0 ? 'even' : 'odd'}

p xs
    .select{|x| x.start_with?('p')}
    .collect(&:length)
    .collect(&f)
    .join(', ')    # => even, odd
```

んー、良い！
改行できるのがとても良い！

`.join`も`Array`のメソッドなので、最後に書けるのがとても良い！

目線が左上から右下に素直に行くのは、とっても大事！

ちなみに関数合成ができたので、複数引数の片方しか使わない場合は、これを

```ruby:ruby
is_p = proc{|x| x.start_with?('p')}

xs = ['foo.ruby', 'bar.python', 'pon.php', 'kaz.js']

p xs
    .collect{|x| x.split('.')}
    .select{|name, ext| is_p.call(ext)}
    .collect{|name, ext| name}
    .join(', ')                                      # => [bar, pon]
```

こんな風に書いたりできる。haskell 風。

```ruby:ruby
fst = proc{|x, _| x}
snd = proc{|_, x| x}

p xs
    .collect{|x| x.split('.')}
    .select(&snd >> is_p)
    .collect(&fst)
    .join(', ')                                      # => [bar, pon]
```

こういうのはメソッドが集まるほど強いので、個人的にはとても好き。

#### python
```python:python
xs = ['ruby', 'python', 'php', 'js']

f = lambda x: 'even' if x % 2 == 0 else 'odd'

print ', '.join(map(f, map(len, filter(lambda x: x.startswith('p'), xs))))

print ', '.join(
    map(
        f,
        map(
            len,
            filter(
                lambda x: x.startswith('p'),
                xs
            )
        )
    )
)
```

辛い...

これくらいなら内包表記で書くかなー...

```python:python
print ', '.join(
    [f(len(x)) for x in xs if x.startswith('p')]
)    # => even, odd
```

慣れてるのでそんなに読み書きは苦ではないけど...

`xs`を探す -> `if`探す -> `[`の左端から読む -> 上の行の`join`読む。ってなるので、目線がすんげーことになる。とても残念。

ところで、scala とか java とかもやったけど、`sep.join(xs)`の形って珍しいよね。普通は`xs.join(sep)`だよなぁ。

なんでこうなってんだろ。
`list`が処理を持てないのかな？。だから`len`も`xs.len()`じゃあなくて`len(xs)`だし`map`も`.map`じゃあなくて`map()`なのかな？`dict`は`.get()`とか`.items()`とかあるのにな。

### スライス
地味だけど重宝する。

だいたい python と同じだった。良い感じ。

#### ruby
```ruby:ruby
xs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

p xs.slice(7..-1)             # => [7, 8, 9]
p xs.slice(7..)               # => [7, 8, 9]    -1 の省略は 2.6 から
p xs.slice(0..0)              # => [0]
p xs[-1]                      # => 9
p xs.slice(5..-2)             # => [5, 6, 7, 8]
p xs.slice(5...-1)            # => [5, 6, 7, 8]
p xs.slice((1..-1).step(2))   # => error
```

なんだよ`range`なら良いんだろーと思ったけど、`range`じゃあなかった。そっかー。

```ruby:irb
> (1..2).class
=> Range

> (1..2).step(2).class
=> Enumerator::ArithmeticSequence

> ((1..2) % 2).class    # % は 2.6 から
=> Enumerator::ArithmeticSequence
```

#### python
`[::]`の意味を知っていればすっきり読み書きできる。（`[start:end:step]`）
ちょっと含む範囲が違う。step も有効で、応用で逆順がサッとできる。

python の好きなところのひとつ。

```python:python
xs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print xs[7:]        # => [7, 8, 9]
print xs[:1]        # => [0]
print xs[-1]        # => 9
print xs[5:-2]      # => [5, 6, 7]
print xs[5:-2:2]    # => [5, 7]
print xs[::-1]      # => [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
```

ちなみに`xs[:1]`は案外便利で、リストの先頭要素がリストのまま欲しいときに重宝する。

1000 くらいの長さのリストを試しに一周だけ動かすときとかに便利。

```python:python
print [f3(f2(x)) for x in xs if f1(x)]        # これを試しに１回だけ動かすのに

print f3(f2(xs[0])) if f1(xs[0]) else None    # がっつり書き直さなくても

print [f3(f2(x)) for x in xs[:1] if f1(x)]    # [:1] だけ付けちゃう
```

ruby と python どちらも`[]`に対してやったら`[]`が返ってくるので安全。

稀に便利なちょいテク。

### 内包表記
もうちょくちょく出してるけど。

#### ruby
ないっぽい。
まぁ`.collect`とかが改行できるし、良いかな。

#### python
下手に`for`で一時変数に足し込むのは変数が散らかるので大嫌い。

`map`との使い分けは状況次第で簡潔な方ってかんじ。

`map`と`filter`が１回ずつ出る場合はまず内包表記でやる。（ネストするから）
`map`か`filter`がどちらか１回の場合は`lambda`ってタイプしないといけないかどうかとかで決めてるなぁ。

```python:python
xs = ['python', 'ruby']

print map(len, xs)            # => [6, 4]
print [len(x) for x in xs]    # => [6, 4]

print map(lambda s: 'lang is %s.' % s, xs)    # => ['lang is python.', 'lang is ruby.']
print ['lang is %s.' % x for x in xs]         # => ['lang is python.', 'lang is ruby.']
```

微妙にどっちかの方がすっきりしてるｗ

あと新人時代に冒頭しか読めなかった[エキ py](https://images-na.ssl-images-amazon.com/images/I/515wWUPkhHL._SX258_BO1,204,203,200_.jpg) に性能の話があったけど、ruby が主軸なので割愛。

### flat_map
`1 : *`構造が入れ子になってたりする時に使う。作るものの特性上、結構使うので気になるところ。

#### ruby
```ruby:ruby
xs = ['main.rb', 'readme.md', 'test.rb']

read_rb = ->(path) {path.end_with?('rb') ? ["this is #{path}", 'bla bla bla...'] : []}

p xs.map(&read_rb)         # => [["this is main.rb", "bla bla bla..."], [], ["this is test.rb", "bla bla bla..."]]
```

`read_rb`は引数で受けたパスのファイルを open, read して、中の行をリストで返すような処理。（だと思って。）

`.map`でやると`[[]]`になっちゃう。
（例として便宜上`readme.md`をスキップしたけど、空ファイルだったりする場合も同様に`[]`になる。そもそも`.md`を`[]`にしたいなら先に`.select`するけど、これは例なので。）

```ruby:ruby
p xs.flat_map(&read_rb)    # => ["this is main.rb", "bla bla bla...", "this is test.rb", "bla bla bla..."]
```

`.flat_map`あるんだね。良い。

#### python
`flatten`的なのがないので、内包表記で`for for`したり、空リストに対して畳み込んだりする。

```python:python
xs = ['main.py', 'readme.md', 'test.py']
read_py = lambda path: ['this is %s' % path, 'bla bla bla...'] if path.endswith('py') else []

def flat_map(f, xs):
    return sum(map(f, xs), [])

print flat_map(read_py, xs)    # => ['this is main.py', 'bla bla bla...', 'this is test.py', 'bla bla bla...', 'this is readme.md', 'bla bla bla...']
```

## 他、気になってること
個人的によく書くこととかを触っておきたい。

### コマンドライン引数
#### ruby
特に`require`は不要。

```ruby:ruby
p ARGV

# => ruby ./command.rb 1 3
#
#    ["1", "3"]
```

グローバル変数だから`$`使うのかな？って思ってたけど、これは定数？

#### python
```python:python
import sys

print sys.argv

# => python ./command.py 1 3
#
#    ['./command.py', '1', '3']
```

### コマンドライン引数パーサ
オレオレ自作コマンドを良く作るので、良く触る。

#### ruby
`OptionParser`っていう手の込んだやつと、手っ取り早く`ARGV`を改造する`getopts`があるみたい。

```ruby:ruby
#!/usr/local/bin/ruby

require 'optparse'

params = ARGV.getopts('', 'tension:', 'lang:en')

puts "#{params['lang'] == 'en' ? 'foo' : 'ふー'}#{'!' * params['tension'].to_i}"


# => $ foo -h
#    Usage: foo [options]
#            --tension=VAL
#            --lang=en
#
#
#    $ foo --tension 4
#    foo!!!!
#
#
#    $ foo --tension 4 --lang ja
#    ふー!!!!
```

すっきりしてて良い感じ。


ところで、どうして`-h`が生成されるの？

`.getopts`が`ARGV`を破壊しているの？それとも`.getopts`に渡した情報がどっかに渡ってるのかな？
get しかしてないのにちょっと気持ち悪いｗ

#### python
3 系だともっとイケてるのかもしれないけど、ずっとこんな感じでやってる。
これは適当だけど、排他オプションとかもちゃんとできるので良い。

```python:python
#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import argparse

parser = argparse.ArgumentParser(description = 'say foo!')
parser.add_argument('tension', type = int, help = 'number of !')
parser.add_argument('-l', '--lang', default = 'en', type = str, action = 'store', help = 'language')
args = parser.parse_args()

print '%s%s' % ('foo' if args.lang == 'en' else u'ふー', '!' * args.tension)


# => $ foo -h
#    usage: foo [-h] [-l LANG] tension
#
#    say foo!
#
#    positional arguments:
#      tension               number of !
#
#    optional arguments:
#      -h, --help            show this help message and exit
#      -l LANG, --lang LANG  language
#
#
#    $ foo 4
#    foo!!!!
#
#
#    $ foo 4 --lang ja
#    ふー!!!!
```

### アノテーション
#### ruby
検索してみたけど、そもそも`@foo`みたいなのないんだ。

`TODO`等の特定のコメントを、アノテーションコメントと言うみたい。
rails はそれをかき集めるコマンドがあるからセットでひっかかるのかな。

#### python
python ではデコレータと言う。
java とかのとは違う感じで、本来の処理の前後に任意の処理を被せられる。

```python:python
def file_testing(f):
    def w(path):
        print 'mkdir %s if not exists\n' % path.split('/')[0]    # => 書き込み先のディレクトリがなければ作る

        f(path)                                                  # => 元々呼ばれた処理を呼ぶ

        print '\nremove %s' % path                               # => 作ったファイルを消しておく
    return w


def sut(path):         # 本当にやりたいこと
    print 'write to %s' % path


@file_testing
def sut_test(path):    # sut のテスト
    sut(path)
    result = sut が作ったファイルを読む
    assert len(result) == 2 とかする
    

sut_test('out/foo.txt')


# => mkdir out if not exists
#
#    write to out/foo.txt
#
#    remove out/foo.txt
```

理解できると案外さっと作れるので、メソッド本体を汚さずにゴミ掃除をしたり実行時間を計ったりできる。（詳細は割愛。）

多用はしないけど重宝する。python の好きなところのひとつ。

### os コマンド実行
これもよく使う。

ファイルモジュールで再帰的にファイル探すのとか面倒なので`find | grep`使っちゃったり、ライブラリ経由して mysql 操作するのが面倒だから`mysql -e`で適当に叩いちゃったりする。
http ライブラリ使うのも面倒なので`curl`しちゃうし、git のオレオレラッパー作るときも、文字列でコマンド組み立てて叩いちゃう。（自分専用は、ね。）

#### ruby
```ruby:ruby
res = `ls /tmp`.split()

p res    # => ["a.md", "a.py", "a.txt", "b.txt"]
```

すっきりしてて良いな！
groovy みたい。

一応、同期処理かも確認しておこう。

```ruby:ruby
puts "foo"
res = `sleep 2s; ls /tmp`.split()
p res
puts "bar"
```

ちゃんと`p res`が終わってから bar が出た。良かった。（groovy でよくハマるｗ）

#### python
手っ取り早いのは`os.system`だけど、戻り値が受け取れない。

```python:python
import os

res = os.system('ls /tmp')
print res    # => 0

# => python command.py
#    a.md
#    a.py
#    a.txt
#    b.txt
```

いつもは素直にリストになってくれる`commands.getoutput`を使ってる。

```python:python
import commands

res = commands.getoutput('ls /tmp').split()

print res    # => ['a.md', 'a.py', 'a.txt', 'b.txt']
```

### ポリシー・思想
#### ruby
当然まだ全然わからないけど、ちょっと調べてわかったことだけ...

ストレスなく楽しむってのが最も重視されているらしい。

あとどうもドキュメントが後追いな感じ？なの？

> 「Matz（まつもと） が Python に満足していれば Ruby は生まれなかったであろう」と公式のリファレンスの用語集で言及されている。

へーｗｗ

でも正直なところ、思ってたよりずっと触りやすくて良いなーって思った。

純粋な oop 言語が良かったらしい。確かに python の`len`とかを見ると、後付け感がすごい。
ruby は触っていて統一感がある感じがした。

知ってる言語の中だと（あんまり詳しくないけど）scala に一番似てる気がした。ド素人意見。

あと python とは逆に、同じ事をやる方法が多い印象もある。
「`proc`の呼び方が`f.call(x)` or `f[x]` of `f.(x)`」とか「`.map` or `.collect`」とか「`->` or `lambda`」とか「`proc` of `Proc.new`」みたいな、別名が多くてどっちに慣れると良いんだろ？みたいなノイズも感じた。

#### python
[the zen of python](https://www.python.org/dev/peps/pep-0020/) ってのがある。

あと印象深いのは、「同じ事をやるなら同じコードになる方が良い」とか「英語的」とかそんなフレーズ。
シンプルで読みやすくて、似るコードが美徳っぽい。

なので「`if`があるから`switch`はない」とか「`i += 1`があるから`i++`がない」とか「`&&`じゃあなくて`and`」とか「`x if x is not None else...`みたいな記述になる」とかなんだろな。
「`map`か内包表記か」とか「いやいや`import`ムズいし`from`とかどうすんだよ」とかも感じないわけではないけど、この考え方は好き。

（昔聞いた話で曖昧だけど、逆に perl は「同じ事をやるいろんなコードがあって良い」的な感じだった気がする。柔軟さやテクさが美徳的な。）

あった、これか

> やり方はいろいろある (There's More Than One Way To Do It; TMTOWTDI)

## おわりに
思ってたよりずっと満足できた。ruby にもまとめにも。集中も続いたのでガッとやってポイッてまとめて放り投げられて良かった。

あとは経験あるのみ。しばらくは ruby 書いてみようかなー。