Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Os fechamentos são chamadas que capturam variáveis do ambiente de encerramento. Podem ser criados fechamentos de função e operação. Um fechamento de operação pode ser criado dentro de uma função, mas só pode ser aplicado em uma operação.
Q# tem dois mecanismos para criar fechamentos: expressões lambda e aplicação parcial.
Expressões lambda
Uma expressão lambda cria uma função ou operação anônima.
A sintaxe básica é uma tupla de símbolo para ligar os parâmetros, uma seta (-> para uma função e => para uma operação) e uma expressão para avaliar quando aplicada.
// Function that captures 'x':
y -> x + y
// Operation that captures 'qubit':
deg => Rx(deg * PI() / 180.0, qubit)
// Function that captures nothing:
(x, y) -> x + y
Parâmetros
Os parâmetros são vinculados usando uma tupla de símbolo que é idêntica ao lado esquerdo de uma instrução de declaração de variável . O tipo de tupla do parâmetro está implícito. Não há suporte para anotações de tipo; Se a inferência de tipo falhar, talvez seja necessário criar uma declaração chamável de nível superior e usar o aplicativo parcial.
Variáveis de captura mutáveis
Variáveis mutáveis não podem ser capturadas. Se você só precisar capturar o valor de uma variável mutável no instante em que a expressão lambda for criada, poderá criar uma cópia imutável:
// ERROR: 'variable' cannot be captured.
mutable variable = 1;
let f = () -> variable;
// OK.
let value = variable;
let g = () -> value;
Características
As características de uma operação anônima são inferidas com base nas aplicações da lambda. Se o lambda é usado com uma aplicação functor, ou em um contexto que espera uma característica, o lambda é então inferido para ter essa característica. Por exemplo:
operation NoOp(q : Qubit) : Unit is Adj {}
operation Main() : Unit {
use q = Qubit();
let foo = () => NoOp(q);
foo(); // Has type Unit => Unit with no characteristics
let bar = () => NoOp(q);
Adjoint bar(); // Has type Unit => Unit is Adj
}
Se você precisar de características diferentes para uma operação lambda do que foi inferido, você precisará criar uma declaração de operação de nível superior.
Aplicação parcial
A aplicação parcial é uma abreviatura conveniente para aplicar alguns, mas não todos, dos argumentos de um chamável.
A sintaxe é a mesma que uma expressão de chamada, mas os argumentos não aplicados são substituídos por _.
Conceitualmente, a aplicação parcial é equivalente a uma expressão lambda que captura os argumentos aplicados e aceita os argumentos não aplicados como parâmetros.
Por exemplo, dado que f é uma função e o é uma operação, e a variável capturada x é imutável:
| Aplicação parcial | Expressão lambda |
|---|---|
f(x, _) |
a -> f(x, a) |
o(x, _) |
a => o(x, a) |
f(_, (1, _)) |
(a, b) -> f(a, (1, b))[^1] |
f((_, _, x), (1, _)) |
((a, b), c) -> f((a, b, x), (1, c)) |
Variáveis de captura mutáveis
Ao contrário das expressões lambda, o aplicativo parcial pode capturar automaticamente uma cópia do valor de uma variável mutável:
mutable variable = 1;
let f = Foo(variable, _);
Isso é equivalente à seguinte expressão lambda:
mutable variable = 1;
let value = variable;
let f = x -> Foo(value, x);
[^1]: O parâmetro tupla é estritamente escrito (a, (b)), mas (b) é equivalente a b.