Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Specifications/Language/2_Statements/CallStatements.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Call Statements

Call statements are a very important part of any programming language. While operation and function calls, much like [partial applications](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/PartialApplication.md#partial-application), can be used as an expression anywhere as long as the returned value is of a suitable type, they can also be used as statements if they return `Unit`.
Call statements are a very important part of any programming language. While operation and function calls can be used as an expression anywhere as long as the returned value is of a suitable type, they can also be used as statements if they return `Unit`.
The usefulness of calling functions in this form primarily lays in debugging, whereas such operation calls are one of the most common constructs in any Q# program. At the same time, operations can only be called from within other operations and not from within functions (for context, see also [this section](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/4_TypeSystem/QuantumDataTypes.md#qubits)).

With callables being first-class values,
Expand Down
118 changes: 118 additions & 0 deletions Specifications/Language/3_Expressions/Closures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Closures

Closures are callables that capture variables from the enclosing environment.
Both function and operation closures can be created.
An operation closure can be created inside a function, but it can only be applied in an operation.

Q# has two mechanisms for creating closures: lambda expressions and partial application.

## Lambda Expressions

A lambda expression creates an anonymous function or operation.
The basic syntax is a symbol tuple to bind the parameters, an arrow (`->` for a function and `=>` for an operation), and an expression to evaluate when applied.

```qsharp
// 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
```

### Parameters

Parameters are bound using a symbol tuple that is identical to the left-hand side of a [variable declaration statement](../2_Statements/VariableDeclarationsAndReassignments.md).
The type of the parameter tuple is implicit.
Type annotations are not supported; if type inference fails, you may need to create a top-level callable declaration and use partial application instead.

### Mutable Capture Variables

Mutable variables cannot be captured.
If you only need to capture the value of a mutable variable at the instant the lambda expression is created, you can create an immutable copy:

```qsharp
// ERROR: 'variable' cannot be captured.
mutable variable = 1;
let f = () -> variable;

// OK.
let value = variable;
let g = () -> value;
```

### Characteristics

The characteristics of an anonymous operation are inferred based on the body of the lambda expression.
For example:

```qsharp
// Has type Unit => Unit is Adj + Ctl because X is known to be Adj + Ctl.
() => X(q)


// Has type Unit => Result because M is neither Adj nor Ctl.
() => M(q)
```

Because of limitations in characteristics inference, this is based only on type information known at the point where the lambda expression occurs.
For example:

```qsharp
let foo = op => op(q);
foo(X);
```

`foo` is inferred to have the following type based on both the body of the lambda and the type of `X`:

```qsharp
(Qubit => Unit is Adj + Ctl) => Unit
```

But the most specific type that `foo` could have is:

```qsharp
(Qubit => Unit is Adj + Ctl) => Unit is Adj + Ctl
```

If you need different characteristics for an operation lambda than what was inferred, you will need to create a top-level operation declaration instead.

## Partial Application

Partial application is a convenient shorthand for applying some, but not all, of a callable's arguments.
The syntax is the same as a call expression, but unapplied arguments are replaced with `_`.
Conceptually, partial application is equivalent to a lambda expression that captures the applied arguments and takes in the unapplied arguments as parameters.

For example, given that `f` is a function and `o` is an operation, and the captured variable `x` is immutable:

| Partial application | Lambda expression |
| ---------------------- | ------------------------------------- |
| `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))` |

### Mutable Capture Variables

Unlike lambda expressions, partial application can automatically capture a copy of the value of a mutable variable:

```qsharp
mutable variable = 1;
let f = Foo(variable, _);
```

This is equivalent to the following lambda expression:

```qsharp
mutable variable = 1;
let value = variable;
let f = x -> Foo(value, x);
```

---

← [Back to Index](https://github.com/microsoft/qsharp-language/tree/main/Specifications/Language#index)

[^1]: The parameter tuple is strictly written `(a, (b))`, but [`(b)` is equivalent to `b`](../4_TypeSystem/SingletonTupleEquivalence.md).
14 changes: 0 additions & 14 deletions Specifications/Language/3_Expressions/PartialApplication.md

This file was deleted.

9 changes: 2 additions & 7 deletions Specifications/Language/3_Expressions/ValueLiterals.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,9 @@ Values of a [user defined type](https://github.com/microsoft/qsharp-language/tre

For instance, if `IntPair` has two items of type `Int`, then `IntPair(2, 3)` creates a new instance by invoking the default constructor.

## Operation Literals

No literals exist for values of [operation type](https://github.com/microsoft/qsharp-language/tree/main/Specifications/Language/4_TypeSystem#available-types); operations have to be [declared](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/1_ProgramStructure/3_CallableDeclarations.md#callable-declarations) on a global scope and new operations can be constructed locally using [partial application](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/PartialApplication.md#partial-application).

## Function Literals

No literals exist for values of [function type](https://github.com/microsoft/qsharp-language/tree/main/Specifications/Language/4_TypeSystem#available-types); functions have to be [declared](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/1_ProgramStructure/3_CallableDeclarations.md#callable-declarations) on a global scope and new functions can be constructed locally using [partial application](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/PartialApplication.md#partial-application).
## Operation and Function Literals

Anonymous operations and functions can be created using a [lambda expression](Closures.md#lambda-expressions).

## Default Values

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function Pow<'T>(op : 'T => Unit, pow : Int) : 'T => Unit {
}
```

They can be instantiated based on a type parametrized definition such as, e.g., the [type parametrized](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/4_TypeSystem/TypeParameterizations.md#type-parameterizations) function `Pow` above, and they can be [partially applied](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/PartialApplication.md#partial-application) as done in Line 2 in the example.
They can be instantiated based on a type parametrized definition such as, e.g., the [type parametrized](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/4_TypeSystem/TypeParameterizations.md#type-parameterizations) function `Pow` above, and they can be [partially applied](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/Closures.md#partial-application) as done in Line 2 in the example.


## Operation Characteristics
Expand Down
2 changes: 1 addition & 1 deletion Specifications/Language/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Q# implements programs in terms of statements and expressions, much like classic
1. [Arithmetic Expressions](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/ArithmeticExpressions.md#arithmetic-expressions)
1. [Concatenations](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/Concatentation.md#concatenation)
1. [Modifiers \& Combinators](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/PrecedenceAndAssociativity.md#modifiers-and-combinators)
1. [Partial Application](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/PartialApplication.md#partial-application)
1. [Closures](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/Closures.md)
1. [Functor Application](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/FunctorApplication.md#functor-application)
1. [Item Access Expressions](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/ItemAccessExpressions.md#item-access)
1. [Contextual Expressions](https://github.com/microsoft/qsharp-language/blob/main/Specifications/Language/3_Expressions/ContextualExpressions.md#contextual-and-omitted-expressions)
Expand Down