Just saying "dynamic typing is easier" doesn't do it for me without further qualification since that statement doesn't conform to my own experience.
Just saying "dynamic typing is easier" doesn't do it for me without further qualification since that statement doesn't conform to my own experience.
If you declare a function parameter as `foo: int = None`... that is just an incorrect declaration. Of course a variable annotated as `int` can take a `None` value, but that is because any variable can take any type in Python. Within the Python type (annotation) system it is simply the case that an `int` and an `int | None` are two different things, as they are in other languages (eg Rust's `T` vs `Option<T>` types).
Mypy used to support the "implicit optional" feature you describe but now you must make nullable arguments explicitly optional. This is in line with Python's "explicit is better than implicit" design philosophy. In any case, how long does it take you to just type `foo: int | None = None`? Or you could re-enable the old behavior to allow implicit optionals with `--implicit-optional` or the corresponding config file option. It seems like you just need to configure mypy to match your preferences rather than fighting with its defaults.
To return to the broader point, I'm unsure what an "irrelevant type warning" is, but I suspect that has something to do with my lack of appreciation for dynamic typing. Can you give an example that isn't just a complaint about typing an extra 6 characters or about mypy being misconfigured for your preferences?
No, it is correct. The value None is not with the domain of type int, a parameter that can take the value None does not in fact have type int.
> This yields no value because when you say `= None` you are saying that this is an optional argument.
When you provide any default value, you are making the argument optional, but that's an orthogonal concern to the Optional[T] type, which doesn't mean “optional argument", it is simply a more convenient way of expressing Union[T, None], though with the modern type syntax, T | U is generally more convenient than either Union[T, U] or Optional[T] for U=None.
Please excuse my pedantry: That would seem to lead to the question …
I can see how it appeared that I was using the phrase in the incorrect way! That usage bothers me too, and I am attentive to it.
Because you can run your program to see what it does without having to appease the type checker first.
There is nothing wrong with presenting type hints or type errors as warnings. The problems arise when the compiler just flat-out refuses to run your code until you have finished handling every possible branch path.
fn main() {
let x: i32 = if true {1} else {"3"};
println!("{}", x);
}
This will not compile even though if it were allowed to execute it would, correctly, assign an integer to x. Python will happily interpret its equivalent: x = 1 if True else "3"
print(x)
Even giving the if-expression an explicit `true` constant for the condition, Rust won't accept that as a valid program even though we can prove that the result of the expression is always 1."Can not" and "will not" are kind of the same thing in this context. It's not like compilers have free will and just decide to give you a hard time. It's the language design that makes it (im)possible to run code that won't type-check.
This means you can only really rely on the parts of your program which are type correct, so...
Surely you can't be against putting a TODO in an unfinished part of the code?
Who are you to tell me what I want? You are making all manner of tacit assumptions about the kind of work I do and what my requirements are. I absolutely do want the compiler filling in every hole it possibly can. For me, that's the whole point of using a high-level language in the first place. For the kind of work I do, what matters most is getting things done as quickly as possible. Correctness and run-time efficiency are secondary considerations.
But for people who prioritize precision and correctness, that's what programming languages were invented for.
But yeah, if all you need to do is build a vanilla app then an LLM is probably an effective tool.