-
Notifications
You must be signed in to change notification settings - Fork 179
API: Consider the formatted output/logging functions #419
Comments
The new C++ standard formatting library is similar to Python's formatting capabilities. |
@kuzminrobin: Thank you for opening this; it sounds like there's a few different suggestions made in the thread above. Would you be willing to clarify what changes you'd propose to the Q# API surface so that we can get that scheduled for Thursday's API review board meeting? Thank you! |
@cgranade, @bettinaheim, @msoeken, thank you for sharing your knowledge! The C++ standard formatting library has been added in C++20, there can be temporary issues with that. In particular, we currently compile our QIR/C++ code with C++14 compiler flag, and the attempt to use C++17 causes compilation errors in the headers provided by MSVC++. I didn't try C++20, this can require an update to the clang/LLVM toolchain, but I expect even more issues with migration to C++20. So the C++ standard formatting library is not something that we can immediately start using (it can require updates in MSVC++). |
Wow!
That's definitely a way to go... |
(Work in progress. Can change) For
|
(Work in progress. Can change) For
|
Duly noted; in the interest of getting this through quickly, please take the following as early feedback.
In terms of Q# style guide and design principles, we'll need a noun or adjective phrase instead of Aside from that, which order of inputs is most consistent with currying? I'd imagine the same format string getting applied to multiple different numeric values would be significantly more common than the same numeric value getting formatted with different strings, such that With respect to input types, is it expected that this should only ever work on integers? If we want formatted strings for other kinds of inputs, then we'll need type suffixes to distinguish them:
Other questions:
@bettinaheim can speak to this better than I can, but if you want to go on and suggest that as a language change, filing a Q# suggestion would be the right next step to kick off that process. I would be slightly concerned with the use of |
Thank you for the early feedback, @cgranade. (For oneself: To do: function DoubleAsString(a : Double) : String {
return $"{a}";
}
|
Thanks for your response, @kuzminrobin
This just means that it has been to the standard version since C++20, and in the future compilers will pick up implementing it into the standard libraries. However, there is a popular implementation of the formatting proposal, called libfmt, which can be used with earlier versions of C++. But as you already mentioned, the main take away is the formatting syntax and it's familiarity to Python. |
(Work in progress. Can change)
DoubleAsStringWithFormat(), IntAsStringWithFormat(): |
I have ran through the Discriminated Unions twice, and through the Pattern matching and match expressions. For now I don't foresee any contradictions. |
I don't know of any usage of either
Fair enough, thanks for looking at that. It can also be important to make sure we don't miss an opportunity for other designs using future functionality; e.g., could formatting options could be handled in a structured way by using DUs instead of string formats to help ensure at compile time that formats are sensible?
Similarly, we could imagine a type-safe version of the integer formatting options:
Given that Q# is ideally intended to minimize runtime failures by using tools such as type safety, such a design could help avoid failures if a user passes an incorrect string format (e.g.: |
Very curious insight... For now I feel somewhat "short-sighted" in Q# to estimate that. But you raised a very good point.
Ideally I would prefer to reserve a space in the language/library for providing both options for the users to choose. Is there any proposal for the multiple overloads to be supported in Q#? Such that both the |
@kuzminrobin Overloading in Q# does not exist, but we do support type parameterizations. Currently, any argument item whose type is parameterized can only be "treated as a black box", meaning you cannot do anything with it that would require type information. For the future, something like type classes could give a way to make these more powerful and allow something like you asked about above. This is still going to be quite some time out though. A question on the formatting: |
Agreed, which is why I suggested the DU-based format only as a point of discussion; I'm not convinced that would be better necessarily, so much as that there are some ways in which compile-time verification fits into the design of Q#. It may be we can do similar with stringly typed formatting specifications (e.g.: never fail on invalid formats, but fall back to a string like
To @bettinaheim's point, we don't have any language functionality to support that currently (indeed, this is why we need type suffixes like the In either case, I don't mean to derail coming up with a proposal that works well in Q# as it is right now, so much as to try and keep an eye on the future so as to minimize any breaking changes we may need if those language suggestions and proposals are eventually adopted. For example, one resolution could be that string-based formatting specifications work well because if we eventually get anonymous DUs and/or typeclasses, that we could use those to provide something similar to overloads in this case, adding new functionality without breaking old. |
@bettinaheim, while providing the usage examples I was thinking about illustrating the minimalistic implementation only, i.e. at least the hexadecimal for
I need to look at this. If from C# we can forward the calls to C++ then we should be totally fine here. In that case I will just provide the same C++ implementation both for QIR and C#. |
(the letter 'i' in the word "stringly") in this particular context sounds very... equally-probable that you meant either "strongly typed" or "string typed"... ;-) |
A reference to a common (and likely unfair in this case!) riff on string-based APIs: http://wiki.c2.com/?StringlyTyped |
(This idea has been abandoned. The reason is in the subsequent feedback. See later version below) Single
|
In the same spirit as before, please take this as preliminary feedback, reflecting that this proposal is still in progress. Thanks!
I think you'd run into trouble here, in that
Q# includes a concept called singleton–tuple equivalence, which states that Similarly,
At the moment, Q# doesn't include any sort of varargs feature; it seems like that could be difficult to merge with the tuple-in tuple-out semantics used by Q#, but if you want to kick off a suggestion as to how to do so, I'd suggest checking with @bettinaheim and then possibly opening a language issue with that suggestion. |
I assume that you mean the following: I cannot write like this:
I have to write like one of these
Thanks for that timely warning! |
That's right,
No worries. If you're interested, the types section of the language guide at https://docs.microsoft.com/azure/quantum/user-guide/language/typesystem/ may be helpful here. |
(Work in Progress. Likely to Change) Proposed ChangeLibrary Only Change. Is the easiest to implement. namespace Microsoft.Quantum.Convert {
function FormattedI(fmt : String, value : Int) : String { // For `Int` formatting.
body intrinsic;
}
function FormattedD(fmt : String, value : Double) : String { // For `Double` formatting.
body intrinsic;
}
} The QIR implementation will pass the parameters to the C++ implementation. Usage examples
|
As per #426, we're good to deprecate existing formatting functions immediately; will respond in more detail on the proposal itself ASAP. |
Thanks for the update, @kuzminrobin! As promised, I've gone on and left some more feedback below, reflecting that as per your comment this is still in progress. In the meantime, I think my biggest take-away is that it would be good to understand the user feedback and usecases that motivate this proposal so as to help identify which subset of features we need to be sure to capture in the proposed API. In particular, the previous formatting functions weren't heavily used at all (in fact, I was unable to find any use at all), speaking to that string formatting is either somewhat niche at this point, or our previous solution was rejected for some reason (e.g.: users weren't aware, didn't meet user needs, etc.).
I think that makes sense, yeah; we may separately want to consider a language suggestion at some point, but I agree that for now, targeting library functionality makes the most sense.
One thing that may be helpful (YMMV, of course) in continuing with the proposal is to prototype or stub what API docs would look like for these. That can sometimes show where things need to be specified a bit further. For example, under what conditions (if any) do these functions My own 2¢ is that string formatting should never result in a
How would you suggest implementing on the C# side so that these new functions can be used with the existing C#-based runtime (e.g.: from Python via IQ#)? Would we want to write a parser for this mini-language in the C# runtime? It doesn't look too complicated, thankfully, but it's still an implementation detail that would be good to have some rough suggestion on to avoid this feature not being accessible by our Python users.
From this, it looks like the |
@cgranade, (I realize that a reference to a video is a bad answer to a question ;-) But the answers in the video are provided by a person who invested years of his life in getting his formatting library proposal to the C++ language, being based on the existing Python implementation that was already working and widely used (adopted to Rust). And a number of people in the C++ standards committee invested multiple hours in reviewing/discussing/complementing the proposal, a number of companies adopted the C++ implementation/library. I doubt that my own answers or research will sound more convincing than that. The video mentioned is a talk at a C++ conference, introducing the C++ formatting library that ended up in C++20 standard (not yet implemented in latest Clang or GCC), the library that I propose to use for the implementation of Q# formatting (and a full credit for that definitely goes to @msoeken who referred me to that formatting library))
Here I don't talk about whether Q# needs the formatting library at all or not. But if it does need, then we need to choose which one to adopt. Proposed library advantages: 25:30 - 26:22, safety (type/memory): 35:20 - 36:02, performance/size/compile-time: 42:03 - 48:00, 260+ contributors. Unrelated to the answer, just for the future reference: (My answers to the other your points to follow) |
To clarify slightly, I understand the usecases for formatting features like this in languages like Python and C++, but my point was that Q# gets used in a quite different context. To wit, I use string formatting in Python and C# quite regularly, but I was unable to find any usage of the previous Q# formatting functions. To that extent, I think we can definitely learn from what formatting string specs are adopted in classical languages and why those specs were chosen, but the use cases here are likely to be somewhat different due to Q# programs running on quantum devices rather than at the host level. |
Well, the use case that comes to my mind at the moment (while we have no fully fledged debugging facility for the Q#/IR/C++ intermixed code), is the detailed logging instead of debugging. |
(Request For Early Feedback. Work in Progress)
Latest State
Earlier Story
(Links DoubleAsStringWithFormat(), IntAsStringWithFormat(), Standard numeric format strings, Custom numeric format strings).
Discussion:
[12:42 PM] Bettina Heim
Hi all,
As part of adding support for Q# to the QIR runtime, we came across the logging functions that allow to give a formatting option. Right now, the option seems to be exactly what C# provides. Since this is pretty extensive and I am not eager to blindly duplicate the C# behavior in our native implementation, I would like to gather your input regarding what formatting options we need and want to support going forward?
[12:50 PM] Chris Granade (THEY/THEM)
There's not a single line of Q# in all of our libraries or samples that calls either function...
Thinking to kind of first principles for the language and libraries, though, the whole point of Message is to provide optional logging information back to the host. To that end, I wouldn't think that it's intended that we should provide UX features like formatting at the Q# level.
I know Bettina, Alan and I played around with the concept of a function that would emit logging info other than strings years ago (e.g.: if a Q# program wants to send a Double to the host as a log message); that may be better than trying to handle formatting at the Q# level.
[12:57 PM] Bettina Heim
Chris Granade (THEY/THEM) Do you know why these have been added in the first place? Do you know of anyone else that could be using them? Would it be good to keep some minimal formatting options, or would you suggest deprecating them?
My inclination would be to allow for some minimal formatting, but definitively not the extensive support that C# provides.
Robin Kuzmin, What kind of formatting support does C++ provide?
[1:32 PM] Robin Kuzmin
The simple option is the printf() formatting of C, see "Conversion specifiers" (or a broader picture - "Format of the format string") in the printf() manual page.
As for C++, let me summarize...
As a short answer I would say, C++ formatted output is harder to adapt as an implementation of the Q# calls. And that C++ formatted output would be described here. E.g. see "hex" that will take you to here and show the examples like
std::cout << std::hex
, after which all the integer output will be in hexadecimal form.[1:48 PM] Robin Kuzmin
As a minimalistic implementation I would say that we need
[1:48 PM] Robin Kuzmin
And most (if not all) of that is already implemented, I believe.
[2:07 PM] Chris Granade (THEY/THEM)
I don't, no; they are amongst the first intrinsics added to the language, IIRC, back when everything was somewhat chaotic.
I'm not aware of such, no; was unable to find a single usage when I looked, so I'm not sure there's a lot of demand for that feature. My initial thought would be to deprecate entirely for now, but happy to discuss further.
[8:20 PM] Robin Kuzmin
I looked at .NET's (C#'s) formatting - Standard numeric format strings and Custom numeric format strings.
looks like for the minimalistic implementation (mentioned in my previous 2 posts) we also need (EN-US locale):
.
)The text was updated successfully, but these errors were encountered: