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で質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) python flask から fastapiへの移行時のエラー対処 1 2023/02/05 12:26
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- UNIX・Linux linuxサーバーのキャッシュをクリアするコマンドを実行したい。 5 2023/01/24 14:52
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- その他(プログラミング・Web制作) pythonリストの特定の値を表示htmlで表示できない 2 2022/05/14 05:48
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
- Java java 引数 戻り値のあるメソッド 3 2023/02/12 06:23
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- Visual Basic(VBA) vbaエクセルマクロについて あるデータを作成し、デスクトップに.xlsx形式で保存するマクロを作成 2 2023/03/02 18:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
あせんうぶり言語
-
(再質問)エクセルのマクロボ...
-
パソコンのスクリーンセーバー...
-
これらは書誌情報だと思うので...
-
pythonエラー
-
英数字を含む文字列(0-9,A-Z)...
-
Beautiful Soupのインストール...
-
VBScriptでExcel(2019)上のデー...
-
100万件越えCSVから条件を満た...
-
rubyでじゃんけんのプログラム...
-
Accessで文字列のバイト数読み込み
-
ビーリアルのユーザー名を変え...
-
教えてください
-
Ruby on railsをrails sで立ち...
-
C言語の入力した文字を反転させ...
-
符号付整数の演算結果を答えよ ...
-
実行時エラー450:引数の数が一...
-
情報の表現。()内がどうしても...
-
pythonのerrorコード
-
三項でたとえば交換って
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Rubyの超初心者です。「戻り値r...
-
【BrowseForFolderでデスクトッ...
-
python return 関数
-
【引数と戻り値の違い】 はじめ...
-
CloseとQuitについて
-
再帰に関する質問です。
-
ブロックつきメソッドやyield文...
-
railsチュートリアル5章の演習
-
ぱいソン
-
rubyでのproc
-
【Ruby】 文法的に何が悪いの...
-
Rubyにインクリメンタル演算子...
-
ハッシュ(単語数を数える) た...
-
Ruby 自作メソッドのブロック...
-
レコードセットオブジェクトの...
-
Ruby Fileクラスについて
-
timesの使いどころ
-
ジェネレーターとはなんですか?
-
Unixのwcコマンドの簡易版ですが
-
自作したメソッド・・・こんな...
おすすめ情報