RubyのブロックとProc
こんばんは。ろんです。最近は冷え込みますね…
暖房器具はオイルヒーター派です。
今日はRubyの強力なお友達、ブロックについて紹介します。
並列してるProcとはブロックをオブジェクト化したもので、まずはブロックの理解から初めてこうと思います。
Rubyのブロックとは?何に使えるものなのか
私の解釈では、参照する事ができて、メンバの更新が可能なメソッドの事。
Javaでいう参照渡しが可能な関数の事を指すようです。
引用先のページではモジュールパターンのような応用が可能とありますが、私はこれを
observer patternと解釈しました。
かろてんさんのデザインパターンの説明がわかりやすいので、ぜひ読んでみてください。エモいという言葉は好きではないですが、マジでエモかった…(褒め言葉)
モジュールパターンについての説明は結城浩さんのデザパタ本が個人的におすすめです。ちょっとヒく厚さなんですが、1週間に1章とかでもいいので読んでおくと設計系の話を見かけた時に抵抗なく入れるし、何より説明が具体的でわかりやすいですよ。
物に例えるところがイメージしやすくていいですよね…
それでRubyのブロックとはなんなのか
だいぶ話が私の設計思想に傾いてしまいましたが、文脈を戻してブロックの説明です。
そう、ブロックはcontext(文脈)が大事なのですよ!!
def block_sample arg
arg + yield
end
p block_sample 3 { 2 }
block_sampleの返り値は何になると思いますか?
正解は5です。
argについての説明は割愛しますが、yieldはブロックの処理結果を呼び出しているメソッドです。
あっけない感じがしますね?しかし、このブロックにはちょっとしたクセがあります。
- ブロックで宣言した変数は外部から参照することができない( 束縛 )
- 他のメンバの代入に影響を及ぼす
ブロック評価の順番とローカル変数への影響
def return_calculate_add val1, val2
val1 + yield(5 + val2)
end
p return_calculate_add(3, 4){|x + y| x + y }
これで下記のうちどの値が返ってくるでしょう?
1. 9 2. 12 3. 15
正解は2の12です。
まずval1, val2それぞれに代入されて
def return_calculate_add val1, val2
val1 + yield(5 + val2) # val1=3, val2=4
end
次にブロックの評価がされます。
return_calculate_add(3, 4){|x + y| x + y } # x=5, y=4
最後にメソッドの中に戻ってval1と足し算してあげれば完了です。
こちらはどうでしょうか?
def return_calculate_add val1, val2
val1 + yield(5 + val2)
end
x = 10
p return_calculate_add(3, 4){|x + y| x + y }
惑わされないでくださいね。スコープの外に定義されている変数なのでブロックでは参照されません。答えは同じです。
def return_calculate_add val1, val2
val1 + yield(5 + val2)
end
x = 10
p return_calculate_add(x, 4){|x + y| x+= x + y }
答えは19です。
def return_calculate_add(val1, val2)
val1 + yield(val2, 5)
end
z = 10
p return_calculate_add(z, 4){|x, y| z+= x + y }
p z
問題はこれで最後です。*1に答えを記載しましたのでチャレンジしてみてください。
これが正解出来たら今日の晩ご飯にデザートをつけてもいいと思います。
応用できそうなこと
共有スコープを使いたい時に便利そうですよ。
よくインスタンス変数にお世話になっていますが、こんなメソッドの書き方ができそうです。
# ケーキの数を計算してくれるメソッド
def cakes_calc cakes, &const
p plain_text = "カップケーキが#{cakes + const.call}個"
end
sample_constructor = Proc.new {
result, pledged_cakes = 0, [3, 8, 1]
bought_cakes, made_cakes = 0
bought_cakes = 1000 / 120
made_cakes = 1
pledged_cakes.each do |c|
result += c
if c == pledged_cakes.last
result += bought_cakes + made_cakes
end
end
result
}
cakes_calc(12, &sample_constructor) # => "カップケーキが33個"
ブロック内ではスコープ外に参照を置いていませんが、もちろん参照は可能です。
これならメンバが再代入される危機も薄れて一石二鳥!
うーん。命名がビミョー。
本日は作り置きのハンバーグを食べ損ねたので、美味しい肉バルの紹介です。
虎ノ門界隈にしてはランチのコスパが~1500円程度とお手頃です。
赤身は臭みがなくて程よく柔らかく、ジューシーなのでわさび醤油ソースでいただけるランチメニューがおすすめ。
同僚の方が食べていたグラタンにonされているハンバーグも私の拳くらいあるのでした。また行きたい。
引用・参考 :
( ありがとうございます )
答えは29, 19
*1:こちら
Rubyの変数とスコープについて
寒いですね。ろんです。
最近ヒットした自炊メニューはハンバーグです。
今晩はいい加減写経も飽きてきてしまったので、Rubyの言語仕様について触れてみようと思います。今回は変数とスコープについて、Javaをなんとなく触れていた時期と比べてメモっておきます。
Rubyのメンバとは
Rubyの変数にはJavaのようにデータタイプの修飾子はなく、暗黙的に代入時のデータを解釈してくれるようです。
また、Rubyの定数は再代入が可能です。ここもJavaとは違うところですね。
そもそもClassが定数として扱われるという性質があり、
メイン宣言(メソッド、メンバを呼び出すフィールドのようなもの)が関数として扱われるJavaとはこちらも違ったところです。同じMVCで設計されているといっても、呼び出し方も違いますね。
その為か、クラスをimportやinterface, overrideなどで多重継承するというよりも、クラスの再オープンや継承が単一クラスの継承で実行されます。
これでは不便なので、mix-inという機能でいろんな機能追加などが可能になるのですが、今回は割愛します。
Rubyの変数たち
勉強を始めた序盤でかなり惑わされ、曖昧になってしまっている部分ですが、
先ほど述べたようにRubyの変数はメンバ宣言が必要なく、修飾子も定義されていません。
主に下記の5つで成り立っています。
ローカル変数 … 代入された位置からブロックもしくはメソッドの終端まで
$グローバル変数 … どこからでも参照ができる
@@クラス変数 … クラスインスタンスから参照が可能
定数 … クラス・モジュール内(内側での宣言も含む)、宣言元を継承もしくはincludeしているモジュール内、外部からはモジュール演算子と宣言されているクラスを表記することでアクセスが可能
ローカル変数はスクリプト言語を学び始めた私にとっては珍妙で、『プログラムは上から下へ降りる挙動をする』という感覚があった為、同一ファイル内で定義されている変数を呼び出そうとした時にName Errorなんて返ってくるので、勝手に理不尽さを感じていました。
こんなにメンバ宣言してしまって…、GCしなくて大丈夫なのかしら…とJavaのコンパイル待ちをしていた時期と比べて開発速度が段違いだった衝撃を思い出します。
話が脱線しましたが、Rubyでのローカル変数はメソッド内での宣言が必要になります。(attr_accesorなどのコンストラクタ類はのぞいて)
グローバル変数は使った事がないのですが、どこからでも参照・更新が出来てしまうという危うさは変わらないようです。freezeを使って再代入出来なくするという手も使えるようですが、各所で話を聞く限り、特異メソッドで定義してあげる方が精神衛生上良さそうな気がします。
インスタンス変数は属しているフィールドのインスタンス内でのみ生存ができるイメージです。正直、メソッドと同名のviewにこやつらが生存している原理に違和感を持ったままですが…
宣言していないのに参照したらどうなるの?
これはクラス変数・定数、一部ローカル変数について例外が発生します。
条件分岐で代入が実行されなかった場合は宣言のみ適用され、後続で参照する事が可能です。
過去に条件の考慮漏れで代入されていないインスタンス変数を参照してしまい、データを作るミスを犯してしまった事があります。
何を集計してどんな出力を行うかにもよるのですが、集計or抽出されたデータにnilが予想される場合、どのような設計を行うのかなあと考えるところです。ログに焼き付けるようにしておくのがベターなのですかね…やった事ないですが。
Javaであれば即刻 IndexOutOfBoundsExceptionやらNullPointerExceptionを投げてくれるので、良い意味で常に危機感と隣り合わせでコーディング出来ますよね。
所感
配列やらを決め打ちでやらずに柔軟に対応してくれるのが助かる!(Vectorもいるけど…)
でもたまにnilに泣かされてます
技術の話ばかりではつまらないので、推しの飲食店をメモることにします。
今回は代々木のトスカーナさん。
コスパ良しでもちもちボロネーゼが評判です。個人的には同じくらいもちもちで焼きたてさっくりなピザ推しなのですが。
ドルチェのオレンジとチョコレートのアイス(料理名失念)も口当たりが良くてサイコーでした。
マサカリお待ちしてまーす🐕
WebCampでRailsの勉強をしたので紹介する
はじめまして。ろんです。
もともと福祉系の仕事をしていて、縁あって今はエンジニアの仕事をしています。
(正確には、次の会社を探しているところですが)
今回は自分がエンジニアという肩書きでお仕事をしていく導入でお世話になったプログラミングスクールと、そこで学ぶ経緯について書いていこうと思います。
もともとSEとして都内のSIerに入社、1ヶ月ほどJavaを書く機会がありました。
ひとりで送り込まれた現場では、テスター・詳細設計から降りてくるコードの実装などを担当していましたが、速度感のある開発がしたいという気持ちが抑えきれず、1年程でこの会社を退職しました。
無職期間は手当を貰いながらPHPやPython, Ruby, Swiftなどを学習系のサイトで学んだり、
ローカルで動くアプリを作ったりしていました。
運よくpaizaのやっている転職支援サービスで未経験可の求人を発見し、面接、入職に到るまではslim, SaSS, jQuery、基本的なRailsの取り扱い方をRails tutorialなどで勉強していました。
しかし、外注として一緒に働いていた先輩に「このままのスキル感じゃヤバイ」
と脅された事、個人的にも「このままでは死ぬ(将来継続して収入を手に入れるスキルが身につく気配がない)」と感じていた為に、バックエンドのお仕事もしていきたいと考えました。そこで、働きながら学べるプログラミングスクールです。
とりあえずやりたいことはないけどエンジニアという肩書きでお金は稼いでいきたい
その足がかりとして
・アプリケーションを作成する上で基本的な概念MVCを人に説明できるようになる
・フロントエンドの最低限(SaSS / CSS, html)の自分のコードを根拠を持って人に説明できるようになる
・この先のことはわからないけどとりあえずRailsでアプリを作れるようになりたい
みたいな目標をもやっと掲げてスクール巡りをしました。
結論から言うと、最初の会社と比べて給料は7万円ほどあげてもらいましたし、
フロントエンドで採用されたものの、要件に挙げられた機能を丸ごと担当するレベルになりました。つまりは未経験・仕様も全くわからん状態からフロントとバックエンドを兼任しました。
WebCampの良かったところ
・メンターが優しい、無駄に絡んでこない、質問には教室が閉まるギリギリまで答えてくれる(私のようなコミュ障に適した距離感)
・とにかくメンターが寛大、業務的な悩み・技術的な興味の問題にも、カリキュラム外であるに関わらず、時間を割いて話を聞いてくださっていました
・自習スペースが綺麗、眺めが良いので精神衛生上良い(私が居たのは渋谷の神南の方でした)
・カリキュラムにめちゃくちゃ難題が含まれない
・コードはGithubで公開してもいいらしい
・受講生もギラギラしていなくて平和そうな雰囲気
私はアプリケーションの制作コース(Ruby on Rails)をTwitterの社長割で利用しました。3ヶ月コースで300k…だったかな。社長割の説明については割愛します。
身につくスキルはhtml, css, RailsのMVC設計と仕組みについて。
コスパ的にはトントン、手に職の先行投資なのでお安いくらいかと思います。
他のスクールだとプレゼンも込みなガチガチのハードモードなカリキュラムもありますが、WebCampは心理的な負荷が少なく、教室も綺麗でとても通いやすかったです。
WebCampで習得した技術など
・DBの基本的なセットアップ( mysql )、 環境構築系
・モデルとコントローラの違い、バリデーションの設定、複数モデルの絡んだフォームの作成
・インデントが綺麗になった
・なんとなくで使っていたcssプロパティの説明ができる( floatは要素自体が浮くので後続の要素を巻き込まない為にはclearfixが必要、みたいな )
・スマートデバイス対応する根気
業務でその後伸ばしていった技術・実装( 一部 )など
・ erbを使ってcontrollerたたいたり、API叩いたりして動的なフォーム追加や勘定計算するフォームのバグフィックス( 非同期処理系の実装 )
・DragDropというgemを拡張してインプットからpdf, csv, xlsxファイルなどをアップロードできるようにする( gemの公式ドキュメントを読み込む根気 )
・スコープをモデルに作って抜きたいデータの設定、ransackというgemを拡張してオリジナルの検索スコープを作る( 多対多の子モデルの条件で親モデルを検索かける感じ、SQL周りの勉強 )
この他に新規モデルの追加とか、決済周りのステータス変更とか重いとこもやってました。ちなみにこの現場にはロジックレビューできる人はいませんでした。
一緒に提携して仕事している外注さんに聞きながら頑張ってました。
頑張ってくれるメンターさんと1つの作品の完成までやり抜くことで、そんな辛い状況でも生き抜くガッツが育まれます。
他にも言いたかったこと
・エンジニアは基本的に質問しない生き物( 自分の意見や不明点が明瞭でなければ誰も話を聞いてくれない世界 )
・メンターに憧れて講師になりたいなら少なくとも2年は現場で仕事してみて欲しい
・インフラトップの社長はイケメン