[Python-ideas] Re: Extract variable name from itself

2023-09-12 Thread Valentin Berlier
Do you mean something like C# nameof()? 
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/nameof
___
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/USPQDMEA7ACWH2T56ZYTWBGG7SMT3RIF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: New Ideas for Python - Oregon State University Open Source Software Course

2023-06-06 Thread Valentin Berlier
> add multi-line commenting to the Python programming language
Python uses docstrings for multi-line comments.

> add capability to optimize for database access and usage
Do you have an example of a concrete "capability to optimize for database 
access and usage"? What does that mean? How would it improve upon existing 
libraries like SQLAlchemy?

> add functionality for mobile application development to the Python 
> programming language
Most programming languages don't come with mobile development toolkits out of 
the box because they're expensive to maintain, and it's better for mobile sdks 
to have their own release cycle tied to the platform they're targeting instead 
of tied to specific language versions. You can use Kivy, the BeeWare project, 
and possibly other projects with their own set of tradeoffs to develop mobile 
apps using python.
___
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/ZTXL3E5NSA43KLJ6MNXBIMM55D42QATE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Ampersand operator for strings

2023-03-07 Thread Valentin Berlier
I'm -1 on this. You can easily make a helper that achieves the desired syntax. 
Presenting "human readable data" isn't just about collapsing spaces, and having 
your own helper means that you can adjust the formatting to your specific use 
case if needed (for example with a different separator).

from typing import Self

class StripJoin:
def __init__(self, value: str = "") -> None:
self.value = value
def __and__(self, other: str) -> Self:
other = other.strip()
separator = bool(self.value and other) * " "
return StripJoin(f"{self.value}{separator}{other}")
def __str__(self) -> str:
return self.value

j = StripJoin()
print(j & "   foo  " & " bar   " & " something   ")
# Output: "foo bar something"

The example above is more efficient than a possible implementation directly on 
the str builtin as it doesn't strip the left side over and over. However it 
still incurs repeated allocations and encourages a pattern that performs badly 
in loops. With a lot of input you should probably accumulate the stripped  
strings in a list and join them all at once.

In any case I recommend reaching out for a library like Rich 
(https://github.com/Textualize/rich) if you care about formatting the output of 
your program nicely.
___
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/A7RPR3FSBXEMRYAUXJVYYROCHVHL7DVP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Variadic patterns

2022-09-13 Thread Valentin Berlier
I really like this. One problem though is that it's not immediately obvious 
what happens with binding patterns and "as" clauses. In the code inside the 
case statement, should these identifiers refer to the last value matched, or 
should they accumulate all the matches in a list?
___
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/U6TBMZXATDAYKYUVK7B3JNHJH3XCPO76/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Time to relax some restrictions on the walrus operator?

2022-05-08 Thread Valentin Berlier
Yeah you can technically craft such pathological edge cases but this is already 
heavily discouraged. Libraries that change the usual semantics of python's 
object model are rare.

The only exception I can think of would be numpy which disallows truthiness 
checks because of the ambiguity of arrays being both scalars and containers. 
However, this means that the "if x := get_some_array():" construct is already 
ill-formed so nothing would change by generalizing the left side to arbitrary 
patterns. And since numpy arrays aren't proper Sequence types you can't use 
them with the current implementation of pattern matching anyway.

So besides carefully crafted pathological edge-cases the "if (...) is not None" 
construct would be completely redundant.
___
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/332DUWASBGXRPUHQN2AVEKTV2ASILKLB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Time to relax some restrictions on the walrus operator?

2022-05-08 Thread Valentin Berlier
> Yes, but what if you're testing for something that could *potentially* match 
> one of these empty objects?

The right side can absolutely be falsy but to be able to conflate the falsy 
return value with the None emitted when the pattern doesn't match, the left 
side has to be one of the dubious patterns I listed.

> I'm worried that this will end up being a bug magnet, or conversely, that 
> people will have to work around it with "if ([x] := foo()) is not None:", 
> which is way too clunky.

In your example "if ([x] := foo()) is not None:" there is no possible value 
returned by foo() that could be both falsy and match the [x] pattern at the 
same time. All patterns besides the ones I listed can only be matched by truthy 
values so the work-around would only be needed for those dubious patterns.

I think I'll experiment with a prototype when I have more time.
___
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/VFRVYISEETRVZE6ODA72L7I3V63M6KY7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Time to relax some restrictions on the walrus operator?

2022-05-08 Thread Valentin Berlier
> What if it does match, though?

The walrus operator returns the value on the right side so this wouldn't 
change. In your example the original dict would get printed.

some_dict  = {"x": 1, "y": 2}
print({"x": x} := some_dict)  # {"x": 1, "y": 2}

The only pattern where it's not possible to know if the pattern was matched by 
looking at the return value is the None pattern:

print(None := x) 

If the pattern matches this will print the value of x, None, and if the pattern 
doesn't match this will also print None because the walrus operator evaluates 
to None instead of the value on the right side when the pattern doesn't match. 
This is not a problem since testing for None is normally done with the is 
operator: x is None

The only patterns where it's not possible to know if the pattern was matched by 
looking at the truthiness of the return values are the following:

print(None := x)
print(False := x)
print(0 := x)
print(0.0 := x)
print("" := x)
print([] := x)
print({} := x)

This is not a problem since in all of these cases testing for truthiness is 
normally done with bool() or by testing the value directly in an if statement.

In my opinion the behavior is fairly unsurprising: return the right side if the 
pattern matches or None otherwise. We can even explain the current restricted 
behavior in terms of pattern matching: the name on the left side is an 
"irrefutable" pattern which will always match and therefore always return the 
right side of the expression.
___
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/YQRKWVCEAQ7D67ODF74IVBDLVXAQGQOL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Time to relax some restrictions on the walrus operator?

2022-05-08 Thread Valentin Berlier
A while ago there was a discussion about allowing "match" patterns for the 
walrus operator. This would cover iterable unpacking as you suggested along 
with all the patterns allowed in match statements.

if [x, y, z] := re.match(r"...").groups():
print(x, y, z)

The walrus expression would evaluate to None if the pattern on the left can't 
be matched.

print(x := 42)  # 42
print(1 := 42)  # None

This would make it really useful in if statements and list comprehensions. Here 
are a couple motivating examples:

# Buy every pizza on the menu
 cost_for_all_pizzas = sum(
 price for food in menu
 if ({"type": "pizza", "price": price} := food)
 )

# Monitor service health
 while Response(status=200, json={"stats": stats}) := health_check():
 print(stats)
 time.sleep(5)
___
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/HC7TAUYFTDMP52KAGDJFIB27KFSSI6C3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Regex pattern matching

2022-02-17 Thread Valentin Berlier
I see. I guess the ambiguity would stem from trying to force match objects into 
the sequence protocol even though the custom __getitem__() means that they're 
essentially a mixed mapping:

Mapping[int | str, str | None]

If we avoid any sort of "smart" length derived from only mo.groups() or 
mo.groupdict(), there's nothing stopping match objects from acting as proper 
mappings. We would need __iter__() which would simply yield all the available 
keys, including group 0 and all the named groups, and __len__() which would 
return the total number of keys.

My point is that the match object doesn't need to masquerade as something else 
to be useful, just implement the protocol to describe the available keys.

m = re.match(r"(a) (?Pb)(x)?", "a b")
list(m)  # [0, 1, 2, 3, 'foo']
dict(m)  # {0: 'a b', 1: 'a', 2: 'b', 3: None, 'foo': 'b'}

This means that pattern matching with mapping patterns would work 
automatically. The first example I shared would look like this:

match re.match(r"(v|f) (\d+) (\d+) (\d+)", line):
case {1: "v", 2: x, 3: y, 4: z}:
print("Handle vertex")
case {1: "f", 2: a, 3: b, 4: c}:
print("Handle face")

The second example would work without any changes:

match re.match(r"(?P\d+)|(?P+)|(?P*)", line):
case {"number": str(value)}:
return Token(type="number", value=int(value))
case {"add": str()}:
return Token(type="add")
case {"mul": str()}:
return Token(type="mul")
___
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/FUB4CD2DKPJV5QVKZEFJ6XBAFKIP4EZ6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Regex pattern matching

2022-02-16 Thread Valentin Berlier
Hi,

I've been thinking that it would be nice if regex match objects could be 
deconstructed with pattern matching. For example, a simple .obj parser could 
use it like this:

match re.match(r"(v|f) (\d+) (\d+) (\d+)", line):
case ["v", x, y, z]:
print("Handle vertex")
case ["f", a, b, c]:
print("Handle face")

Sequence patterns would extract groups directly. Mapping patterns could be used 
to extract named groups, which would be nice for simple parsers/tokenizers:

match re.match(r"(?P\d+)|(?P\+)|(?P\*)", line):
case {"number": str(value)}:
return Token(type="number", value=int(value))
case {"add": str()}:
return Token(type="add")
case {"mul": str()}:
return Token(type="mul")

Right now, match objects aren't proper sequence or mapping types though, but 
that doesn't seem too complicated to achieve. If this is something that enough 
people would consider useful I'm willing to look into how to implement this.
___
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/EKMIJCSJGHJR36W2CNJE4CKO3S5MW3U4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Python standard library TOML module

2021-12-10 Thread Valentin Berlier
Yes. This is desperately needed. Usually I'm not a big fan of adding new 
standard library modules but in this case since toml is becoming such a 
critical part of packaging it seems like a no-brainer.
___
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/B5T6TMAK2MSCQ4IV3VLRSFS6FBVGHRVN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Unpacking in tuple/list/set/dict comprehensions

2021-10-16 Thread Valentin Berlier
+1

I think this is a very sensible proposal and I encountered the use-cases you 
mentioned several times.
___
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/5ILYEOUJY7U2RZ6CFVVFHUZD2UFUNUCE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Typing Callable Ellipsis -- support for type hints a la Callable[[int, float, ...], None]

2021-09-21 Thread Valentin Berlier
You can do that with a custom protocol 
https://docs.python.org/3/library/typing.html#typing.Protocol
___
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/OHODQQX2TREFRTOVRIFYVQSLKGB2MVZI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Otherwise clause in for statement to run when a empty iterable is used

2021-09-14 Thread Valentin Berlier
I find that when I run into a similar scenario the reason why I need the 
iterable to be non-empty is because I'm trying to find something in it, and for 
this the `else` clause works pretty well:

for item in get_items():
if check(item):
do_thing(item)
break
else:
raise ValueError()

Early returns can also be useful:

for item in get_items():
if check(item):
return do_thing(item)
raise ValueError()
___
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/7PJDRJ6ESY5KT4VECU57P4PEPPOH4LK5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: We should have an explicit concept of emptiness for collections

2021-08-22 Thread Valentin Berlier
> (len(collection) == 0) is True

bool((len(collection) == 0) is True) == True
___
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/MAPJNXHXGE64QJWLZ27HDPU4NMTI52W5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-05-26 Thread Valentin Berlier
Now this is a really interesting proposal. Something wasn't right in the other 
discussion, I didn't think making variable decorators inconsistent with the 
current class and function decorators by providing the variable name was 
particularly good. I've always felt like that something like 
__decoration_call__ was missing, so I'm really grateful that someone took the 
time to think about it. I'd say this looks pretty promising, and I can't see 
any specific downside compared to the alternative proposals.
___
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/KX5ZOTCYLGLUT365VKE6U45HAISKI7ZC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: match expressions in python 3.10

2021-05-24 Thread Valentin Berlier
On the other hand I think extending the walrus operator would make the change 
less intrusive and the syntax more easily discoverable:

if match := re.match(r"...", some_string):
print(match[1], match[2])

if [_, a, b] := re.match(r"...", some_string):
print(a, b)  # Assuming match objects would then be made into proper 
sequences

Also, since it's not a new operator there's no need to worry about operator 
precedence. And since the current behavior of the walrus operator would already 
implement a subset of the proposed changes, I think it would reduce friction 
when deciding whether or not to adopt it.

One last point is that the new operator would lead to two equivalent constructs:

if thing.value matches foo:
...

if foo := thing.value:
...

I think using the "matches" operator like this would probably be frowned upon 
but that's yet another thing you would need to explain when teaching the 
language. Also, I can easily imagine some codestyle where the walrus operator 
would be considered obsolete as it would overlap with the "matches" operator 
while only providing a subset of the functionality, thus leading to 
fragmentation in the ecosystem.
___
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/6YUVCSL23YKSCKRDJXVUZW2XSGXAYCJM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: match expressions in python 3.10

2021-05-24 Thread Valentin Berlier
There was a discussion about this a couple months ago but instead of adding a 
new keyword the idea was that the walrus operator could be upgraded from simply 
being a binding operator to matching patterns supported by the match statement.

if ["example", *files] := variable:
print(files)

If the pattern doesn't match the expression would evaluate to None instead of 
the right hand side value. The current syntax would still work the same as it 
would be interpreted as an unconditional name binding pattern.

foo = [1, 2, 3]
assert ([] := foo) is None
assert ([a, b, c] := foo) is foo
assert (bar := foo) is foo  # No special case needed for the current behavior
___
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/67C6OWL5YOFYKXJGY6XI34JKJC6WBUGT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Comprehensions within f-strings

2021-05-03 Thread Valentin Berlier
I didn't even realize f'{n for n in row}' was already valid syntax. Since 
generator expressions can usually only appear within parentheses, I assumed the 
syntax wouldn't conflict with anything because you would need to parenthesize 
the generator to make it work. Anyway, now I see that the better option is to 
leave the interpolation as-is but introduce a conversion flag that can unroll 
any iterable, so the current behavior actually works in our favor here. This 
would indeed be more powerful than any specialized comprehension syntax.

print(''.join(f'{n:>8.3f}' for n in row) + f' | {sum(row):>8.3f}')
print(f'{row!u:>8.3f} | {sum(row):>8.3f}')

Now the second option is even more attractive in my opinion. I'm using !u for 
"unroll". The good news is that implementing a conversion flag is a much less 
intrusive change.
___
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/YBTB5WMSBZQPCIUPPMRLTYITPSSRPQRK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Comprehensions within f-strings

2021-05-01 Thread Valentin Berlier
Recently there's been some discussion around string comprehensions, and I 
wanted to look at a specific variant of the proposal in a bit more detail.
Original thread: 
https://mail.python.org/archives/list/python-ideas@python.org/thread/MVQGP4GGTIWQRJTSY5S6SDYES6JVOOGK/

Let's say i have a matrix of numbers:

matrix = [[randint(7, 50) / randint(1, 3) for _ in range(4)] for _ in range(4)]

I want to format and display each row so that the columns are nicely lined up. 
Maybe also display the sum of the row at the end of each line:

for row in matrix:
print(''.join(f'{n:>8.3f}' for n in row) + f' | {sum(row):>8.3f}')

This gives me a nicely formatted table. Now with the proposal:

for row in matrix:
print(f'{n for n in row:>8.3f} | {sum(row):>8.3f}')

The idea is that you would be able to embed a comprehension in f-string 
interpolations, and that the format specifier at the end would be applied to 
all the generated items. This has a few advantages compared to the first 
version. It's a bit shorter and I find it easier to see what kind of shape the 
output will look like. It would also be faster since the interpreter would be 
able to append the formatted numbers directly to the final string. The first 
version needs to create a temporary string object for each number and then feed 
it into the iterator protocol before joining them together.
___
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/HSTXKN7OUUR34IXLVMXR65XVPNWPVEL5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: String comprehension

2021-05-01 Thread Valentin Berlier
> But that was not the primary motivator for adding them to the language.

I don't think the original author thinks that way either about string 
comprehensions. I was asked about the kind of speed benefits that string 
comprehensions would have over using a generator with "".join() and I used 
f-strings as an example because the benefits would be similar.

By the way now that i think about it, comprehensions would fit into f-string 
interpolation pretty nicely.

f"""
Guest list ({len(people)} people):
{person.name + '\n' for person in people}
"""

> Which massively reduces the possible kinds of comprehensions one might write, 
> and I suspect most of those are already covered by string methods.

I actually replied to David Mertz about this. String comprehensions can derive 
substrings from any iterable. Just like the only requirement for using a 
generator expression in "".join() is that it produces strings. Comprehensions 
can also have nested loops which can come in handy at times. And of course this 
doesn't mean I'm going to advocate for using them with complex predicates.
___
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/J4UNAY3QY7M34UU5OIMZJCZR5XV7O676/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: String comprehension

2021-05-01 Thread Valentin Berlier
> you talked about builtin *iterables*

My mistake, I reused the terminology used by the original author to make it 
easier to follow.

> The point of iterators like map, zip and filter is to *avoid* performing the 
> computation until it is required.

Of course. Maybe I wasn't clear enough. I don't know why we're bringing up 
these operators in a discussion about comprehensions. And what would a "range" 
comprehension even look like? To me the fact that there's no comprehensions for 
enumerate, filter, map, range, reversed and zip doesn't contribute to making 
dict, list and set exceptional cases.

As I said we're left with bytearray, frozenset and memoryview. These are much 
less frequently used and don't even have a literal form so expecting 
comprehensions for them would be a bit nonsensical. On the other hand strings, 
bytes, lists, dicts and sets all have literal forms but only lists, dicts and 
sets have comprehensions. Three out of five doesn't make them exceptional cases 
so it's only logical to at least consider the idea of adding comprehensions for 
strings (and bytes) too.
___
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/MU5CMPQJ2REDMDOKHFJTJCF2B3F5LIPN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: String comprehension

2021-04-30 Thread Valentin Berlier
> The builtin interables bytearray, bytes, enumerate, filter frozenset, map, 
> memoryview, range, reversed, tuple and zip suggest differently.

enumerate, filter, map, range, reversed and zip don't apply because they're not 
collections, you wouldn't be able to store the result of the computation 
anywhere. bytes comprehensions would make sense if string comprehensions are 
added. This leaves us with bytearray, frozenset and memoryview. How often are 
these used compared to strings, dicts, and lists?

> If we were re-designing Python from scratch today, it is quite likely that we 
> would have only generator comprehensions

I don't know about this, but unless everything besides generator expressions 
get deprecated the current comprehensions are here to stay and string 
comprehensions would fit perfectly alongside them (this is my opinion).
___
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/JAGVQPSYUJAMVH4LCMLA6GJDH55ET2JJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: String comprehension

2021-04-30 Thread Valentin Berlier
> c"f(c) for c in some_string if g(c)"

Even this example would allow the interpreter to skip building the generator 
object and having to feed the result of every f(c) back into the iterator 
protocol. This is similar to f-strings vs str.format. You could say that 
f-strings are redundant because they can't do anything that str.format can't, 
but  they make it possible to shave off the static overhead of going through 
python's protocols and enable additional optimizations.
___
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/UPXU2CNCACBAO7EV4XI3MMKZDAFSHTAA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: String comprehension

2021-04-30 Thread Valentin Berlier
> the ONLY predicate that can be expressed about a single character is it being 
> a member of a subset of all Unicode characters

You seem to be assuming that the comprehension would be purposefully restricted 
to iterating over strings. The original author already provided examples with 
predicates that don't involve checking for a subset of characters.

old = [0, 1, None, 2]
new = c"str(x + 1) for x in old if isinstance(x, int)"

The existing "".join() idiom isn't restricted to iterating over an existing 
string. You also have to account for nested comprehensions. There's nothing 
that would prevent you from having arbitrary complexity in string comprehension 
predicates, just like nothing prevents you from having arbitrary predicates 
when you join a generator expression.
___
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/6T7NQT5HFVYSI3RHUCBDDCEWKJ7HDPZG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: String comprehension

2021-04-30 Thread Valentin Berlier
It's kind of weird that people seem to be missing the point about this. Python 
already has comprehensions for all the iterable builtins except strings. The 
proposed syntax doesn't introduce any new concept and would simply make strings 
more consistent with the rest of the builtins.  The argument that we can 
already do this with the "".join() idiom is backwards. It's something we have 
to do _because_ there's no way to write a string comprehensions directly. 
Comprehensions express intent. Joining a generator expression with an empty 
string doesn't convey the intent that you're building a string where each 
character is derived from another iterable.

Also I haven't seen anyone acknowledge the potential performance benefits of 
string comprehensions. The "".join() idiom needs to go through the entire 
generator machinery to assemble the final string, whereas a decent 
implementation of string comprehensions would enable some pretty significant 
optimizations.
___
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/CYCM35RAKL7PMPGE2VYQ2ZPKK5RSMEZM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add venv activate command to the venv modules

2021-01-04 Thread Valentin Berlier
To get around the fact that activating a virtualenv requires setting 
environment variables in the current shell poetry has a shell command that 
simply spawns a new shell with the appropriate environment variables: 
https://python-poetry.org/docs/cli/#shell

So a cross-platform `activate` command wouldn't be possible but something like 
this could:

$ python -m venv venv_name shell
(venv_name) $ # the virtualenv is now active
(venv_name) $ exit
$ # back into the parent shell
___
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/AOUNEH6HA6QC7KE7WRRYXSP6FSVOTJ5P/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Function for fetching what months between two dates

2020-12-15 Thread Valentin Berlier
Hi. Bundling this into the standard library doesn't seem to provide any real 
advantage over defining it as a free-standing utility function in your own 
code. 

And if it's in your own code you can easily tweak it if you need to :)
___
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/26U3IAZ4IBNL7KKKCV7O5Q6KOSEJZLXQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Make for/while loops nameable.

2020-12-04 Thread Valentin Berlier
I think this is the kind of feature that can very easily be abused. Whenever I 
want to break out of a nested loop I take this as an opportunity to extract the 
loop into its own function and use the return statement to break out of the 
loop. IMO this is a lot better than having named or indexed loop control 
because a proper function can later be reusable, and it lets you explain why 
you need to return early in the docstring.
___
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/SMU7CAFHWQROQYLWK3HEL5XDDRXKU46Z/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: [RFC] Built-in shorthand b() for breakpoint()

2020-12-02 Thread Valentin Berlier
Single-letter variables are common. If your use-case is inserting breakpoints 
into arbitrary library code there's no way to guarantee that the builtin won't 
be shadowed by some arguments or other local variables, making your alias 
extremely unreliable.

def add(a, b):
"""Arbitrary library code."""
b()  # This will fail because the argument shadows the builtin
return a + b

Sure you could argue that the `breakpoint` builtin is affected by shadowing 
too, but it's much less common to have a variable named `breakpoint` than `b`.

I think an even worse consequence would be the cryptic error message that 
beginners would be likely to encounter in programming tutorials.

Quick example:

def add(a):  # Assuming some kind of tutorial about functions
return a + b

NameError: name 'b' is not defined

Let's imagine that the beginner made a mistake and forgot to declare the second 
argument. The error message is clear, but with your `breakpoint` alias this is 
what the interpreter will print out:

TypeError: unsupported operand type(s) for +: 'int' and 
'builtin_function_or_method'

Really confusing. I highly oppose this.
___
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/4VB2TQRS5DLSYN3UVXL7PPTFWMC3ZPB4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Move semantics

2020-11-27 Thread Valentin Berlier
The C++ example specifically shows that if you're talking about ownership and 
lifetimes, you're not talking about move semantics. As you pointed out, the 
example wouldn't work in Rust specifically because Rust has a borrow checker, 
and not just move semantics.

A compiler with a borrow checker will perform move optimizations, which at 
runtime result in behavior similar to C++ move semantics. So I'm pointing out 
that in this thread, we're really talking about borrow checking with 
declarative lifetimes more than move semantics.
___
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/DNZP5Z372TFTT2QDXHQYQ7SM5OGDTAZQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Move semantics

2020-11-27 Thread Valentin Berlier
This thread is a mess. Move semantics is nothing more than creating a shallow 
copy that steals the inner state of a previous instance. It's an optimization, 
and moving out of a variable never makes the previous instance unusable:

void f1(std::vector&& vec);

void f2() {
std::vector vec;
f1(std::move(vec));

vec.push_back(2); // This compiles just fine
}

Since move semantics are a pass-by-value optimization, they can't exist in 
python where calling any kind of function simply shares bindings. In python no 
matter how hard you try you'll never run into the "hollow" instances that move 
semantics leave behind.

Some of the use-cases described in this thread are actually about borrow 
checking: making it possible to terminate the semantic lifetime of a variable 
by passing it to a function. Manually propagating lifetime restrictions through 
type annotations is definitely possible, and could be supported with a mypy 
plugin, but it will be very verbose, and without any kind of "constness" in the 
language the added safety will be pretty limited.
___
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/XFLGRVBLGD7P2TLT6Z55QK6356676A5H/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 634-636: Mapping patterns and extra keys

2020-11-17 Thread Valentin Berlier
I'm in favor of keeping the PEP as it currently is. Mappings are naturally 
structural subtypes of one another, therefore mapping patterns should be 
consistent with class patterns. 

car = Car(...)

match car:
case Vehicle():
pass
case Car():  # will never match
pass

This example is analogous to the first one in the discussion. If Car is a 
subclass of Vehicle, then Vehicle() is a more general pattern than Car() and 
will always match despite the instance not being exactly of type Vehicle. With 
mapping patterns it's exactly the same thing. You need to match the more 
specific patterns first. Matching x and y is more general than matching x, y 
and z.

One more thing. If we compare the proposed behavior to other languages the most 
relevant example would be object destructuring in javascript:

const { 'x': x, 'y': y } = { 'x': 1, 'y': 2, 'z': 3 };
const { x, y } = { x: 1, y: 2, z: 3 };  // more common short form

Object destructuring only matches the specified fields. You can also match the 
remaining fields but it's always explicit:

const { x, y, ...rest } = { x: 1, y: 2, z: 3 };
console.log(rest);  // { z: 3 }

The pattern is widely adopted and the behavior generally lines up with people's 
expectations.
___
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/52L3EQ5FUBXDZRFAU4D4PESMZ6GUGIHC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 634-636: Mapping patterns and extra keys

2020-11-17 Thread Valentin Berlier
I'm in favor of keeping the PEP as it currently is. Mappings are naturally
structural subtypes of one another, therefore mapping patterns should be
consistent with class patterns.

car = Car(...)

match car:
case Vehicle():
pass
case Car():  # will never match
pass

This example is analogous to the first one in the discussion. If Car is a
subclass of Vehicle, then Vehicle() is a more general pattern than Car()
and will always match despite the instance not being exactly of type
Vehicle. With mapping patterns it's exactly the same thing. You need to
match the more specific patterns first. Matching x and y is more general
than matching x, y and z.

One more thing. If we compare the proposed behavior to other languages the
most relevant example would be object destructuring in javascript:

const { 'x': x, 'y': y } = { 'x': 1, 'y': 2, 'z': 3 };
const { x, y } = { x: 1, y: 2, z: 3 };  // more common short form

Object destructuring only matches the specified fields. You can also match
the remaining fields but it's always explicit:

const { x, y, ...rest } = { x: 1, y: 2, z: 3 };
console.log(rest);  // { z: 3 }

The pattern is widely adopted and the behavior generally lines up with
people's expectations.
___
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/I65QIOZNEIMJSE6YP2VNJGAXM3KOFM56/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Dict unpacking assignment

2020-10-24 Thread Valentin Berlier
I think that instead of dict unpacking specifically, what we need is to come up 
with a way to use the pattern-matching proposed in PEP 634 outside of match 
statements. This would make it possible to unpack any pattern.

My opinion is that the walrus operator is practically waiting to support 
pattern-matching:

if Response(status=200, json={"title": title}) := get('/posts/42'):
print(title)

I wrote a few more examples here:

- 
https://mail.python.org/archives/list/python-ideas@python.org/thread/MJ7JHYKHKB2T4SCFV4TX4IMKUANUAF5B/

-- 
Valentin
___
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/ZWFMZH7QCOQHXPFGHAWOI74OSUAPCWGL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extrapolating PEP 634: The walrus was waiting for patmat all along

2020-10-24 Thread Valentin Berlier
> Why should a failed match return None? That's not helpful if it matches 
> but the value itself is None.

The only pattern that would match `None` is this one:

print(None := get_value())  # Always None

Here, the walrus operator would always return `None`. Either because the 
function returned `None` or the function returned something else and the 
pattern didn't match. The behavior is consistent, this particular pattern is 
just not that useful. Pattern-matching shouldn't exempt you from checking for 
`None` with the `is` operator anyway:

print(get_value() is None)  # True or False

The proposed semantics don't get in the way of idiomatic python. Most of the 
time you only care about the truthiness of the value returned by the walrus 
operator. The most common example would be with regular expressions:

price_tag = "Price: $7"

if match := re.match(r".*(\d+).*", price_tag):
print(match[1])

By the way I'm hoping that with PEP 634 `Match` objects can become proper 
`collections.abc.Sequence` instances. This would allow regex destructuring:

if [_, amount] := re.match(r".*(\d+).*", price_tag):
print(amount)

-- 
Valentin
___
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/7GWNFOLPAASUZCXAXAAUWFX7APVGNM4X/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extrapolating PEP 634: The walrus was waiting for patmat all along

2020-10-24 Thread Valentin Berlier
> If you look in PEP 622 you'll see that there was a rejected idea `if
> match ...` that's pretty similar. We nixed it because it just made the
> PEP larger. For 3.11 we can consider something like this.

Of course I understand the PEP is already pretty big. But if it goes
through and we start thinking about extending it with `if match`
statements, my point is that it would be worth considering extending the
walrus operator instead :)
___
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/EEJ27EVCQJTAPTWO6SRRHOOARRLSJJVT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Extrapolating PEP 634: The walrus was waiting for patmat all along

2020-10-23 Thread Valentin Berlier
Pattern-matching is great. I think PEP 634 is on the right track, but it 
would be a waste to only use pattern-matching for choosing a branch in a 
match statement.


Let’s look at Rust:

if let [x, y] = my_array {
...
}

Rust "if let" constructs are an alternative to full-blown match 
statements that make it less verbose to match a single pattern.


We have a similar problem. The syntax proposed by PEP 634 is pretty 
verbose for matching a single pattern:


match my_list:
case [x, y]:
...

Two keywords and two indentation levels. We can do better:

if [x, y] := my_list:
...

Yes, your first intuition is right. This looks similar to the Rust 
version but would work completely differently. But hear me out. Let's 
look past my terrible example and focus on the idea.


1. The walrus operator was purposefully designed to create bindings and 
not to perform assignments to arbitrary lvalues.

2. Matching a pattern only introduces bindings as well, no assignments.
3. The current behavior of the walrus operator is equivalent to matching 
the right-side operand to an "irrefutable" capture pattern.


Allowing the walrus operator to do pattern-matching would simply make 
the returned value conditional. If the pattern doesn't match, the walrus 
operator returns None.


print(x := 42)  # 42
print(1 := 42)  # None

The current PEG parser would backtrack when encountering the walrus 
operator to interpret the left-side as a pattern.


Finally, more examples:

# Buy every pizza on the menu
sum(
price for food in menu
if ({"type": "pizza", "price": price} := food)
)

# Download all images from document
{url: download(url) for tag in html if (Img(src=url) := tag)}

# Monitor service health
while Response(status=200, json={"stats": stats}) := health_check():
print(stats)
time.sleep(5)

I'm convinced that making the walrus operator a pattern-matching 
operator would turn it into the perfect companion for PEP 634. What do 
you think?


References:

- PEP 634: https://www.python.org/dev/peps/pep-0634/
- Rust "if let": https://doc.rust-lang.org/book/ch06-03-if-let.html

--
Valentin
___
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/MJ7JHYKHKB2T4SCFV4TX4IMKUANUAF5B/
Code of Conduct: http://python.org/psf/codeofconduct/