ruby split

rubyのsplit メソッド

str.split(pattern = $;, [limit])

splitメソッドは、引数patternを区切り文字として文字列を分割し、配列を返します。引数の指定のしかたによってさまざまな分割ができます。分割できなかったときは、要素が文字列1つだけの配列を返します。

参照:

split (String) - Rubyリファレンス

引数でデフォルト引数が設定されている pattern = $;

$;は組み込み変数

irb(main):001:0> $;
=> nil

splitメソッドの引数を省略すると空白文字による分割になる

だから以下は同じ結果

irb(main):007:0> "1 2 3".split(" ")
=> ["1", "2", "3"]
irb(main):008:0> "1 2 3".split
=> ["1", "2", "3"]

Elixir 開発環境

Elixirの勉強を個人的に始めたので覚書を残す。

dockerでElixirを使えるようにする

以下コマンドでdocker imageをpullする

docker pull trenpixster/elixir

docker上のelixir imageを起動する

docker run --rm -v /Users/kei/takakuda/elixir_tutorial:/elixir_tutorial -it trenpixster/elixir /bin/bash

あまりdockerを使ったこともなかったのでoptionも調べる

--rm : コンテナ終了時に自動的にコンテナを削除する

-v : ホスト側のディレクトリがコンテナにマウントされ、コンテナ上で作ったファイルがホストの方に残る

-it : ターミナルでコンテナを実行できる

iexで対話シェルが動くことを確認。

Elixirのプロジェクトを作成する

mix new project

mixはビルドツール。 以下のようにフォルダ、ファイルが作成されます

.
├── README.md
├── config
│   └── config.exs
├── lib
│   └── project.ex
├── mix.exs
└── test
    ├── project_test.exs
    └── test_helper.exs

ここからelixirで開発していきます

gem 作り方覚書

準備

# gem自信のupdate
gem update --system

# bundlerのupdate
gem update bundler

# generatorからプロジェクト作成
bundle gem new_gem -t

-tはテストも作成するoption defaultでRSpec

他のgemと名前がかぶってはいけないので

gem search new_gem

で名前がかぶっていないことを確認しましょう。

雛形を作成することができたらnew_gem.gemspecを編集します

spec.summary       = %q{TODO: Write a short summary, because Rubygems requires one.}
spec.description   = %q{TODO: Write a longer description or delete this line.}
spec.homepage      = "TODO: Put your gem's website or public repo URL here."

TODOと書かれている箇所を編集していきます

summary -> サマリー

description -> 長めのサマリー

homepage -> https://github.com/takakuda/new_gem

といった感じです

# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' と書かれている箇所は社内用のgemを外部に公開しないために公開して良いホストを指定する箇所です。 RubyGems.orgに公開するのでごっそりこのあたりの記述は消します。

作成したgemをlocalで確認

new_gemを作った同じ階層にテスト用のフォルダを作成し

bundle init

Gemfileを作成します

new_gem
├── Gemfile
├── README.md
├── Rakefile
├── bin
│   ├── console
│   └── setup
├── lib
│   ├── new_gem
│   │   └── version.rb
│   └── new_gem.rb
├── miura.gemspec
└── spec
    ├── new_gem_spec.rb
    └── spec_helper.rb
new_gem_test
├── Gemfile
├── Gemfile.lock

Gemfileでは

gem "new_gem", path: "../new_gem"

でlocalのgemをinstallします

その後にbundleを実行

あとはtest用のfileを作成してgemをrequireで呼べば確認できます

確認後公開用にリポジトリを作成し、https://rubygems.org/でアカウントを作成して有効な状態にすればリリースの準備は完了です

リリース

リリースはgemspecのあるディレクトリでrake releaseを実行

自分のプロファイルページに追加されていれば完了です! https://rubygems.org/profiles/takakuda

Rubyにおける「シンボル」ってなんだ?

結局「シンボル」ってなに…

結論から言うとシンボルはRubyの内部で整数として扱われる。2つの値が同じか調べるときなど、文字列よりも高速に処理することができる。

シンボルのほうがさらにメモリの使用効率が良いらしい。

irb(main):009:0* 'a'.object_id
=> 70227007054700
irb(main):010:0> 'a'.object_id
=> 70227010342780
irb(main):011:0> 'a'.object_id
=> 70227010329420

irb(main):013:0* :a.object_id
=> 736988
irb(main):014:0> :a.object_id
=> 736988
irb(main):015:0> :a.object_id
=> 736988

シンボルは同じシンボルであれば同じオブジェクトであるということらしい。

Stringの場合はobject_idが実行ごとに変わっている

なんで「シンボル」使ってるんだろうとか考えたことなかったな… 勉強勉強…

f:id:takakudakei:20181129005549j:plain

for文とeachの違いってなんなん?

最近コードレビューをしていて、for文を使っているコードを読んだときに、「Rubyだったらeach使いなよ」とレビューしてました。

Rubyだったらeach。お決まりのように考えていたのですが…なんで?

違い

結論から言うと、for文は配列の要素を受け取る変数、for文の中で作成したローカル変数がfor文の外でも扱うことができるということ

each文

numbers = [1, 2, 3, 4]
sum = 0

numbers.each do |n|
  sum += n
  sumsum = sum += n
end

irb(main):014:0> sum
=> 10

irb(main):025:0> sumsum
NameError: undefined local variable or method `sumsum' for main:Object
    from (irb):25
    from /Users/kei/.rbenv/versions/2.4.1/bin/irb:11:in `<main>'

for文

numbers = [1, 2, 3, 4]
sum = 0

for n in numbers
  sum += n
  sumsum = sum += n
end

irb(main):016:0> n
=> 4
irb(main):017:0> sum
=> 10
irb(main):018:0> sumsum
=> 10

for文の外でも使えてる!

なぜかも説明できないのに「そういうもんだから」っていうのはだめだなぁ…と感じました。もっと勉強しよ。

f:id:takakudakei:20181129005549j:plain

do...end と {} の違い

do...end と {} の違い

基本的にはどっちを使っても結果は同じ。

違いは、 do...end よりも {} のほうが

結合度が強い

どういうことか?

配列のdeleteメソッドの例

a = [1, 2, 3]

a.delete(100)
=> 0

a.delete(100) do
  'できない'
end
=> "できない"

ブロックを渡さない時は指定した値が見つからないとnilが返る

ブロックを渡すと指定した値が見つからない時はブロックの戻り値が戻り値となる

Ruby は引数の()を省略することができる

a.delete 100 do
  'できない'
end
=> "できない"

これは動く

a.delete 100 { 'できない' }
=> syntax error, unexpected '{', expecting end-of-input

結合度が強いとはこういうことらしい

a.delete 100 ではなく 100 { 'できない' } と解釈される

このように引数付きのメソッド呼び出しで{}をブロックとして使う場合は、メソッド引数の()を省略することができない

  • Ruby2.4.0, 2.4.1はRuby側の不具合でエラーが出ない。

普段 {} のほうがワンライナーで書けるーくらいしか思ってなくて、何が違うのかなんて考えたこともなかった…

ブロックローカル変数

ブロックローカル変数とは?

あまり使う機会はない。というか使わないと思う。

だけどもまたRuby勉強し直してて初めて知ったことなのでめも。

ブロック引数を;で区切り、続けて変数を宣言すると、ブロック内でのみ有効な独立した変数を扱うことができる

numbers = [1, 2, 3, 4]
sum = 0
# ブロック外のsumとは別物の変数sumを用意する
numbers.each do |n; sum|
  sum = 10
  sum += n
  p sum
end

=>

11
12
13
14

# ブロック内で使ったsumとブロック外のsumは別物なのでブロック外sumは変化なし

sum => 0

変数に適切な名前をつければブロックローカル変数なんて使わなそう…

チェリー本読んでるけどまだまだ知らないこと多い。