Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los cierres son invocables que capturan variables del entorno envolvente. Se pueden crear cierres de función y operación. Se puede crear un cierre de operación dentro de una función, pero solo se puede aplicar en una operación.
Q# tiene dos mecanismos para crear cierres: expresiones lambda y aplicación parcial.
Expresiones lambda
Una expresión lambda crea una función o operación anónimas.
La sintaxis básica es una tupla de símbolos para enlazar los parámetros, una flecha (->
para una función y =>
para una operación) y una expresión que se va a evaluar cuando se aplica.
// 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
Los parámetros se enlazan mediante una tupla de símbolos idéntica al lado izquierdo de una instrucción de declaración de variable de . El tipo de la tupla del parámetro es implícito. No se admiten anotaciones de tipo; Si se produce un error en la inferencia de tipos, es posible que tenga que crear una declaración invocable de nivel superior y usar la aplicación parcial en su lugar.
Variables de captura mutable
No se pueden capturar variables mutables. Si solo necesita capturar el valor de una variable mutable al instante en que se crea la expresión lambda, puede crear una copia inmutable:
// ERROR: 'variable' cannot be captured.
mutable variable = 1;
let f = () -> variable;
// OK.
let value = variable;
let g = () -> value;
Características
Las características de una operación anónima se deducen en función de las aplicaciones de la expresión lambda. Si la expresión lambda se usa con una aplicación de functor o en un contexto que espera una característica, se deduce que la expresión lambda tiene esa característica. Por ejemplo:
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
}
Si necesita características diferentes para una expresión lambda de operación a la que se infirió, deberá crear en su lugar una declaración de operación de nivel superior.
Aplicación parcial
La aplicación parcial es una abreviatura conveniente para aplicar algunos argumentos, pero no todos, a los que se puede llamar.
La sintaxis es la misma que una expresión de llamada, pero los argumentos sin aplicar se reemplazan por _
.
Conceptualmente, la aplicación parcial es equivalente a una expresión lambda que captura los argumentos aplicados y toma los argumentos no aplicados como parámetros.
Por ejemplo, dado que f
es una función y o
es una operación, y la variable capturada x
es inmutable:
Aplicación parcial | Expresión 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)) |
Variables de captura mutable
A diferencia de las expresiones lambda, la aplicación parcial puede capturar automáticamente una copia del valor de una variable mutable:
mutable variable = 1;
let f = Foo(variable, _);
Esto equivale a la siguiente expresión lambda:
mutable variable = 1;
let value = variable;
let f = x -> Foo(value, x);
[^1]: La tupla de parámetro se escribe estrictamente (a, (b))
, pero (b)
es equivalente a b
.