Rubyにおけるblockの本質を理解する
Rubyの特徴は2つあります. Moduleは、マルチ継承の問題を優雅に解決する Blockブロック呼び出し この2つの特性はいずれもRubyオリジナルではないが、明らかにこの2つの特性を適切に発揮し、最近のC#もそれらを改善して支持している.
しかし、この2つの特性こそ、RubyBeginnerを常に困惑させている.これも私が勉强の过程の中でよく出会う问题で、私はBlockの牛を解く过程を列挙して、自分の过程に対して1つの记录を作ると思っています.
前言
Rubyでは、いわゆる「Block」は多種あるが、Blockはコンピュータ科学理論の中で「過程」と呼ばれている.
仕方がない、ruby設計哲学の一つは、現実世界と似ていて、一つの問題はいくつかの異なる方法で解決することができる.
では、より少ない符号化のために、より「RubyLike」の符号化のために、始めましょう.
スタート
1.それは何ですか.
(Blockがどうなっているのかまだ分からない場合は、RubyProgrammingの第2版のホの本をかじることをお勧めします)
まず一つのニーズから始めましょう
配列がソートをサポートし、使用できる例を見てみましょう.
では、使い方を見てみましょう.
blockを用いるソートというsort法が強いことがわかる.わかりやすいです.
Cに詳しいなら、Cの関数ポインタに似ているような感じがするかもしれませんが、確かに、私が始めたときもそうでしたが、よく考えてみると、Cの関数ポインタの使用は本当にリスクが高く、複雑でいろいろなタイプの変換があります.
関数式プログラミングを知っていれば、このblockはいわゆる「高次関数」パラメータのように感じられますが、うーん、確かに、ほとんどの場合、それを
メソッドのパラメータでよい、このパラメータは式ではなく、完全なコードであることができる.
2.どのような形式がありますか.
(リード、block、Proc、lamba、Methodって聞いたでしょ?)
次に、それらの形式を見てみましょう.
block:
blockはrubyが最もよく使う文法の一つであり、最も「RubyLike」でもあるが、その使い方は以上簡単に紹介した.
私たちは自分の方法を実現するblockを見ました.
so easyは、yieldというキーワードを使用して、いわゆるメソッドパラメータをサポートすることができます.blockパラメータをサポートしたい場合は、以下のこともできます.
Proc:
blockの同胞としてrubyの発展の過程で現れ、その出現の目的は簡単で、
ブロックを多重化できる
ニーズを見てみましょう.
2つの配列arr 1,arr 2を長さで並べ替えてください.Procを利用してこのように書くことができます.
簡単ですね.パラメータに&この記号が付いていることに気づくことができます.&の目的も簡単です.ruby解釈器に教えてください.「ああ、これは一般的なパラメータではなく、「高次関数」です.
また、細心の注意を払う人は、私がProcを書くのはいつもP大文字で、blockはいつも小文字であることに気づくことができます.これはなぜですか.
1.Procは実際にRubyに内蔵されているクラスであり、blockは私たちがコードブロックと呼ぶ略記にすぎない.
2.Procインスタンスはメソッドパラメータとして渡すことができ、blockは匿名のProcに似ている.
ここで、blockとProcの基本的な違いは明らかになりました.重要な特性を追加します.
1.blockとProcのジャンプコードはnextを使用します(returnではなく、次に言うlambdaは正反対です)
2.blockとProcはいずれもメソッドで1回しか受け入れられない.すなわち、メソッドは複数のblockまたはProcを得ることができない(心配しないで、松本行弘も2つのblockを使う必要はないと言った)(また、実際にはhashまたは配列を渡して2つのProcインスタンスを得ることができる)
3.戻り値、すなわち最後の文の戻り値がある.(私はrubyのすべての式の戻り値をよく知らなかったので、はっきりした学生が討論を歓迎しています)
lambda:
Lambdaを使ってrubyをもっと面白くして、外国人の話でfunnyと呼んで、私たちをもっと困惑させて、こんなに多くの形式をして何をしますか?
まずlambda自体についてお話ししますが、rubyは多くの言語を混ぜ合わせた特徴であり、lambdaは例外ではなくlisp自体から得られた命名であることがわかります.Lambdaはみんな聞いたことがあるようです.ええ、ギリシャのアルファベットです.λまぁ(11番目)
私が言いたいのは、それはただのキーワードで、ある意味を表すために、ruby言語の神が設計したのです.(特にありませんが…)
由来は分かりましたが、使用を見てみましょう.
上記のProcの例に準じて、lambdaの例を書き続けます.
うん、違いない?
ええ、ここは本当に違いません.ああ、それは何をしますか.
実はsizeを使うことができますcode_lambda.classを見て、Procの対象でもあることに気づきましたか?
ええと、どうしたんですか.実はあなたが&伝達を使うとき、rubyはすべてProcに変換してあげましたが、このProcオブジェクトは彼Procオブジェクトではなく、違いがあります.
もう1つの例を見てみましょう
うっかりするとsortがいくつかのパラメータを伝えることができることが分からなかった.
こう書きました(もし、kが1つ増えたら):
うん、異常を報告した.
Procのコードで走ってくれないか?大丈夫です.
では、最初の違いをまとめます.
1.lambdaはコード伝達パラメータをチェックし始めたが、Procは手伝ってくれなかった.
Procがチェックしない以上、何を送ってくれますか?すぐに検証できます.
うん、空の値.そうですね.△予想通りでしょう.
続けてみると、コードブロックから戻って実行を続けたい場合があります.どうすればいいですか.
returnを試してみましょう.
一例
出力はまったく違いますね.では、2つ目の違いがあります.
2.lambdaではreturnを使用するが、Proc/blockでは使用できない.
では、何を使って返すか、そのホの本を読んでから知っておくべきで、nextを使えばいいです.
では、少し印象を深めて、質問をします.Procがreturnを使用するのはなぜLocalJumpErrorに戻ったのでしょうか.
実は簡単で、Procは当時コードブロックを定義したコンテキスト環境、すなわち閉パッケージを保持しています.ここでLocalJumpErrorを返すのは、私たちが定義したコンテキストが再びreturnできないためです.
言い換えれば、Procのreturnは実際にはprocの上位環境に直接returnされている.
ここにはテクニックがあります
Procで高次ジャンプを実現
次のようになります.
Procとlambdaの違いを完全に理解しました.
さて、区別はやっと終わりましたが、どうやって使えばいいのでしょうか.
1.lambdaはもっと完全な方法のようで、匿名にすぎず、そのパラメータは「神」にチェックされ、returnの時は自分の「方法」から戻る.
2.Procはただ1つの過程で、頼りなくて、パラメータが間違っている時ただ捨てられてあるいはランダムに1つのnilを拾ってあなたにあげて、returnの時原始の父の環境から戻ります.
rubyの発展過程によると、lambdaはblock/Procより少し遅く出てきて、lambdaの文法はもちろんprocよりもっと良い(私を驚かせない角度から)が、procは消えていない原因は、互換性である一方で、その「魔法」と少し関係がある.
だから、使うならblockが優先的に使われるべきで、それはもっと簡潔です.
オブジェクト伝達が必要な場合は、lambdaをもっと使うことをお勧めします.驚くことはありません.パラメータをチェックすることもできますが、喜んでいませんか.
Procの高次ジャンプの使い方に出会ったら、分かるといいですね.
ここを見ると、基本的にこのまとめの栄養は何もありません.あなたも心に理解しているような気がします.しかし、私はやはり実際の状況を明らかにしたいと思っています.
LambdaはProcの一例にすぎません...(rubyの勉強の深さが高すぎる原因はここにあるので、興味のある人は研究したり検討したりしてもいいです)
最後に、lambdaがこのように方法(Method)に似ている以上、簡単にMethodを言います.
Methodもrubyのクラスで、その名前は私たちにすべてを教えてくれました.例を見てください.
Methodクラスはlambdaによく似ています名前以外は...
さあ、私は料理を休んでもいいです.あなたたちも今まで...
しかし、この2つの特性こそ、RubyBeginnerを常に困惑させている.これも私が勉强の过程の中でよく出会う问题で、私はBlockの牛を解く过程を列挙して、自分の过程に対して1つの记录を作ると思っています.
前言
Rubyでは、いわゆる「Block」は多種あるが、Blockはコンピュータ科学理論の中で「過程」と呼ばれている.
仕方がない、ruby設計哲学の一つは、現実世界と似ていて、一つの問題はいくつかの異なる方法で解決することができる.
では、より少ない符号化のために、より「RubyLike」の符号化のために、始めましょう.
スタート
1.それは何ですか.
(Blockがどうなっているのかまだ分からない場合は、RubyProgrammingの第2版のホの本をかじることをお勧めします)
まず一つのニーズから始めましょう
配列がソートをサポートし、使用できる例を見てみましょう.
では、使い方を見てみましょう.
#
["p","bc","de"].sort do |i,j|
i.size <=> j.size
end
#
["p","bc","de"].sort do |i,j|
i <=> j
end
blockを用いるソートというsort法が強いことがわかる.わかりやすいです.
Cに詳しいなら、Cの関数ポインタに似ているような感じがするかもしれませんが、確かに、私が始めたときもそうでしたが、よく考えてみると、Cの関数ポインタの使用は本当にリスクが高く、複雑でいろいろなタイプの変換があります.
関数式プログラミングを知っていれば、このblockはいわゆる「高次関数」パラメータのように感じられますが、うーん、確かに、ほとんどの場合、それを
メソッドのパラメータでよい、このパラメータは式ではなく、完全なコードであることができる.
2.どのような形式がありますか.
(リード、block、Proc、lamba、Methodって聞いたでしょ?)
次に、それらの形式を見てみましょう.
block:
blockはrubyが最もよく使う文法の一つであり、最も「RubyLike」でもあるが、その使い方は以上簡単に紹介した.
私たちは自分の方法を実現するblockを見ました.
def method_with_block
yield
end
method_with_block do puts 'call me' end
so easyは、yieldというキーワードを使用して、いわゆるメソッドパラメータをサポートすることができます.blockパラメータをサポートしたい場合は、以下のこともできます.
def method_with_block_parameter
n = 'windy'
yield(n)
end
method_with_block do |i| puts 'call me' + i end
Proc:
blockの同胞としてrubyの発展の過程で現れ、その出現の目的は簡単で、
ブロックを多重化できる
ニーズを見てみましょう.
2つの配列arr 1,arr 2を長さで並べ替えてください.Procを利用してこのように書くことができます.
size_code = Proc.new do |i,j|
i.size <=> j.size
end
arr1.sort(&size_code)
arr2.sort(&size_code)
簡単ですね.パラメータに&この記号が付いていることに気づくことができます.&の目的も簡単です.ruby解釈器に教えてください.「ああ、これは一般的なパラメータではなく、「高次関数」です.
また、細心の注意を払う人は、私がProcを書くのはいつもP大文字で、blockはいつも小文字であることに気づくことができます.これはなぜですか.
1.Procは実際にRubyに内蔵されているクラスであり、blockは私たちがコードブロックと呼ぶ略記にすぎない.
2.Procインスタンスはメソッドパラメータとして渡すことができ、blockは匿名のProcに似ている.
ここで、blockとProcの基本的な違いは明らかになりました.重要な特性を追加します.
1.blockとProcのジャンプコードはnextを使用します(returnではなく、次に言うlambdaは正反対です)
2.blockとProcはいずれもメソッドで1回しか受け入れられない.すなわち、メソッドは複数のblockまたはProcを得ることができない(心配しないで、松本行弘も2つのblockを使う必要はないと言った)(また、実際にはhashまたは配列を渡して2つのProcインスタンスを得ることができる)
3.戻り値、すなわち最後の文の戻り値がある.(私はrubyのすべての式の戻り値をよく知らなかったので、はっきりした学生が討論を歓迎しています)
lambda:
Lambdaを使ってrubyをもっと面白くして、外国人の話でfunnyと呼んで、私たちをもっと困惑させて、こんなに多くの形式をして何をしますか?
まずlambda自体についてお話ししますが、rubyは多くの言語を混ぜ合わせた特徴であり、lambdaは例外ではなくlisp自体から得られた命名であることがわかります.Lambdaはみんな聞いたことがあるようです.ええ、ギリシャのアルファベットです.λまぁ(11番目)
私が言いたいのは、それはただのキーワードで、ある意味を表すために、ruby言語の神が設計したのです.(特にありませんが…)
由来は分かりましたが、使用を見てみましょう.
上記のProcの例に準じて、lambdaの例を書き続けます.
size_code_lambda = lambda do |i,j|
i.size <=> j.size
end
arr1.sort(&size_code_lambda)
arr2.sort(&size_code_lambda)
うん、違いない?
ええ、ここは本当に違いません.ああ、それは何をしますか.
実はsizeを使うことができますcode_lambda.classを見て、Procの対象でもあることに気づきましたか?
ええと、どうしたんですか.実はあなたが&伝達を使うとき、rubyはすべてProcに変換してあげましたが、このProcオブジェクトは彼Procオブジェクトではなく、違いがあります.
もう1つの例を見てみましょう
うっかりするとsortがいくつかのパラメータを伝えることができることが分からなかった.
こう書きました(もし、kが1つ増えたら):
size_code_lambda = lambda do |i,j,k|
i.size <=> j.size
end
arr1.sort(&size_code_lambda)
うん、異常を報告した.
Procのコードで走ってくれないか?大丈夫です.
では、最初の違いをまとめます.
1.lambdaはコード伝達パラメータをチェックし始めたが、Procは手伝ってくれなかった.
Procがチェックしない以上、何を送ってくれますか?すぐに検証できます.
size_code = Proc.new do |i,j,k|
puts k,k.class
i.size <=> j.size
end
arr1.sort(&size_code)
# nil, NilClass
うん、空の値.そうですね.△予想通りでしょう.
続けてみると、コードブロックから戻って実行を続けたい場合があります.どうすればいいですか.
returnを試してみましょう.
一例
def methods(&code)
code.call
puts 'methods end'
end
a_proc = Proc.new { puts 'call proc' ; return ; }
a_lambda = lambda { puts 'call lambda' ; return ; }
methods(&a_proc) # => unexpected return (LocalJumpError)
methods(&a_lambda) # => methods end
出力はまったく違いますね.では、2つ目の違いがあります.
2.lambdaではreturnを使用するが、Proc/blockでは使用できない.
では、何を使って返すか、そのホの本を読んでから知っておくべきで、nextを使えばいいです.
では、少し印象を深めて、質問をします.Procがreturnを使用するのはなぜLocalJumpErrorに戻ったのでしょうか.
実は簡単で、Procは当時コードブロックを定義したコンテキスト環境、すなわち閉パッケージを保持しています.ここでLocalJumpErrorを返すのは、私たちが定義したコンテキストが再びreturnできないためです.
言い換えれば、Procのreturnは実際にはprocの上位環境に直接returnされている.
ここにはテクニックがあります
Procで高次ジャンプを実現
次のようになります.
def go
a = Proc.new do
puts 'proc'
return
end
methods(&a)
puts 'end go'
end
def methods(&a)
puts 'methods'
a.call
puts 'end methods'
end
go
# =>methods
# proc
Procとlambdaの違いを完全に理解しました.
さて、区別はやっと終わりましたが、どうやって使えばいいのでしょうか.
1.lambdaはもっと完全な方法のようで、匿名にすぎず、そのパラメータは「神」にチェックされ、returnの時は自分の「方法」から戻る.
2.Procはただ1つの過程で、頼りなくて、パラメータが間違っている時ただ捨てられてあるいはランダムに1つのnilを拾ってあなたにあげて、returnの時原始の父の環境から戻ります.
rubyの発展過程によると、lambdaはblock/Procより少し遅く出てきて、lambdaの文法はもちろんprocよりもっと良い(私を驚かせない角度から)が、procは消えていない原因は、互換性である一方で、その「魔法」と少し関係がある.
だから、使うならblockが優先的に使われるべきで、それはもっと簡潔です.
オブジェクト伝達が必要な場合は、lambdaをもっと使うことをお勧めします.驚くことはありません.パラメータをチェックすることもできますが、喜んでいませんか.
Procの高次ジャンプの使い方に出会ったら、分かるといいですね.
ここを見ると、基本的にこのまとめの栄養は何もありません.あなたも心に理解しているような気がします.しかし、私はやはり実際の状況を明らかにしたいと思っています.
LambdaはProcの一例にすぎません...(rubyの勉強の深さが高すぎる原因はここにあるので、興味のある人は研究したり検討したりしてもいいです)
最後に、lambdaがこのように方法(Method)に似ている以上、簡単にMethodを言います.
Methodもrubyのクラスで、その名前は私たちにすべてを教えてくれました.例を見てください.
def a
puts 'a'
end
puts method(:a).class
method(:a).call
# => Method
# a
Methodクラスはlambdaによく似ています名前以外は...
さあ、私は料理を休んでもいいです.あなたたちも今まで...