Skip to content

Differences from the previous QDK

Bill Ticehurst edited this page Sep 13, 2023 · 10 revisions

Language Syntax Updates

This section details some of the updates to the Q# language and what syntax can be used in a valid program.

Expression-based

As part of developing the new compiler, the Q# language has been updated to be expression-based instead of statement-based. This allows for new use of existing syntax, such as embedding an if-expression into another expression:

let x = if check { 0 } else { 1 };

Implicit return

The previous example also takes advantage of using statements without a trailing semicolon at the end of a block to return a value from that block. This pattern can be used instead of explicit return-expressions in a callable:

function ReturnsThree() : Int {
    return 3;
}

function AlsoReturnsThree() : Int {
    3
}

Block-expressions

Block-expressions are now supported that can organize multiple lines, scope variables, and return a value:

let flip = {
    use q = Qubit();
    H(q);
    if M(q) == One {
        X(q);
        "Heads"
    } else {
        "Tails"
    }
};

Explicit Types for Local Variables

Local variables can now be explicitly typed using the same syntax as types for callable argument declarations:

let x : Int[] = [];

Explicit types are not required but can sometimes be helpful when resolving type ambiguity for functions that accept generics, such as Length.

Implicit Namespace Prelude

Name resolution now incorporates an implicit prelude which is a set of namespaces that are treated as if they had been opened as long as no other resolved names supersede them. The namespaces that are treated this way are Microsoft.Quantum.Core, Microsoft.Quantum.Canon, and Microsoft.Quantum.Intrinsic. These do not need to be explicitly opened expect when using aliases or otherwise differentiating from potential conflicts.

Standard Library

The Q# standard library is now hosted in the same repository as the compiler and runtime, and can be found in the top-level library folder. Not all functionality and features have been migrating from the existing Q# libraries, found at https://github.com/microsoft/QuantumLibraries. If an item from the previous library is needed for a program, that item and any dependencies can be copied into the source program. If any library functionality is critical to a workflow and should be considered for inclusion in the new standard library, please file an issue with the details.

Sparse Simulation by Default

The new QDK uses a built-in sparse state quantum simulator as the default target for local simulation. This simulator is written in Rust and comes from the QIR Runner repository, allowing it to compile to WASM and run across a variety of environments. Currently this is the only simulation backend available in the QDK, though other backends are under consideration for future integration. For more information on the sparse simulation design, see Testing large quantum algorithms using sparse simulation.

QIR Generation

The new QDK produces QIR by generating the textual representation of LLVM (.ll) instead of using bitcode (.bc). Most targets and tools that accept bitcode can also parse textual LLVM, including tools like PyQIR and QIR Runner.

The new QDK is currently limited to QIR generation for programs compatible with the QIR Base Profile. When Base Profile compilation is configured, the compiler and/or VSCode extension will produce errors for patterns that are not compatible with the target. The compiler can also conditionally skip compilation of items that have attributes indicating they are specific to particular compilation targets:

@Config(Full)
function ResultAsBool(input : Result) : Bool {
    input == One
}

Adaptive and Full QIR generation are on the roadmap but not yet implemented.