destructuring with if let¶
shorthand for a one-variant peel of an enum or optional value:
the pattern left of := is any match pattern, the clause is taken when the
pattern matches the subject on the right, and the pattern's captures are bound
for the body
elif let works the same way, and mixes freely with ordinary conditions. a
subject is only evaluated once every earlier clause has failed, exactly as a
condition in that position would be
if shape is Square:
print(shape.side)
elif let Shape.Circle(r) := shape:
print(r * 2)
else:
print("something else")
narrowing¶
a clause narrows like the match case it stands for — the captures inside the
body, and the subject in every branch:
def describe(v: int | str) -> str:
if let int(n) := v:
reveal_type(n) # int
reveal_type(v) # int
return f"int {n}"
else:
reveal_type(v) # str
return v
captures leak¶
a capture stays bound after the statement, possibly unbound when the pattern did
not match — the same rule walrus bindings and match captures follow
let is not a keyword here¶
let only introduces a pattern when the clause really is
let <pattern> := <subject>; everywhere else it stays an ordinary name, so
if let := f(): is still a walrus test on a variable called let
Some is not a pattern¶
Some(x) builds an optional, it is not a class, so it cannot appear in pattern
position — if let Some(x) := opt: is rejected. peel an optional by matching
the type it wraps (if let int(n) := opt:), which narrows away the None just
the same
lowering¶
there is no python spelling that keeps a match inside an if header, so the
whole chain flattens onto a selector variable: each clause header becomes a
guard that records which clause was taken, followed by a plain if that runs
the original body
__by_if_let_0__ = 0
match shape:
case Shape.Circle(r):
__by_if_let_0__ = 1
if __by_if_let_0__ == 1:
print(r * 2)
if __by_if_let_0__ == 0:
print("not a circle")
del __by_if_let_0__
only the headers are rewritten, so every body keeps its own source. match is
python 3.10 syntax, so if let needs a target of 3.10 or later
a clause takes any pattern destructuring does, including an
and pattern, and binds with := for the reasons set out there — writing =
is reported
open questions¶
while letfor loop-and-peel iteration- a guard clause (
if let P := s if cond:), whichmatchcases have