This is one of the reasons why PEP 638 might fill a real gap. As I understand it, we could without much effort have a list!
macro that expands into the generator you wrote, and assembles the list.
Yes, exactly this is the reason why I started this analysis conditional-expression/results.md at main ¡ 15r10nk/conditional-expression ¡ GitHub . I want to get a feeling of the impact of this idea.
It is not complete jet, but I hope that it will provide some insightful data.
There is no reason to push this if there are too few use cases, because people would be surprised by the syntax if they are not read/use them frequently.
Thank you for this great explanation. This will help me to study the history of this syntax.
I think something like
f(1, 2, conditional!( a = 3 if condition))
Could be transformed to
f(1, 2, **({"a":3} if condition else {}))
This would be crazy. And I fear what would happen if everyone would write such crazy stuff.
One reason I like python is that everything has a well defined simple semantic.
Hmm, I really donât know if I would love or hate it.
Just my opinion: I believe conditional arguments might be a difficult ask to start with. However, something like the collection-if
from dart could be a great first step and prove to be quite useful.
After you know how to use it, itâs something that feels natural and at least I use it a lot when writing dart
. So much so that I wondered myself why Python canât do this as well.
What I meant was @Rosuavâs F# example for conditional elements, not the conditional arguments. The syntax is so close that you only need to stick a Yield
node into every Expr
node you encounter in the AST.
Quick demo using ast.parse on function source
import ast
import inspect
class YieldExpr(ast.NodeTransformer):
def visit_Expr(self, node):
node.value = ast.Yield(node.value)
return node
def list_macro(func):
source = inspect.getsource(func)
while source.startswith('@'):
_, source = source.split('\n', 1)
node = ast.parse(source)
newnode = ast.fix_missing_locations(YieldExpr().visit(node))
results = {}
exec(compile(node, inspect.getfile(func), 'exec'), func.__globals__, results)
return list(results[func.__name__]())
foo = False
bar = True
fruits = [4, 5]
status = 400
# as a macro, this could just be "list! items:"
@list_macro
def items():
6+8 # unconditional emit
if foo:
1+1 # conditional emit
if bar:
2+2 # conditional emit
# emit governed by a loop
for x in fruits:
3+x # loop with emit
# emit governed by a match
match status:
case 400:
400+2
case 404:
404+10
print(items)
# [14, 4, 7, 8, 402]
With PEP 638 that would i) work in a non-horrible manner, ii) be constructed at compile-time, and iii) be available under a good-looking macro name.
I like this approach and this concept very much! It would be great if it will be added to Python!
A couple of times when I had to write a collection in this style, the way I implemented this was with filter
:
h=filter(None, (
(cookie.name, cookie.value),
('path', cookie.path),
('domain', cookie.domain),
('port', cookie.port) and cookie.port is not None,
('path_spec', None) and cookie.path_specified,
('port_spec', None) and cookie.port_specified,
('domain_dot', None) and cookie.domain_initial_dot,
('secure', None) and cookie.secure,
('expires', time2isoz(float(cookie.expires))) and cookie.expires,
('discard', None) and cookie.discard,
('comment', cookie.comment) and cookie.comment,
('commenturl', cookie.comment_url) and cookie.comment_url,
))
I do agree that the way you write it here is much more natural-sounding.
Guess what youâre really after is âdefault argument valueâ. Similar topics have been raised times and again on this forum. Basically Python lacks a way for callee to identify some arguments of being taken default values by default, and lacks a way for caller to specify a parameter to be passed its default value.
Please use the Help category to ask questions. Do not resurrect a year old topic.