On Mon, Jan 17, 2022 at 4:38 PM Christopher Barker <python...@gmail.com> wrote:
>
> On Sun, Jan 16, 2022 at 6:34 PM Chris Angelico <ros...@gmail.com> wrote:
>>
>> > def fun():
>> >     return "some string"
>> >
>> > doesn't return the same string, unless it's iterned, which is an 
>> > implementation detail, yes?
>>
>> Not sure what you mean. That's a constant, so it'll always return the
>> exact same object, surely?
>
>
> I *think* that's only if it's interned -- and in any case, is a guarantee of 
> the language, or an optimization?
>
> I tried to test with a longer string, and it was the same one, but then I 
> found in this arbitrary post on the internet:
>
> ... in Python 3.7, this has been changed to 4096 characters
>
> ( I guess I haven't played with that since 3.7) -- I haven't actually tried 
> with a string literal linger than 4096 chars :-)

When you return a literal, like that, the literal becomes a function
constant. That's not necessarily a language guarantee, but I would be
hard-pressed to imagine a Python implementation that copied it for no
reason.

> But this certainly doesn't:
>
> In [1]: def fun():
>    ...:     return [1,2,3]
>    ...:
>
> In [2]: l1 = fun()
>
> In [3]: l2 = fun()
>
> In [4]: l1 is l2
> Out[4]: False
>
> So the issue is immutability and interning, not "literal display".

The difference is that list display isn't a literal, but a simple
quoted string is. The square brackets are guaranteed to construct a
new list every time.

> My point is that a frozenset litteral could open the door to interning frozen 
> sets, but that could probably be done anyway. And why? Are they heavily used 
> in any code base?
>

A frozenset literal would allow the same frozenset to be reused, but
it's not about interning. You're right that interning would be
possible even without a literal, but in order to intern frozensets
without a literal, we'd still need to construct a brand new
(non-frozen) set to pass to the constructor, since there needs to be a
way to indicate which elements we want.

Technically, there are no "complex literals", but thanks to constant
folding, a value like 3+4j can become a function constant. In theory,
I could imagine a Python implementation that treats 3 and 4j as
constants, but adds them at runtime, producing a unique complex object
every time. But since there are no shadowable name lookups, it's easy
enough to take advantage and gain a nice optimization.

In theory, what could be done for frozensets would be to use a *tuple*
for the arguments, which can then be used for an intern-style lookup:

_frozenset = frozenset
_fscache = {}
def frozenset(t):
    if type(t) is tuple: # strict check, don't allow subclasses
        if t not in _fscache: _fscache[t] = _frozenset(t)
        return _fscache[t]
    return _frozenset(t)

This would remove some of the copying, but at the cost of retaining
all the tuples (in other words: now you have a classic caching
problem). Could be useful for situations where it really truly is
constant, but it's still a bit of a roundabout way to do things.

A true frozenset literal can't possibly be shadowed, so the compiler
would be free to do all the same optimizations that it does with
tuples.

ChrisA
_______________________________________________
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/7LRVPVKTQULH7QSF7GURV2W2MIVTWLKK/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to