-
Notifications
You must be signed in to change notification settings - Fork 99
Editing Q# in VS Code
The recommended way of developing Q# code is in VS Code with the Azure Quantum Developer Kit extension. This extension provides both a rich Q# development environment and Azure Quantum integration. Features of the extension include:
- Syntax highlighting and basic syntax features (e.g. brace matching)
- Q# cell support in Jupyter notebooks. The extension will detect
%%qsharp
magic cells and automatically update the cell language to Q# - Error checking in Q# source files
- Breakpoint debugging and script execution for Q# source files
- Integration with Azure Quantum for quantum job submission
- Hover-definition and docs
- Go-to-definition
- Function signature help
- Snippet and sample support
- Completions
Several common quantum algorithms are provided as samples in the completion list. After creating a new .qs
document, type sample
to filter the completion list to them, and tab-complete to insert the sample.
After developing a Q# quantum algorithm, you have the option to run your code. This can be done either locally on a quantum simulator, for free; or via submission to Azure Quantum, for a price.
In VS Code, access the Command Palette (ctrl
/cmd
+shift
+P
). Run the command "Debug: Run Q# File". This will run the file on your computer, using a quantum simulator. (You can also use the Play icon and drop-down in the top-right of the editor. See the screenshot in Debugging Locally
section following. Or simply press Ctrl-F5). Note that this command only appears if you currently have a ".qs" file selected and open. You can see the output from the program in the VS Code Debug Console
output pane.
The extension includes a debugger. The debugger can handle typical breakpoint-style debugging (step into, over, out of, etc) as well as render program state.
To start the debugger, click the debug icon in the top left of VS Code. Select "Debug Q# File".
From here, the state of the program should be visible in the debugger pane on the left, and breakpoints will work. You can see the qubit state as well as local variable state in the "Variables" section:
For fun, try stepping through an adjoint section. The debugger will show you how the adjoint is generated and applied.See this wiki article for instructions on submitting to Azure.
Q# supports the notion of Q# projects, which are multiple Q# files that are compiled together as one unit. To create a Q# project, create a folder and add a file called qsharp.json
to it. qsharp.json
should look like this:
{
"author": "your name here",
"license": "your chosen license here"
}
Q# source files are read from src/
:
.
├── qsharp.json
└── src/
├── Main.qs
├── Foo.qs
└── bar/
└── Bar.qs
A Q# project, unlike a single-file compilation, can have dependencies on other Q# projects. If you've used libraries or library code in other languages, you will be familiar with this concept.
There are two ways to take a dependency on an external Q# project. The first is a local dependency, and the second is a GitHub dependency. To get started, add a "dependencies"
property to your qsharp.json
project manifest file. A local dependency looks like this:
{
"author": "your name here",
"license": "your chosen license here",
"dependencies": {
"SomeDependency": {
"path": "/path/to/other/project/on/disk"
}
}
}
And a GitHub dependency looks like this:
{
"author": "your name here",
"license": "your chosen license here",
"dependencies": {
"SomeDependency": {
"github": {
"owner": "GitHubUser",
"repo": "GitHubRepoName",
"ref": "CommitHash"
}
}
}
}
Note: for GitHub dependencies, the ref
property refers to a Github refspec, however we recommend always using a commit hash.
After following the steps in the above section, you'll be able to access items that have been exported from the external project. They'll be available in a namespace defined as the name given to the dependency in the qsharp.json
project manifest file. As an example, consider the following manifest file:
{
"author": "your name here",
"license": "your chosen license here",
"dependencies": {
"SomeDependency": {
"path": "/path/to/other/project/on/disk"
}
}
}
In this manifest file, we define an external dependency called "SomeDependency"
. This external project will therefore show up under the namespace SomeDependency
. To access an exported callable Bar()
from "SomeDependency"
, we can call it as such: SomeDependency.Bar();
. To import all items from an external project, we can use a glob import: import SomeDependency.*;
. This is analogous to the existing open
syntax: open SomeDependency;
.
Import statements allow for either importing individual items, or glob-importing entire namespaces into the current scope. Imports can also be used to alias items. Here are a few examples:
-
import Foo.Bar;
: imports a single item calledBar
from the namespaceFoo
. -
import Foo.Bar as Foobar;
: imports a single item calledBar
from the namespaceFoo
, but makes it accessible in the local scope asFoobar
. -
import Foo.*;
: import all items from the namespaceFoo
. -
import Foo.* as F;
import the namespaceFoo
asF
, items insideFoo
are now accessible viaF
. For example,Foo.Bar
is now accessible asF.Bar
. -
import Foo.Bar, Foo.* as F, Foo.Bar as Foobar;
: imports can be combined into one line.
Q# Projects are a great way to import external code. But what if you want to publish your project as a library, so others can import it? What if you want to become a Q# library author? A set of features has been added to enable you to define your project's exported API.
Any callable, type, or namespace can be exported for external usage. Consider the following Q# project structure:
.
├── qsharp.json
└── src/
└── MathStuff.qs
And consider the contents of MathStuff.qs
:
function Add(a: Int, b: Int): Int {
return a + b;
}
To export Add
, we add an export statement:
function Add(a: Int, b: Int): Int {
return a + b;
}
export Add;
The callable Add
will show up in this project's API as MathStuff.Add()
, because export statements export items from the namespace they were exported from. That means that if you export Add()
from the namespace Foo.Bar
, it will show up to consumers of the project as Foo.Bar.Add()
.
In a similar manner to imports, exports can also be aliased:
function Add(a: Int, b: Int): Int {
return a + b;
}
export Add as MyAdd;
Export statements export items for external projects. All items are available to other namespaces within the same project by default, without any exporting needed.
In a project, if there's a namespace called Main
, it is treated as the root of the project. So, if you have the below structure:
src/
Foo.qs
Main.qs
Bar.qs
and a consumer of the project with the manifest:
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyLibrary": {
"path": "/path/to/other/project/on/disk"
}
}
}
Anything exported from Main.qs
, say a callable X
, will show up in the consumer of the project as MyLibrary.X()
. The behavior of items exported from Foo.qs
and Bar.qs
is unchanged; an item X
exported from these namespaces would show up as MyLibrary.Foo.X()
and MyLibrary.Bar.X()
.