microsoft / qsharp

Azure Quantum Development Kit, including the Q# programming language, resource estimator, and Quantum Katas
https://microsoft.github.io/qsharp/
MIT License
439 stars 87 forks source link

File name containing period cannot be converted into a valid namespace name #1796

Open tcNickolas opened 2 months ago

tcNickolas commented 2 months ago

Describe the bug

image

Expected behavior

Q# supports namespaces with periods, and file systems support file names with periods, so I expect a namespace to be generated successfully. Personally, I like to place my main code in namespace called "Topic" and test code - in the namespace "Topic.Test", and it would be great to do that while taking advantage of the new feature on omitting explicit namespace declarations.

System information

sezna commented 2 months ago

Q# supports namespaces with periods

This is not actually true anymore (as of #493), as Microsoft.Quantum is actually a namespace called Microsoft which contains another namespace named Quantum. Each individual namespace needs to be a valid identifier.

If, e.g. scratch.test were converted into a namespace test which is in a namespace scratch, then that file would also be accessible if you had a file scratch/test.qs -- two files that define the same namespace is not intuitive.

To accomplish your scenario with implicit filesystem namespaces, you can either use explicit namespaces, or you can have a file Topic.qs and a file Topic/Test.qs -- would that work for you?

tcNickolas commented 2 months ago

Should we update documentation to mention this? Right now it says the opposite

A namespace block consists of the keyword namespace, followed by the namespace name, and the content of the block inside braces { }. Namespace names consist of a sequence of one or more legal symbols separated by a dot (.). While namespace names may contain dots for better readability, Q# does not support relative references to namespaces. For example, two namespaces Foo and Foo.Bar are unrelated, and there is no notion of a hierarchy.

The issue here is not that I cannot find a way to define a namespace with a dot in it. The issue is that I create a valid file that should be converted to a valid namespace name, and it errors out instead.

In the past we had plenty of different files that defined parts of the same namespace, it is not a problem at all. To give you just one example written by an external user (without my input), https://github.com/Strilanc/quantum-block-lookahead-adder/tree/master/anc/src has Q# code in multiple files, all of it in one namespace BlockAdder.

sezna commented 2 months ago

We did move away from re-opening namespaces as a pattern with the introduction of implicit filename-based namespaces. This was intentional, as we don't want you to be able to re-open a file-based namespace and add items to it -- it is confusing, and can lead to spaghetti code. We want to maintain that a file is the canonical source for items defined within that namespace. We do not want the situation where scratch.test.qs and scratch/test.qs refer to the same namespace -- multiple sources of truth leads to a lot of confusion. In the past this pattern was allowed, and used in the standard library, but it led to confusion in tooling and a lack of API boundaries -- this situation wouldn't scale to external projects.

What I've just said is only the case when using the newly-introduced implicit namespaces. For explicit namespaces, existing behavior still works (that is, this change wasn't breaking). You can still create a new file and explicitly define a namespace namespace Scratch.Test {}. So, if you just name your file anything at all (scratch.qs perhaps) and use explicit namespaces, the functionality will continue to work as it had before. Does that address your concern?