On Aug 27, 2019, at 18:59, Steven D'Aprano <st...@pearwood.info> wrote:
> 
> On Tue, Aug 27, 2019 at 10:07:41AM -0700, Andrew Barnert wrote:
> 
>>> How is that different from passing a string argument to a function or 
>>> class constructor that can parse that token however it wants?
>>> 
>>>   x'...'
>>> 
>>>   x('...')
>>> 
>>> Unless there is some significant difference between the two, what does 
>>> this proposal give us?
>> 
> 
>> Before I get into this, let me ask you a question. What does the j 
>> suffix give us?
> 
> I'm going to answer that question, but before I answer it, I'm going to 
> object that this analogy is a poor one. This proposal is *in no way* a 
> proposal for a new compile-time literal.

Yes, you’re the same person who got hung up on the fact that these affixes 
don’t really give us “literals” back in either 2013 or 2016, and I don’t want 
to rehash that argument. I could point out that nobody cares that -1 isn’t 
really a literal, and almost nobody cares that the CPython optimizer 
special-cases its way around that, and the whole issue with Python having three 
different definitions of “literal” that don’t coincide, and so on, but we 
already had this conversation and I don’t think anyone but the two of us cared.

What matters here is not whether things like the OP’s czt'abc' or my 1.23f or 
1.23d are literals to the compiler, but whether they’re readable ways to enter 
constant values to the human reader. 

If so, they’re useful. Period.

Now, it’s possible that even though they’re useful, the feature is still not 
worth adding because of Chris’s issue that it can be abused, or because there’s 
an unavoidable performance cost that makes it a bad idea to rely on them, or 
because they’re not useful in _enough_ code to be worth the effort, or 
whatever. Those are questions worth discussing. But arguing about whether they 
meet (one of the three definitions of) “literal” is not relevant.

> This proposal is for mere syntactic sugar allowing us to drop the 
> parentheses from a tiny subset of function calls, those which take a 
> single string argument.

And to drop the quotes as well. And to avoid polluting the global namespace 
with otherwise-unused one-character function names.

Can you honestly tell me that you see no significant readability difference 
between these examples:

    vec = [1.23f, 2.5f, 1.11f]
    vec = [f('1.23'), f('2.5'), f('1.11')]

I think anyone would agree that the former is a lot more readable. Sure, you 
have to learn what the f suffix means, but once you do, it means all of the 
dozens of constants in the module are more readable. (And of course most people 
reading this code will probably be people who are used to 3D code and already 
_expect_ that format, since that’s how you write it in C, in shaders, etc.)

> And even then, only when the argument is a 
> string literal:
> 
>    czt'abc'  # Okay.
> 
>    s = 'abc'
>    czt's'  # Oops, wrong, doesn't work.

Sure, just like you can’t apply an r or f prefix to a string expression.

> But, to answer your question, what does the j suffix give us?
> 
> Damn little. Unless there is a large community of Scipy and Numpy users 
> who need complex literals, I suspect that complex literals are one of 
> the least used features in Python.
> 
> I do a lot of maths in Python, and aside from experimentation in the 
> interactive interpreter, I think I can safely say that I have used 
> complex literals exactly zero times in code.

I don’t think your experience here is typical. I can’t think of a good way to 
search GitHub python repos for uses of j, but a hacky search immediately turned 
up this numpy issue:https://github.com/numpy/numpy/issues/13179: 

> A fast way to get the inverse of angle, i.e., exp(1j * a) = cos(a) + 1j * 
> sin(a). Note that for large angle arrays, exp(1j*a)needlessly triples memory 
> use…

That doesn’t prove that people actually call it with `1j * a` instead of 
`complex(0, a)`, but it does seem likely.


>> You can write complex numbers without it just fine:
> [...]
> 
> Indeed. And if we didn't already have complex literals, would we accept 
> a proposal to add them now? I doubt it.

I’m not sure. I assume you’d be against it, but I suspect that most of the 
people who use it today would be for it.

But if we had custom affixes, I think everyone would be happy with “just define 
a custom j suffix”. Would anyone really argue that they need the performance 
benefit or compile-time handling? How often do you evaluate zillions of 
constants in the middle of a tight loop? And what other argument would there be 
for adding it to the grammar and the compiler and forcing every project to use 
it?

Which is exactly what I think of the Decimal and Fraction suffixes, contrary to 
what Chris says. There will be a small number of projects than get a lot of 
readability benefit, but every other project gains nothing, so why add it as a 
builtin for every project?

And I don’t see why float32 is any different from Decimal and Fraction, given 
that the actual problem is not lossless values but readability, so a builtin 
Decimal suffix wouldn’t help there.

> But if you think we would, how 
> about a proposal to add quaternions?
> 
>    q = 3 + 4i + 2j - 7k

I’m sure you can guess my answer to that: most projects don’t need it, so there 
should definitely not be builtin suffixes for it. But if we have custom 
suffixes, it anyone _does_ need it, they can do it trivially, without having to 
bother the rest of us asking for it.

>> I don’t think so. What does the j suffix give us? The two extra 
>> keystrokes are trivial. The visual noise of the parens is a bigger 
>> deal.
> 
> I don't think it is.

You’ve cut off my paragraph to make it misleading. The visual noise of the 
parens _is_ a bigger deal than the two extra keystrokes, but as I said in the 
very next sentence, it’s still not the point of the feature. The real big deal 
is that it lets you write complex numbers in a way that looks like complex 
numbers. I don’t see any benefit in arguing about whether the “bigger deal but 
still not the point” is actually a bigger deal or not, because who cares?

> I think the big deals in this proposal are:
> 
> - you have something that looks like a kind of string czt'...' 
>  but is really a function call that might return absolutely 
>  anything at all;

It doesn’t return “anything at all”, any more than a function returns “anything 
at all”. 

It returns something consistent that has a specific meaning in your project. I 
don’t know what czt means a priori, but if I were reading the OP’s code, I 
could look it up, and then I would know.

And I could assume that, unless the author is an idiot, an affix on a string 
literal is going to be something stringy, and an affix on a number literal is 
going to be something numbery. Sure, you _could_ violate that assumption, but 
that’s no different from the fact that you could write a function called 
sqrt(n) that returns an iterable of the contents of all the files in the nth 
sub directory of $HOME. You’re not going to do that. (Or, if you do, I’m going 
to stop reading your code.)

> - you encourage people to write cryptic single-character 
>  functions, like v(), x(), instead of meaningful expressions
>  like Version() and re.compile();

Do you honestly not see the readability benefit in a bunch of constants that 
all look like `2.3d` instead of `Decimal('2.3')`?

Do you honestly think that `D('2.3')` is just as good as `2.3d`, and also worth 
using up a scarce resource (one-letter global names) for?

If not, then I don’t see why you’re pretending not to see the benefit of the 
proposal.

> - the OP still hasn't responded to my question about the ambiguity
>  of the proposal (is czt'...' a one three-letter prefix, or three 
>  one-letter prefixes?)

Well, this is why I wanted him to get into more details than his initial 
10000-feet-vision thing.

I honestly see a lot more use for numeric affixes than string ones, and for 
suffixes rather than prefixes, and for just one suffix per value rather than 
some rule for combining them. But I know that last time around (or maybe the 
time before), a sql prefix was the thing that got the most people excited, and 
I could see wanting to combine that with raw or not, and so on, so I’d like to 
see a concrete proposal on how all of that works.

> all of which *hugely* outweighs the gain of being able to avoid a pair 
> of parentheses.

Which, you’ll note, I already said was not the point of the proposal.

>> And the exact same thing is true in 3D or CUDA code that uses a lot of 
>> float32 values
> 
> Indeed, but this proposal doesn't help you here. You still have to write 
> strings.

No I don’t. I write `1.23f`, just like I do in C or in GLSL, exactly what I 
want to write, and read.

In my version of the proposal (which I described in my first email in the 
thread—including a link to a hacky import hook that implements it that I wrote 
up last time this subject came up in 2015), the parser sees a literal token 
(any kind of literal, not just string literals) followed by a string of 
identifier characters (that weren’t munched by that literal), it looks up that 
string, and calls the looked-up function with the raw text of the literal token.

The OP’s second email in the thread incorporated my idea into his existing 
idea. His version is more complicated than mine because it handles prefixes as 
well as suffixes, and it doesn’t have a proof of concept to verify that it’s 
all doable unambiguously, but it still allows me to write `1.23f`.

> What you want is a float32 literal, let's say 1.23f

I don’t care whether it’s an actual literal. I do care that I can write it as 
`1.23f`. And both my proposal and the OP’s allow that, so I’m happy with either.

> While I'm sympathetic, and I'd like to see a Decimal literal, I doubt 
> that there's enough use-cases outside of specialists like yourself for 
> 16- or 32-bit floats to justify making them built-ins with literal 
> syntax. Python is not Julia :-)

See, I would _not_ like to see a builtin Decimal literal. Or float16 or float32 
or fixed1616, or Fraction, or _any_ other new kinds of literals.

As long as I can use `1.23f` to mean `float32('1.23')` in the projects where I 
have a mess of float32 constants (and maybe copy-paste them into my REPL from a 
shader or a C debugger session), I’m happy. And I think user-defined affixes 
are a better way to get that than trying to convince everyone that Python 
should add a builtin float32 type and all the math that goes with it and then 
add a suffix for float32 literals.

Not because I doubt I could convince anyone of that, not because I’d have to 
wait 5 years before I could start using it even if I could, but because it’s 
simply not right in the first place.

Python should not have a builtin float32 type. And therefore, Python should not 
have a builtin `f` suffix.

And even if that weren’t an issue, I’d _still_ rather have a custom affix 
feature rather than a mess of new builtin ones.

If I run into an unfamiliar affix in your code, I’d rather look it up in your 
project that consult a table with a mess of builtin affixes.

If I want `d` for Decimal in one project, why should that mean nobody can ever 
use `d` for something different in a project that doesn’t do any decimal math 
but does a whole bunch of… something else I can’t think of off the top of my 
head, but I’m sure there will be at least one suffix that has two good meanings 
in widely different uses. Just like the namespace for builtin functions, the 
namespace for builtin affixes is—and should be—a limited resource.

And meanwhile, what would I get from `d` being builtin? I can save one import 
or register call or whatever per project. My program that takes 80 seconds to 
run starts up 2us faster because a few dozen (or at most hundred) constructed 
constants can be stored in the .pyc file. I don’t have to watch my speech to 
carefully avoid using the word “literal” imprecisely. None of those are worth 
anywhere near as much to me as being able to have the suffixes I want for the 
project, even if I just thought of them today—and to _not_ have the ones I 
_don’t_ want, even is some of them have a broader niche.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/TGYSJ742R2LD6JUUQREK2YPICYEJIRNA/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to