Skip to content

Commit a738a07

Browse files
committed
document infinity and nan float-literal types
1 parent 8fac42c commit a738a07

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# infinity and not-a-number float literals
2+
3+
python has no literal syntax for the special floating-point values, so they have
4+
no literal *type* either — an annotation cannot say "this is infinity". basedpython
5+
adds three special float-literal types, written as attributes of `float`:
6+
7+
- `float.inf` — positive infinity
8+
- `-float.inf` — negative infinity
9+
- `float.nan` — not-a-number
10+
11+
they exist only in **type positions**. the transpiler erases each to plain `float`
12+
in the emitted python, since the runtime has no spelling for them:
13+
14+
```by
15+
def clamp(lo: -float.inf, hi: float.inf) -> None:
16+
...
17+
```
18+
19+
transpiles to:
20+
21+
```python
22+
def clamp(lo: float, hi: float) -> None:
23+
...
24+
```
25+
26+
## the literal types
27+
28+
bound as parameters so the inferred type can be revealed:
29+
30+
```by
31+
def f(pos: float.inf, neg: -float.inf, nan: float.nan) -> None:
32+
reveal_type(pos) # revealed: inf
33+
reveal_type(neg) # revealed: -inf
34+
reveal_type(nan) # revealed: nan
35+
```
36+
37+
## each is a subtype of `float`
38+
39+
a special float literal is assignable to `float`, but a plain `float` is not
40+
assignable back to the literal — same direction as any literal-to-base relation:
41+
42+
```by
43+
def f(inf: float.inf, x: float) -> None:
44+
a: float = inf
45+
b: float.inf = x # error: [invalid-assignment]
46+
```
47+
48+
## infinities keep their sign
49+
50+
`float.inf` and `-float.inf` are distinct types — a positive infinity is not a
51+
negative one:
52+
53+
```by
54+
def f(pos: float.inf) -> None:
55+
neg: -float.inf = pos # error: [invalid-assignment]
56+
```
57+
58+
## nan is signless
59+
60+
a nan carries no sign, so `-float.nan` is the same type as `float.nan`:
61+
62+
```by
63+
def f(nan: float.nan) -> None:
64+
also_nan: -float.nan = nan
65+
reveal_type(also_nan) # revealed: nan
66+
```
67+
68+
## type-position only
69+
70+
these are *types*, not values. python's runtime `float` has no `inf` / `nan`
71+
attribute, so writing `float.inf` in a value position is rejected by the checker
72+
and would fail at runtime — use the standard library (`math.inf`, `math.nan`, or
73+
`float("inf")`) for the actual values:
74+
75+
```by
76+
x: float = float.inf # error: [unresolved-attribute]
77+
```

docs/basedpython/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ basedpython is a Python-like language that transpiles to pure Python
2929
- [`typeof` keyword](features/typeof.md)
3030
- [star projections (`X[*]`)](features/star-projection.md)
3131
- [strict `float` and `complex`](features/no-number-promotions.md)
32+
- [infinity and nan float literals](features/float-literals.md)
3233
- [literal type promotion](features/literal-types.md)
3334
- [symbolic operations in types](features/symbolic-type-ops.md)
3435
- [typed dict literals](features/typed-dict-literal.md)

0 commit comments

Comments
 (0)