質問

多くの人が単語 closure block を同じ意味で使用していることがわかりました。これらの人々のほとんどは、彼らが話していることを説明できません。

一部のJavaプログラマー(非常に高価なコンサルタント会社のプログラマーも含む)は、匿名の内部クラスについて「ブロック」と呼んでいます。および「クロージャ」 -しかし、私はこれが真実ではないことを知っています。 (変数が定義されているメソッドのスコープから可変変数を渡すことはできません...)

探しているのは:

  • 正確なコンピューターサイエンスブロックの定義
  • 正確なコンピューターサイエンス閉鎖の定義
  • および 2つの違いの明確化

リンク、記事、または書籍を参照してくださいください。

役に立ちましたか?

解決

ブロックはステートメントと宣言で構成できるコードの一部にすぎませんが、クロージャは本当のファーストクラスのオブジェクトであり、値としてブロックを持つ変数。

主な違いは、ブロックは単に命令を一緒にグループ化するだけです(たとえば、 while ステートメントの本文)、クロージャーは実行可能なコードを含む変数です。

通常、クロージャーがある場合、それを関数にパラメーターとして渡し、それを切り上げ、切り下げ、そして主に呼び出すことができます!

Closure c = { println 'Hello!' }
/* now you have an object that contains code */
c.call()

もちろん、クロージャーはより強力で、変数であり、オブジェクトのカスタム動作を定義するために使用できます(通常、プログラミングではインターフェイスまたは他のOOPアプローチを使用する必要がありました)。

クロージャは、その機能がそれ自体の内部で行うことを含む機能と考えることができます。

ブロックは、変数のスコープを許可するため便利です。通常、スコープ内で変数を定義すると、外側の定義を問題なくオーバーライドでき、ブロックの実行中に新しい定義が存在します。

for (int i = 0; i < 10; ++i)
{
     int t = i*2;
     printf("%d\r\n", t);
}

t はブロック( for ステートメントの本文)内で定義され、そのブロック内で持続します。

他のヒント

ブロックは構文的なものです-ステートメントの論理単位( closure よりも scope に関連しています)。

if (Condition) {
    // Block here 
} 
else {
    // Another block
}

クロージャは、匿名の関数またはクラスに関連しています-匿名(関数)オブジェクト、環境(変数を含む)にバインドされたコードの一部。

def foo() {
   var x = 0
   return () => { x += 1; return x }
}

ここで foo はクロージャを返します!ローカル変数 x は、 foo が終了した後もクロージャを通じて保持され、返された匿名関数の呼び出しを通じてインクリメントできます。

val counter = foo()
print counter() // Returns 2
print counter() // Return 3

Rubyでブロックとクロージャーが同様に処理されるのはRubyだけであることに注意してください。これは、Rubyがブロックと呼ぶものは クロージャーだからです

(1..10).each do |x|
    p x
end

-メソッドには、Rubyでは block と呼ばれるクロージャー関数(パラメーターxを取得)が渡されます。

複数の定義を伴う用語があり、通常は一緒に見つかるために複数の異なるものが混同されるため、ここには多くの混乱があります。

最初に、「ブロック」があります。これは、たとえばループの本体など、ユニットを作成するコードの単なるチャンクです。言語に実際にブロックスコープがある場合、そのコードチャンク内にのみ存在する変数を定義できます。

第二に、値型として呼び出し可能なコードがあります。関数型言語では、これらは関数値です-「ファン」、「匿名関数」と呼ばれることもあります。 (関数は割り当てられた名前ではなく、値にあるため、それらを呼び出すために名前は必要ありません)、または「lambdas」 (教会のラムダ計算でそれらを作成するために使用される演算子から)。これらは「クロージャ」と呼ばれることもありますが、自動的に真のクロージャではありません。修飾するためには、作成を囲む字句スコープをカプセル化(「閉じる」)する必要があります。つまり、関数自体のスコープ外で定義された変数は、関数が呼び出されたときにいつでも使用できます。呼び出し元が参照変数の後にある場合でも、そうでなければ、参照変数は範囲外になり、そのストレージがリサイクルされます。

たとえば、次のJavascriptを検討してください:

function makeClosure() {
  var x = "Remember me!";
  return function() {
    return "x='" + x + "'";
  }
}

// console.log(x); 
// The above is an error; x is undefined
var f = makeClosure();
console.log(f());
// The above outputs a string that includes x as it existed when f was created.

変数 x は、関数 makeClosure の本体内でのみ定義されます。その定義以外では存在しません。 makeClosure を呼び出した後、その中で宣言された x は削除されます。そして、それは、ほとんどのコードの観点からです。ただし、 makeClosure によって返される関数は x が存在する間に宣言されているため、後で呼び出すときに引き続きアクセスできます。それは本当の閉鎖になります。

スコープを保持しないため、クロージャーではない関数値を持つことができます。部分的なクロージャーを持つこともできます。 PHPの関数値は、値の作成時にリストする必要がある特定の変数のみを保持します。

関数全体をまったく表さない呼び出し可能なコード値を持つこともできます。 Smalltalkはこれらを「ブロッククロージャー」と呼びますが、Rubyは「ブロッククロージャー」と呼びますが、多くのRubyistは単に「ブロック」と呼びます。 .. } または do ... end 構文。それらをラムダ(または「関数クロージャ」)と区別するのは、それらが新しい呼び出しレベルを導入しないことです。 ブロッククロージャーの本体のコードが return を呼び出す場合、ブロック自体ではなく、ブロッククロージャーが存在する外部の関数/メソッドから戻ります。

この動作は、R.D。Tennentが「対応原則」とラベル付けしたものを保存するために重要です。たとえば、Javascriptでは、これを置き換えることができます:

x=2
console.log(x)

これ:

(function(){x = 2;})();
console.log(x)

この例はあまり興味深いものではありませんが、プログラムの動作に影響を与えずにこの種の変換を行う機能は、機能的なリファクタリングにおいて重要な役割を果たします。しかし、ラムダを使用すると、 return ステートメントを埋め込むとすぐに、次の原則が成立しなくなります。

大声でひげを生やした人は、閉鎖とブロックについてこう言います:

http://martinfowler.com/bliki/Closure.html

ある時点で、彼はクロージャーはメソッドへの引数として渡すことができるブロックであると言います。

使用している用語は、最近Rubyで最も一般的に使用される ものですが、コンストラクトは以前Algol、Smalltalk、Schemeに登場していました。もしあれば、Ruby標準を引用します。

あなたの正確な質問に答えられるかどうかはわかりませんが、説明できます。既にご存知の方はおaびします...

def f &x
  yield
  x
end

def g
  y = "block"
  t = f { p "I'm a #{y}" }
  y = "closure"
  t
end

t = g
t.call

そして...

$ ruby exam.rb
"I'm a block"
"I'm a closure"
$ 

ブロックはメソッド呼び出しに添付された関数のような匿名のシーケンスです。 Ruby API全体で使用されています。無名関数を簡単に作成できるようにすると、あらゆる種類の機能に役立つことがわかります。

ただし、 f が戻ってから g が戻った後、 f から( > x )、次に g から( t として)。ここで、ブロックをもう一度呼び出します。繰り返しになりますが、 g()が返されていることに注意してください。しかし、ブロックは、もう存在しない関数インスタンス(およびスコープ)のローカル変数を参照していますか?!そして、 y ?の新しい値を取得しますか?!

クロージャーは、その語彙スコープで閉じられる関数のようなオブジェクトです。関数呼び出しインスタンスのローカル変数に非常に役立つdo-it-with-a-stackモデルを破壊するため、実装が非常に困難です。


1。 Rubyには、クロージャーのような関数オブジェクトのさまざまなフレーバーがあります。これはそのうちの1つです。

  

5

それは整数です。

  

Int workDaysInAWeek = 5

これは整数変数であり、別の整数に設定できます。 (状況によってその値を変更できない場合、定数と呼ばれる場合があります。)

上記の懸念数に対して、ブロックおよび閉鎖はアルゴリズムに関係します。また、それぞれ blocks closures の違いも上記と同等です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top