
rubyでのproc
http://d.hatena.ne.jp/shunsuk/20090101/1230816826
ここのサイトで解説されていることなんですけど,
「同じblockを何度も使いたいときがあります。そんなときに再利用するためのコードがProcです。blockとProcの唯一の違いは、blockは保存できないということです。Procについて見てみましょう。」
とあるのですが,なにをもってblockは保存できないといってるのでしょうか?
「lambdaはメソッドと同じように振る舞いますから、returnを使うことができます。この意味の違いは、下の例に現れます。」
の下にサンプルプログラムがあると思いますが,
puts generic_return(Proc.new { |x, y| x + 2; y + 2 })
puts generic_return(Proc.new { |x, y| [x + 2, y + 2] })
この2行ではエラー処理が行われず,なんらかの出力がされています,
これはなぜでしょうか?メソッドの中にreturnがある限りエラー処理が起こると思っているのですが・・・
あと,あまり関係ない質問になるかもしれませんが
array.iterate!(method(:square))
このような記述のとき,squareは関数名ということはわかるのですが,
:(コロン)これはなにを指すのでしょうか?
よろしくおねがいします.
No.2ベストアンサー
- 回答日時:
> なにをもってblockは保存できないといってるのでしょうか?
Lambdaの項の最初に“Procを2通りの方法で使ってきました。直接渡す方法と、変数に保存する方法です。”という記述があります。
保存とは変数に保存するということの様です。Procのインスタンスは変数に保存して使い回しができますが、ブロックはできないということではないでしょうか。
> この2行ではエラー処理が行われず,なんらかの出力がされています,
> これはなぜでしょうか?メソッドの中にreturnがある限りエラー処理が起こると思っているのですが・・・
メソッドの中ではなくて、Proc.new{ }の中にreturnがある場合ですね。
この中にreturnがあると、そのProcが定義されたレベルからのreturnを行おうとするようです、このサンプルだとProcはプログラムのトップレベルで定義されているので、トップレベルからreturnしようとしてエラーになっている様です。
要するにProcを使用する場合はreturnを使うな、returnを使う場合はlambdaを使えということではないでしょうか。
No.4
- 回答日時:
はまりやすいところですが、proc組み込み関数はくせ者です。
Ruby1.8ではproc組み込み関数は、lambdaを返します。
Proc.new{。。。。} # => procオブジェクト
lambda {。。。。} # => lambdaオブジェクト(クラスはProc)
proc {。。。。} # => lambdaオブジェクト(クラスはProc)!!!!!注意
Ruby1.9ではproc組み込み関数の機能が変更されています。
Proc.new{。。。。} # => procオブジェクト
lambda {。。。。} # => lambdaオブジェクト(クラスはProc)
proc {。。。。} # => procオブジェクト
#3の方は、Ruby1.9をお使いと思われます。
No.3
- 回答日時:
#解説は他の方に任せてサンプルのみ。
#ブロックを返す単純なメソッドを定義
def make_proc1(&b)
b
end
#別の例
def make_proc2
proc
end
#ブロック保存もどきが作れる。
p= make_proc1{puts "proc test"}
p.call
p= make_proc2{puts "proc test"}
p.call
#が以下のように直接は保存できない。(blockは保存できないにあたる?)
p = {puts "proc test"}
return #トップレベルのreturn(※1)は戻り先が無いのでLocalJumpError
p = proc{ p "proc test";return}#トップレベルのreturn(※1)を含むproc作成。
p.call #これもップレベルのreturn(※1)と一緒LocalJumpError
def proc_test
return #メソッド内のreturn(※2)。nilを返してproc_testを終了する。
p "fin proc_test" #これは実行されない。
end
def proc_test
p = proc{ p "proc test";return}#proc_testのreturn(※2)と一緒。
p.call #proc_testのreturn(※2)と一緒なのでLocalJumpErrorはおきない。
p "fin proc_test" #これは実行されない。
end
def proc_test(b)
b.call #トップレベルのreturn(※1)を含むprocの場合、戻り先が無いのでLocalJumpError
p "fin proc_test" #これは実行されない。
end
proc_test(proc{ p "proc test";return})#トップレベルでreturn(※1)を含むprocを渡す。
def sub_proc
#sub_procからのreturnだが、呼び出す際にはsub_procは
#すでに終了しているのでエラー。
proc{ p "proc test";return}
end
proc_test sub_proc
この回答への補足
#!/usr/bin/ruby
p = proc{ p "proc test";return}#トップレベルのreturn(※1)を含むproc作成。
p.call #これもップレベルのreturn(※1)と一緒LocalJumpError
これを実行したところ,
"proc test"
と出力されました.
#!/usr/bin/ruby
def proc_test
p = proc{ p "proc test";return}#proc_testのreturn(※2)と一緒。
p.call #proc_testのreturn(※2)と一緒なのでLocalJumpErrorはおきない。
p "fin proc_test" #これは実行されない。
end
としたところ,proc testが出力されそうですが,なにも出力されませんでした.
#!/usr/bin/ruby
p = proc{ p "proc test";return}#トップレベルのreturn(※1)を含むproc作成。
p.call #これもップレベルのreturn(※1)と一緒LocalJumpError
これを実行したところ,
"proc test"
と出力されました.
#!/usr/bin/ruby
def proc_test(b)
b.call #トップレベルのreturn(※1)を含むprocの場合、戻り先が無いのでLocalJumpError
p "fin proc_test" #これは実行されない。
end
proc_test(proc{ p "proc test";return})#トップレベルでreturn(※1)を含むprocを渡す。
これを実行したところ,
"proc test"
"fin proc_test"
と出力されました.
#!/usr/bin/ruby
def proc_test(b)
b.call #トップレベルのreturn(※1)を含むprocの場合、戻り先が無いのでLocalJumpError
p "fin proc_test" #これは実行されない。
end
def sub_proc
#sub_procからのreturnだが、呼び出す際にはsub_procは
#すでに終了しているのでエラー。
proc{ p "proc test";return}
end
proc_test sub_proc
これを実行したところ,
"proc test"
"fin proc_test"
と出力されました.
LocalJumpErrorrubyのバージョンにもよるのでしょうか?特にエラーは出力されませんでした.
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
また,実行時には
ruby -W test.rb
と警告をつけて実行しています.
No.1
- 回答日時:
>なにをもってblockは保存できないといってるのでしょうか?
原文は見てませんが、翻訳を見る限り、この文脈で「保存」とはどういう意味なのか定義されてません。従って意味不明の文章です。
あえて想像すると、「変数に直接代入できない」という意味ではないでしょうか。別の所に書いてありますが、呼び出され側のメソッドで、&が付いた仮引数で受け取ることは出来るので、変数には代入できるのですが、直接ではありません。
a = {|x| x*2}
ということは出来ないので。
>これはなぜでしょうか?メソッドの中にreturnがある限りエラー処理が起こると思っているのですが・・・
何故かと問われても、「正しいプログラムだから」としか言いようがないです。逆に何故「エラー処理が起こる」と思ったのでしょうか?
>このような記述のとき,squareは関数名ということはわかるのですが,:(コロン)これはなにを指すのでしょうか?
単に square と書くと、square というメソッドを呼び出してその結果を表します。
ここでは、呼び出さずにメソッドの名前を伝えたいわけです。:square はシンボルというもので、簡単には説明できませんので、理解できるまでは『「書き換えられず部分取り出しも出来ない文字列」のようなもの』と思っておけば良いです。実際、
array.iterate!(method("square"))
と書いても同じ結果です。文字列よりシンボルの方が処理効率が良く、またシンボルしか書けないところもあります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
1、Rstudioで回帰直線を求める...
-
(再質問)エクセルのマクロボ...
-
パソコンのスクリーンセーバー...
-
pandasでsqlite3にテーブル作成...
-
WIN11にオフイスを複数入れるこ...
-
回復ドライブとインストールメ...
-
英数字を含む文字列(0-9,A-Z)...
-
VBScriptでExcel(2019)上のデー...
-
C++のCreateFile関数で、ASCII...
-
Ruby require ライブラリー
-
ruby OpenURI::Meta
-
ruby while式
-
ruby loopメソッド 変数(再喝)
-
ruby 配列
-
ruby loopメソッド 変数
-
ruby クラス・オブジェクト・イ...
-
ルビー言語 ライブラリー 追記
-
ruby raise句
-
ruby begin句
-
ruby ensure句
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Access2000にExcel2000のデータ...
-
railsチュートリアル5章の演習
-
Ruby 同じ名前のメソッド
-
timesの使いどころ
-
Rubyのクラス
-
CloseとQuitについて
-
ハッシュ(単語数を数える) た...
-
再帰に関する質問です。
-
rubyでのproc
-
ブロックつきメソッドやyield文...
-
「arg」は何の略?
-
get() と find() の違いについて
-
エラー「メソッドまたはデータ...
-
教えてください。vb5.0
-
エクセルVBA オートフィルタで...
-
実行時エラー450:引数の数が一...
-
クラス名やモジュール名の競合...
-
VBAで型が一致しないエラー(バ...
-
HSTLやSSTL等のI/Oピン
-
What class are you in? には何...
おすすめ情報