-
Notifications
You must be signed in to change notification settings - Fork 53
Add the concept of an rvalue #131
Description
One of the major pains of working with Q# is that a lot of slight variations on operations require special casing. For example, suppose I want to swap two registers if two LittleEndian registers are equal, and I have already written methods to prepare the equality result and do a swap conditioned on a control. Further assume I am trying to be efficient and want to avoid redundant recomputation of ancillae when uncomputation the equality result. Then I am basically forced to write this:
use control_holder = Qubit();
use temporary_ancillae = Qubit[n];
within {
init_equality_result(a, b, temporary_ancillae, control_holder);
} apply {
Controlled swap_registers([control_holder], (c, d))
}
What I would like to write instead is this:
if a == b {
swap(c, d);
}
but that's perhaps a bit ambitious so in this issue I will settle for suggesting this:
Controlled swap_registers([temporary_equals_result(a, b)], (c, d));
The intention here is that temporary_equals_result returns some kind of special type, called something like QubitExpression or QuantumRValue, which defines methods for initializing and uncomputing a result with automatically managed auxilliary storage. The idea is that these explicitly specified methods are explaining things like "there will be n ancillae whose lifetimes is tied to the lifetime of the result" and "you can use measurement based uncomputation when getting rid of the ancillae".
Anyways, I'm sure this needs a lot of refinement, but the inability to plug temporary expressions together and have the compiler automatically make sure they appear and disappear as needed in a LIFO ordering does strike me as one of the major reasons that writing Q# code produces a lot of boilerplate (and feels like such a slog) compared to writing expressions in other languages.
I did actually mock out this idea in https://github.com/Strilanc/quantumpseudocode and it seemed to work well. But it was severely hampered by that library's inability to automatically derive inverses, which is not a problem in Q#.