クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

新版チェリー本を読んで今更ながら知ったこと〜主にmap(&:upcase)の話〜

新版チェリー本を読んで今更ながら知ったこと〜主にmap(&:upcase)の話〜

こんにちは、エンジニアの神山です。

Rubyを書いてる人であれば一度は聞いたことあるチェリー本こと プロを目指す人のためのRuby入門 。その新版が昨年12月に出ました。

先日読んでたところ、今まで知らなかったことや忘れていたことがいくつか発掘されたので、記事にしてみました。ちなみに僕はRubyを触って6年になります。

先にチェリー本のリンクを貼っておきます。とても素晴らしい本なので、ぜひ読んでみてください。

プロを目指す人のためのRuby入門[改訂2版] 言語仕様からテスト駆動開発デバッグ技法まで (Software Design plus)

www.amazon.co.jp

map(&:upcase) の仕組み

これを知れた喜びからこの記事を書いたと言っても過言ではありません。(わりとみんな知っているのだろうか。。)

皆さんは、①の書き方が②のようにも書ける理由をご存知でしょうか。

# ①
['abc', 'def'].map { |string| string.upcase }

# ②
['abc', 'def'].map(&:upcase)

これには Procオブジェクトが関わっています。ただ単純な話ではないので細かく説明していきます。 ※ブロックやProcオブジェクトに関してはWEB上にたくさん情報があるので簡単な解説にとどめます。

ブロックとは

ブロックとは処理(のかたまり)です。先程のコードで言うと、 { |string| string.upcase } です。言語化すると 文字列を大文字にする処理 になります。 Rubyを書いてる人であれば eachmap などのメソッドでよく使いますね。

ちなみにブロックを扱うメソッドを定義するにはこのように書きます。(いろんな書き方があるので下は一例です。)

# 文字列に何らかの処理をするメソッド
def string_ex(string, &block)
  puts '文字列に処理を施します'
  block.call(string)
end

> string_ex('hoge') { |s| s.upcase }
文字列に処理を施します
=> "HOGE"

> string_ex('hoge') { |s| "!!!#{s}!!!" }
文字列に処理を施します
=> "!!!hoge!!!" 

# 組み合わせて使うこともできます。
> string_ex(string_ex('hoge') { |s| "!!!#{s}!!!" }) { |s| s.upcase }
文字列に処理を施します
文字列に処理を施します
=> "!!!HOGE!!!"

このようにブロックを扱うメソッドを定義すると、状況に応じて好きな処理を渡すことできます。 ※ブロックを引数として受け取るには & が必要です。

Procオブジェクト とは

Procオブジェクトとはブロックのような処理をオブジェクト化したものです。先程の例をProcオブジェクトを使って書き直してみます。

# 小文字を大文字にする処理
upcase_proc = Proc.new { |s| s.upcase }

# 文字列を強調させる処理
emphasis_proc = Proc.new { |s| "!!!#{s}!!!" }

> string_ex('hoge', &upcase_proc)
文字列に処理を施します
=> "HOGE"

> string_ex('hoge', &emphasis_proc)
文字列に処理を施します
=> "!!!hoge!!!"

> string_ex(string_ex('hoge', &upcase_proc), &emphasis_proc)
文字列に処理を施します
文字列に処理を施します
=> "!!!HOGE!!!"

ブロックで渡したときとの違いとして、Procオブジェクトを先程のメソッドに渡すには & をつける必要があります。

mapにProcオブジェクトを渡す

今までの流れからわかるように、 &proc_object のように書けば map にProcオブジェクトを渡すことができます。

upcase_proc = Proc.new { |s| s.upcase }

> ['abc', 'def'].map(&upcase_proc)
=> ["ABC", "DEF"]

ここで補足ですが & はメソッドにProcオブジェクトを渡す前に to_proc メソッドを利用してProcオブジェクトに変換を行っております。 今回で言うと、 map に渡す前に実は upcase_proc.to_proc を行っております。ただProcオブジェクトに to_proc しても変わらないので今回は処理に変化はありません。

シンボルをProcオブジェクトに変換

「そんなことできるの?」って思う人もいるかも知れません。僕も初めて知りました。 たとえば今まで例に使っていた upcase_proc は以下のように定義できます。

> upcase_proc = :upcase.to_proc
=> #<Proc:0x000055b7ae696728(&:upcase) (lambda)>

> string_ex('hoge', &upcase_proc)
文字列に処理を施します
=> "HOGE"

まとめ

改めて大事なことを列挙します。

  • ブロックはProcオブジェクトとしてオブジェクト化できる
  • Procオブジェクトはブロックを扱うメソッドに対して、 & を使うことでブロックのように渡せる
  • & は引数をメソッドに渡す前に引数に to_proc を行う
  • シンボルは to_proc でProcオブジェクト化される

つまり map(&:upcase)map { |string| string.upcase } と同義になるのは、以下のような説明になります。

  • :upcase& によってProcオブジェクトに変換(内部で .to_proc される)
  • また & によってProcオブジェクトをブロックと同じように map に渡される

正規表現のキャプチャに名前をつけられる

正規表現のキャプチャは度々使ってましたが、名前をつけられることは初めて知りました。

正規表現のキャプチャとは

() を使うことでマッチした値を利用することができます。

> text = '2022年5月10日'
=> "2022年5月10日"

> result = /(\d+)(\d+)(\d+)/.match(text)
=> #<MatchData "2022年5月10日" 1:"2022" 2:"5" 3:"10">

# キャプチャできる
> result[1]
=> "2022"
> result[2]
=> "5"
> result[3]
=> "10"

# ちなみに組み込み変数を使うこともできる
> $1
=> "2022"
> $2
=> "5"
> $3
> $~
=> #<MatchData "2022年5月10日" 1:"2022" 2:"5" 3:"10">

ただ result[1] だと実際何を表す値かわからないですよね。 そこでキャプチャに名前をつけることができます。

> text = '2022年5月10日'
=> "2022年5月10日"

> result = /(?<year>\d+)(?<month>\d+)(?<day>\d+)/.match(text)
=> #<MatchData "2022年5月10日" 1:"2022" 2:"5" 3:"10">

# キャプチャできる
> result[:year]
=> "2022"
> result[:month]
=> "5"
> result[:day]
=> "10"

ちなみに =~ で書くとキャプチャ名をそのままローカル変数として使えます。今まで組み込み変数を使ってたので良いことを知れました。

> /(?<year>\d+)(?<month>\d+)(?<day>\d+)/ =~ text
=> 0

> year
=> "2022"
> month
=> "5"
> day
=> "10"

1行パターンマッチ

パターンマッチはRuby3.0で正式に導入されました。ただまだ実務で使ったことがなく知らないことばかりです。 その中でも1行で書くことができる1行パターンマッチはとても便利そうです。

> full_name = { first: 'taro', last: 'kitabeppu' }
> full_name in { first: String, last: String }
=> true

> full_name = { hoge: 'taro', last: 'jiro' }
>  full_name in { first: String, last: String }
=> false

> full_name = { first: 1, last: 'hoge' }
>  full_name in { first: String, last: String }
=> false

番号指定パラメータ

ブロックパラメータを明示的に指定せずに、番号指定パラメータを使って書くことができます。ただ分かりづらいのでそこまで利用頻度はなさそうです。

> [1, 2, 3].map { _1.to_s }
=> ["1", "2", "3"]

全範囲オブジェクト

下のように書くと全範囲を表す範囲オブジェクトになるそうです。

nil..nil
..nil
nil..

> (nil..nil).cover?(1000000000000000000000000000000000000000000000)
=> true

まとめ

社内で共有したところ「これは知ってた」「これは知らなかった」などの声があり、意外に自分が当たり前だと思っていることも他の人は知らなかったりすることに気づきました。こういう共有はとても有効だと思うので、今後も続けていきたいです。

改めて再度、本の紹介をして終わります。意外な気付きがあったりするのでぜひ読んでみてください。

プロを目指す人のためのRuby入門[改訂2版] 言語仕様からテスト駆動開発デバッグ技法まで (Software Design plus)

www.amazon.co.jp

クラウドワークスに興味のある方へ

株式会社クラウドワークスでは、共によりよい社会を築いてくれる仲間を募集しています! ぜひご応募ください!

crowdworks.co.jp

クラウドワークスへ入社して半年のエンジニアが入社経緯とペアプロを語る

クラウドワークスへ入社して半年のエンジニアが入社経緯とペアプロを語る

2021年11月に株式会社クラウドワークスへ入社した小西です。エンジニアとしてクラウドテックというハイクラスなエンジニア・デザイナーを中心とした人材と企業をマッチングするエージェントサービスを開発しています。

クラウドワークスに入社するまでの経緯や入社後に始めたペアプロのことなどをお伝えしていこうと思います。

目次

  • 目次
  • 入社経緯
  • 入社してどうだったか
  • ペアプロの提案
    • ペアプロの良いところ
      • 技術スキルや業務知識などのノウハウが共有できる
      • コードレビューの前にアドバイスが受けられる
      • チームの醸成になる
  • ペアプロで変えていく組織
  • クラウドワークスに興味のある方へ

入社経緯

入社までのエンジニア歴は4年ほどで、Web系の受託開発を行うスタートアップ企業で3年近く働いた後にフリーランスとして約1年Web開発の仕事を受けていました。フリーランスでの仕事を辞めて入社までの期間が2ヶ月ほど空いているのですが、この期間自分のやるべきことが分からなくなり、東日本を放浪[^1]しながらこれから何をすべきかをずっと考えていました。4年ほど仕事をしてきて得るものは沢山ありましたが、得たものを使って社会に還元できているのか、自分のやっていることが世の中の役に立っているのかを考えると正直自信を持って「できてます」とは言えませんでした。クラウドワークスに入社を決めるまで、なぜその仕事をしているのかと言う問いに対して自分の中に解がなかったために、やるべきことが分からなかったのだと思います。

世の中の役に立っていると言えるには、世の中になければならないものへ貢献している必要があります。例えば、電気や水道などの生活インフラは人が生活するうえでなくてはなりません。放浪中に転職活動もしていたのですが、世の中にとって意味のある仕事がしたいという思いのもと、社会のインフラになっているような会社を探していました。その中で出会ったのがクラウドワークスです。

続きを読む

「HTML解体新書」HTMLのこれからと向き合うための本

アイキャッチ:「HTML解体新書」HTMLのこれからと向き合うための本

「HTMLの前提についてはざっと知った、ステップアップできるHTMLの勉強がしたい」「人に勧められるHTMLにまつわる書籍はあるだろうか」「令和でHTMLを学ぶならこの1冊、というものがほしい」―――そうした人々のニーズを叶えてくれる書籍が販売された。

その名も「HTML解体新書」だ。

本ブログ記事は、レビュアーとして関わり本書を読んだ@okuto_oyamaによる感想と、HTMLのこれからについて考えていることをまとめたものである。

本の内容については、著者によるブログ記事にまとまってあるのでそちらを参考にしてもらいたい。

creators.bengo4.com

続きを読む

AWS AthenaでALBのログを過去分も検索する

こんにちは。SREチームの田中 (@kangaechu)です。リモートワークで座ってばかりの生活に危機感を感じ、昨年11月頃からランニングを始めました。最初は1キロ走っただけでヒイヒイ言っていたのですが、最近は10キロくらい走れるようになりました。運動は嫌いな方だったのですが、走るのが楽しいと思えるようになったのが一番の収穫かなと思っています。

今回はALB(Application Load Balancer)のログ検索について紹介します。

3行で説明するよ

  • AWSの公式ドキュメントの通りAthenaの設定をするとALBの過去ログが検索できない
  • 正規表現をいい感じにすることで過去ログも検索できるようになった
  • Athenaのテーブル作成、Terraformでできるよ
続きを読む

フロントエンド開発体験向上のために VRT を導入してみた

アイキャッチ:フロントエンド開発体験向上のために VRT を導入してみた

はじめに

こんにちは、ジャンヌチームです。 前回のVue3 移行記事に引き続き、フロントエンド周辺の改善をおこなっています。 今回は開発体験の向上を目的とした、 VRT の導入の記録となる記事になります。

VRT について

VRT とは Visual Regression Testing のことで、画像による回帰テスト、つまり画像の変更をテストするものです。

クラウドワークスでは Vue3 移行に伴い、ほぼ全ての Vue.js コンポーネントで Storybook を定義しています。 この Storybook 定義を用いて、Storyshot による DOM レベルの自動回帰テストを行っています。

しかし CSS の変更におけるビジュアルテストは担保できていなかったため、VRT を導入することにしました。

続きを読む

© 2016 CrowdWorks, Inc., All rights reserved.