Pergunta

Descobri que muitas pessoas usam as palavras fechamento e bloco alternadamente. A maioria dessas pessoas não pode explicar o que está falando.

Alguns programadores Java (mesmo os de consultorias realmente caros) falam sobre classes internas anônimas como "blocos" e "fechamento" - mas eu sei que isso não é verdade. (Você não pode passar variáveis ??mutáveis ??no do âmbito de aplicação do método em que são definidos ...)

Eu estou procurando:

  • , a ciência da computação precisa definição de um bloco
  • , a ciência da computação precisa definição de um fechamento
  • e esclarecimentos sobre a diferença entre os dois.

Eu realmente gostaria de ver links, artigos ou livro referências sobre estes, por favor .

Foi útil?

Solução

Enquanto um bloco é apenas um pedaço de código que pode ser composto por declarações e declarações, mas nada mais, a fechamento é um verdadeiro objeto de primeira classe, uma verdadeira variável que tem um bloco como seu valor.

A principal diferença é que um bloco simplesmente grupos instruções juntas (por exemplo o corpo de um enquanto declaração), enquanto um fecho é uma variável que contém um código que pode ser executado.

Se você tem um fecho geralmente você pode passá-lo como um parâmetro para funções, currify e decurrify-lo, e, principalmente, chamá-lo!

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

Claro fechamentos são mais poderosos, eles são variáveis ??e podem ser usados ??para definir o comportamento personalizado de objetos (enquanto normalmente você tinha que usar Interfaces ou outro OOP abordagens de programação).

Você pode pensar em um fechamento como uma função que contém o que essa função faz dentro de si.

Os blocos são úteis porque permitem que o escopo de variáveis. Normalmente, quando você definir uma variável dentro de um escopo que você pode substituir as definições exteriores, sem quaisquer problemas e novas definições existirá apenas durante a execução do bloco.

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

t é definido dentro do bloco (o corpo da declaração for) e vai durar apenas dentro desse bloco.

Outras dicas

Um bloco é algo sintática -. A unidade lógica de declarações (mais relacionado com escopo do que fechamento )

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

Um fechamento está relacionada com funções anoymous ou classes -. Um anônimo (função) objeto, um pedaço de código que está vinculado a um ambiente (com as suas variáveis)

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

Aqui foo retorna um fecho! Os locais persiste variável x através do encerramento mesmo depois foo terminadas e podem ser incrementados através de chamadas da função anônima devolvidos.

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

Note que é apenas o Ruby em que bloco e fechamento são tratados da mesma forma desde que o Ruby chama bloco é um de fechamento:

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

each-método é passado uma função de fechamento (tendo um parâmetro x), que é chamado de bloco em Ruby.

Há muita confusão por aqui porque há um acordo com várias definições, e várias coisas distintas que são confundidas simplesmente porque eles são geralmente encontrados juntos.

Em primeiro lugar, temos "bloco". Isso é apenas um pedaço lexical de código que faz com que uma unidade - o corpo de um loop, por exemplo. Se o idioma realmente tem escopo de bloco, em seguida, variáveis ??podem ser definidas que só existem dentro desse pedaço de código.

Em segundo lugar, temos de código que pode ser chamado como um tipo de valor. Em linguagens funcionais, estes são valores da função - às vezes chamado de "divertimentos", "funções anônimas" (porque a função é encontrado no valor, não o nome do seu atribuído a, você não precisa de um nome para chamá-los), ou " lambdas"(do operador usado para criá-los em Lambda Cálculo da Igreja). Eles podem ser chamados de "fechamento", mas eles não são automaticamente verdadeiros encerramentos; a fim de qualificar, devem encapsular ( "close over") o escopo léxico em torno de sua criação - isto é, variáveis ??definidas fora do âmbito da própria função, mas no âmbito da sua definição ainda estão disponíveis sempre que a função é chamada, mesmo se o ponto de chamada é após a variável referenciada de outra forma teriam ido para fora do alcance e teve seu armazenamento reciclado.

Por exemplo, considere este 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.

O x variável é definida somente dentro do corpo da makeClosure função; fora dessa definição, ela não existe. Depois chamamos makeClosure, o x declarada dentro dele deve ser ido. E é, do ponto de vista da maior parte do código. Mas a função retornada por makeClosure foi declarado enquanto x existia, por isso ainda tem acesso a ele quando você chamá-lo mais tarde. Isso faz com que seja um verdadeiro fechamento.

Você pode ter os valores da função que não são encerramentos, porque não preservar escopo. Você também pode ter fechamentos parciais; os valores da função do PHP única preservar variáveis ??específicas que devem ser listados no tempo o valor é criado.

Você também pode ter valores de código que podem ser chamadas que não representam funções inteiras em tudo. Smalltalk chama esses "fechamentos em bloco", enquanto Rubi chama de "procs", embora muitos Rubistas apenas chamá-los de "blocos", porque eles são a versão reificada do que está criada pelo { ... } ou do ... end sintaxe . O que os torna diferentes lambdas (ou "fechamentos de função") é que eles não introduzir um novo nível de chamada. Se o código no corpo de um return invoca fecho bloco, que retorna a partir da função / método exterior existe o encerramento dentro de bloco, não apenas o próprio bloco.

Esse comportamento é fundamental para preservar o que R.D. Tennent rotulado o "princípio da correspondência", que afirma que você deve ser capaz de substituir qualquer código com uma função incorporada que contém esse código no corpo e chamou imediatamente. Por exemplo, em Javascript, você pode substituir o seguinte:

x=2
console.log(x)

com este:

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

Esse exemplo não é muito interessante, mas a capacidade de fazer esse tipo de transformação, sem afetar o comportamento do programa desempenha um papel fundamental na refatoração funcional. Mas com lambdas, assim que você tem incorporado declarações return, o princípio não se sustenta mais:

function foo1() {
  if (1) {
    return;
  }
  console.log("foo1: This should never run.")
}
foo1()
function foo2() {
  if (1) {
    (function() { return; })();
  }
  console.log("foo2: This should never run.")
}
foo2()

A segunda função é diferente do primeiro; o console.log é executada, porque o return só retorna da função anônima, não de foo2. Isso quebra o princípio de correspondência.

É por isso que Ruby tem duas procs e lambdas, mesmo que a distinção é uma fonte perene de confusão para os iniciantes. Ambos os procs e lambdas são objetos de Proc classe, mas eles se comportam de maneira diferente, como indicado acima: a return apenas retornos do corpo de um lambda, mas ele retorna a partir do método em torno de um proc

.
def test
  p = proc do return 1 end
  l = lambda do return 1 end
  r = l[]
  puts "Called l, got #{r}, still here."
  r = p[]
  puts "Called p, got #{r}, still here?"
end

O método test acima nunca vai chegar ao segundo puts, porque a invocação de p fará test para retornar imediatamente (com um valor de retorno de 1). Se Javascript teve fechamentos em bloco, você poderia fazer a mesma coisa, mas isso não acontece (embora haja uma proposta para adicioná-los).

A única alto, barbudo tem a dizer sobre Closures e Blocos:

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

Em um ponto, ele diz um fechamento é um bloco que pode ser passado como um argumento para um método.

Os termos que você está usando são mais comumente usados ?? juntos estes dias em Ruby, embora as construções anteriormente apareciam em Algol, Smalltalk, e Scheme. Eu citaria o padrão Ruby, se houvesse um.

Eu não tenho certeza se eu sou capaz de responder à sua pergunta exata, mas posso ilustrar. Minhas desculpas se você já sabe disso ...

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

E ...

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

Assim, um bloco é um anônimo função semelhante a seqüência de código anexado a uma chamada de método. É usado em todo o API Ruby. Quando você se torna mais fácil o suficiente para criar uma função anônima não é que eles são úteis para todos os tipos de coisas.

Mas note que, depois de f retornos, em seguida, retorna g, realizamos para o bloco, retornando-o de f (como x) e, em seguida, a partir g (como t). Agora chamamos o bloco de uma segunda vez. Mais uma vez, nota que g() voltou. Mas o bloco refere-se a uma variável local, em um exemplo de função (e escopo) que não existe qualquer mais ?! E torna-se o novo valor de y ?!

Assim, um fechamento é uma função semelhante objeto que é fechado sobre o seu alcance lexical. Eles são bastante desafiador para implementar, porque eles destroem o modelo do-it-com-a-pilha que é tão útil para as variáveis ??locais em casos de chamada de função.


1. Ruby tem vários sabores de fecho do tipo de função objectos; Este é apenas um deles.

5

Essa é uma inteira .

Int workDaysInAWeek = 5

Essa é uma variável inteira e pode ser ajustado para um diferente inteira . (Se as circunstâncias impedi-lo de modificar esse valor, pode ser chamado de um constante .)

Considerando que os números acima referem, blocos e fechamento preocupação algoritmos. A distinção entre blocos e fechos , respectivamente, também é equivalente ao anterior.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top