[Python-ideas] User-defined literals

Andrew Barnert abarnert at yahoo.com
Fri Jun 5 17:45:52 CEST 2015


On Jun 5, 2015, at 05:18, Paul Moore <p.f.moore at gmail.com> wrote:
> 
>> On 5 June 2015 at 00:03, Andrew Barnert <abarnert at yahoo.com> wrote:
>> If it's meant to be a "compile-time decimal value"... What kind of value is that? What ends up in your co_consts? An instance of decimal.Decimal? How does that get marshaled?
> 
> Well, Python bytecode has no way of holding any form of constant
> Decimal value, so if that's what you want you need a change to the
> bytecode (and hence the interperter). I'm not sure how that qualifies
> as "user-defined".

That's the point I was making. Nick proposed this syntax in reply to a message where I said that being a compile-time value is both irrelevant and impossible, so I thought he was claiming that this syntax somehow solved that problem where mine didn't.

> We seem to be talking at cross purposes here. The questions you're
> asking are ones I would direct at you (assuming it's you that's after
> a compile-time value, I'm completely lost as to who is arguing for
> what any more :-() My position is that "compile-time" user-defined
> literals don't make sense in Python, what people actually want is
> probably more along the lines of "better syntax for writing constant
> values of user-defined types".

Be careful of that word "constant". Python doesn't really have a distinction between constant and non-constant values. There are values of immutable and mutable types, and there are read-only attributes and members of immutable collections, but there's no such thing as a constant list value or a non-constant decimal value. So people can't be asking to create constant decimal values when they ask for literal decimal values.

So, what does "literal" mean, if it's neither the same thing as "compile-time" nor the same thing as "constant" but just happens to overlap those perfectly in the simplest cases? Well, I think the sense in which these things should "act like literals" is intuitively obvious, but very hard to nail down precisely. Hence the intentionally vague "sufficiently simple" definition I gave. But it doesn't _need_ to be nailed down precisely, because a proposal can be precise, and you can then check it against the cases people intuitively want, and see if they do the right thing.

Notice that the C++ committee didn't start out by trying to define "literal" so they could define "user-defined literal"; they started with a vague notion that 1.2d could be a literal in the same sense that 0x1F is, came up with a proposal for that, hashed out that proposal through a series of revisions, translated the proposal into standardese, and then pointed at it and defined "literal" in terms of that. They could have instead decided "You know what, we don't like the term 'literal' for this after all" and called it something different in the final standard, and it still would have served the same needs, and I'm fine if people want to take that tack with Python. A name isn't meaningless, but it's not the most important part of the meaning; the semantics of the feature and the idiomatic uses of it are what matter.

> Oh, and just as a point of reference see
> http://en.cppreference.com/w/cpp/language/user_literal - C++ user
> defined literals translate into a *runtime* function call.

No, if you define the operator constexpr, and it returns a value constructed with a constexpr constructor, 1.2d is a compile-time value that can be used in further compile-time computation.

That's the point I made earlier in the thread: the notion of "compile-time value" only really makes sense if you have a notion of "compile-time computation"; otherwise, it's irrelevant to any (non-reflective) computation. Therefore, the fact that my proposal leaves that part out of the C++ feature doesn't matter.

(Of course Python doesn't quite have _no_ compile-time computation; it has optional constant folding. But if you try to build on top of that without biting the bullet and just declaring the whole language accessible at compile time, you end up with the mess that was C++03, where compile-time code is slow, clumsy, and completely different from runtime code, which is a large part of why we have C++11, and also why we have D and various other languages. I don't think Python should add _anything_ new at compile time. You can always simulate compile time with import time, where the full language is available, so there's no compelling reason to make the same mistake C++ did.)


More information about the Python-ideas mailing list