[Development] Feature freeze exception for QTBUG-95587
Ulf Hermann
ulf.hermann at qt.io
Mon Sep 13 09:56:23 CEST 2021
> My first impression is that this looks like nice syntax. However maybe we should discuss a bit how it fits into the language design, since it seems like we’re trying to have a cohesive language design nowadays. I’m never quite sure to what extent QML is “our” language, or to what extent the rule is “just do what Javascript does”, and then we have to defer to ECMA standards, and common web-development practices (which I don’t know very much about). But is there any precedent for this “@“ operator, for what it’s worth?
We've extended the JavaScript syntax in quite a few ways already. We
have type annotations borrowed from TypeScript, and an "as" keyword with
our own semantics. Adding additional constructs that don't clash with
JavaScript is fine.
> QML has this peculiarity of doing string conversion when binding to properties of specific types, like color: “#123” and point: “5,6” and vector3Prop: “5,6,7”. Personally I prefer languages in which the syntax for type conversion is definable and extensible rather than being just a side effect of trying to shoehorn a string into some other type; but that’s what we have. And another peculiarity is putting all those constructor functions into the Qt namespace, like Qt.rgba(), Qt.point(), Qt.vector3d() etc. (This is probably even less intuitive for JS developers?) If we were trying to design a language from scratch, without the baggage left from Qt 4, we’d probably be able to do better with the syntax for both of those, right? But can we evolve toward something better now?
Creation of value value types from JavaScript is indeed still an open
problem. I don't think we will need an extra operator to fix it, though.
You should just be able to pass the parameters to a value type
constructor as a JavaScript array or object. For example:
property point p: [5, 6]
property point p: {x: 5, y: 6}
In order to make this perform, we need some kind of typed JavaScript
"parameter object" that lives on the stack as far as possible while
adhering to reference semantics. We want such a thing anyway, for
compilation to C++. The specifics are not decided, yet. If you have any
particular ideas, let me know.
> So now it seems like you are introducing a prefix operator on that string-shoehorning, which could potentially become a multi-purpose feature. It causes a bit of bias that this operator is pronounced “at”, so maybe the thought is it fits better with the sorts of conversions that imply some sense of “place”, either a geometric location or in a virtual space like the space of URLs and URIs?
Yes, introducing an entirely new operator for the specific purpose of
URL conversion and resolution seems rather excessive at first. However,
URLs are a vital thing in QML, and the automatic string-shoehorning is
indeed not ideal. In order to make the conversion explicit, you have to
write Qt.resolvedUrl() today. No one wants to do that in all the places
where they use URLs. We still should make the conversion explicit, in
order to avoid all the ambiguity surrounding strings and URLs, as seen
in the various bugs. Instead of an operator, we could introduce a new
function in the global object, e.g. qsUrl(). However, this potentially
clashes with other names and is not that much nicer than
Qt.resolvedUrl(). Also, it doesn't express "resolved" (and I want a
non-resolving URL constructor, too). The '@' operator is nice in that it
can be easily thought of as resolving the "place" it points to and it
doesn't require parentheses.
However, if we nail down the meaning of @"string" to "create and resolve
a URL", then we cannot use a plain '@' for much else. We might, however,
add, for example, a @point[32, 34] that would create a point and resolve
it in some way. The plain '@' would then become a shorthand for @url.
URL is certainly the most important value type that isn't also a
JavaScript type. Therefore, the extra short syntax seems adequate to me.
(This brings up the point that I should check for @somevariable to be
invalid ... there you do need to add parentheses or a space)
> We already have some string conversions in place, but if we define “@“ as giving that conversion some sort of “alternate” interpretation, in how many more contexts does that idea make sense? Do we need an “alternate” way of converting colors, points, rectangles or something like that? Or could the “@“ operator be even more general than that, sometimes being applied to other types than strings? Maybe to convert Euler angles to a quaternion? Radians to degrees?
In the above sense, the '@' operator should only be used for things that
perform some resolution. I could, for example, envision geometry mapped
to/from the surrounding element. An object type like QQuickItem might
define '@' operations for specific value types which would then be valid
in its scope.
> If we use the “@“ operator for this-and-that over time, it would still be best if it retains some sort of language-wide cohesive meaning. On the other hand, it seems a waste to introduce a nice single-character operator and only ever use it for _one_ purpose; of course that’s fine for a range of minor versions if it only does one thing, as long as we know how we can potentially go further with it.
URLs are actually rather important. You use them to identify JavaScript
and QML files, and any resources you refer to. Even a separate operator
only for URLs would be fine for me.
> Oh I just got another idea… if we had introduced units into QML (which we IMO should have), as in being able to specify Rectangle { width: 5mm }, we could think of URL resolution as another type of unit conversion; so then I suppose it should be some sort of postfix operator rather than prefix, like maybe Image { source: “my icon.png”csd } (if we define “csd” as meaning “component source directory”). Using short words rather than punctuation would leave it more open to having several more such conversion operators rather than only one “alternate”. OTOH I think @“my icon.png” looks nicer for this one usecase, considered alone. In C++ we have a counter example with string-conversion tokens that are prefixes, as in u”string”. And the even weirder ones with extra stuff on both ends, as in u"qtbase”_qs.
This only works for literals. You can resolve any expression as URL,
though, as long as it evaluates to a string or a URL. We might still
introduce units for literals and there we might have a "url" suffix in
order to create a URL in the first place, rather than going through
string. It would not resolve the URL relative to the current context.
However, units are yet another discussion.
> It’s just a question of which approach leads to more cohesion of the QML language as a whole, and which way is most intuitive for users (those who have mainly prior JS experience, and those who have Qt C++ experience).
Neither kind of experience helps you with URL resolution in QML,
unfortunately. In HTML a relative URL is always relative to the place
where it's used. You can pass relative URLs around all you like and they
might mean different things in different places. I've actually tried to
do this with the behavior change from Qt5 to Qt6, but we see now that
this is not quite enough.
So, the cohesion of the language is the actual question. The above
explanations make it clear, that the '@' operator still leaves enough
potential for extension while recognizing the central importance of the
url type and granting it a special shortcut.
best regards,
Ulf
More information about the Development
mailing list