New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document design about implicit casting and implicit typing #2168
Comments
I'm in favor of small changes with small blast radius and minimal risk of breakage down-the-line. I think static, strong typing, despite the need for explicit type notations, is more valuable than syntactic convenience except in ONE case: constructors.
This:
some_var : MyClassFactoryProxyStubInterface = MyClassFactoryProxyStubInterface(my_arg1, my_arg2)
is needlessly verbose, and can robustly be shorted to
some_var = MyClassFactoryProxyStubInterface(my_arg1, my_arg2)
or
some_var : MyClassFactoryProxyStubInterface(my_arg1, my_arg2)
The guiding principle is "The Law of Demeter," which states that "if understanding some declaration requires me to search other places and files, then the declaration is too implicit." In other words, if the types are not understandable by a human AT-A-GLANCE, then the type notation is too loose.
|
The issue with
Where the For the long struct names, another idea is:
Which makes it a lot shorter. One advantage of requiring
and
But the "var" syntax
Because now we have the "action at a distance", we should only allow implicit typing from the single statement; this is multiple statements. Instead of "var", maybe we can do:
As an alternative syntax for:
That way it can't be used for anything else than structs, you HAVE to initialize it, i.e., It's not clear ot me it is worth doing, but we can. I recommend for now let's type everything explicitly and see. Once we gain more experience, let's find a simpler syntax for some of these more annoying cases. |
"Action at a distance" is a violation of the Law of Demeter, so I don't like it. I much prefer "type aliases," i.e., MyTypeAlias = SomeGiganticUglyCombinationOfLongNamesAndTypeCombinatorsLikeUnionListDictAndTuple
some_var : MyTypeAlias = MyTypAlias(arg1, arg2, ...) |
btw i use type aliases heavily in the pure-Python version of lasr https://github.com/rebcabin/lpython/tree/brian-lasr/lasr/cpython, e.g., Line = int
Col = int
LTType = Optional[str]
LTVal = Optional[Union[str, int]]
FullForm = Dict[str, Any | Dict[str, Any]] |
The implicit casting are things like
2 * x
wherex
isf64
, as well as automatic casting of arguments to functions. It is allowed in some languages, but not all. For example in Rust no implicit casting is allowed. We currently do not allow any implicit casting either.A separate question is implicit typing, where the compiler infers the type from the right hand side. In Rust one has to always type functions, but inside functions one can use implicit typing. The author of Rust expresses some regret about this in https://graydon2.dreamwidth.org/307291.html:
An example of this would be https://doc.rust-lang.org/rust-by-example/types/inference.html:
This is similar to implicit typing in LFortran, where we have to come back to fix up the type, depending on how it used (in there it is regarding if
f
is a variable or a function). This is hard to implement and make correct in all cases, and it is also confusing to the user, since the type off
can change retroactively, by how it is used later in the code.Right now LPython does not do any implicit typing.
The main advantage of the current design is that we can always add this later, but if we add some now and later realize we added too much, we cannot take it away without breaking compatibility. The second advantage is that it might also be the right design for us, or close to it.
The third case are implicit declarations. I think Rust doesn't allow that, you always have to explicitly declare using
let
. In LPython, currently we have to dof: f32 = f32(5)
. Here thef32
on the left has two functions, one is explicit type, the other is explicit declaration. If we relax it to justf = f32(5)
then we have implicit declaration and implicit type. Finally, we could do something likef: Var = f32(5)
which would be explicit declaration and implicit type. The issue with implicit declarations is that it's easy to make a mistake and reassign to an already existing variable when that was not meant to be by the user. By always having to explicitly declare it (whether with explicit type likef: f32
or implicit type likef: Var
) the compiler will check that the variable is not redeclared, avoiding mistakes. LPython currently does not allow implicit declarations.In conclusion, LPython currently does not allow:
In comparison, Rust doesn't allow implicit casting and implicit declarations, but it allows implicit typing, although I think it went too far, see above.
The text was updated successfully, but these errors were encountered: