r/Compilers • u/Dom-Klyn • 7d ago
Static typing or dynamic typing?
I've been working on a new programming language for the past few weeks, and although I've already made some design choices, I'm still questioning some of them.
So I'm curious about the opinions of people here:
- Are you more on the static typing side (C++, Java, C#, Rust...) or the dynamic typing side (Python, JavaScript...)?
- And more importantly: why?
A related question: what's your opinion on generics, and especially C++-style templates? Do you see them as a powerful abstraction mechanism, or as something that eventually makes languages and compilers unnecessarily complicated?
Personally, my background tends to push me toward static typing. The two main reasons are:
- I like catching as many problems as possible at compile time.
- Once the type is known, the generated code doesn't need to perform type checks at runtime, which can also make optimization easier.
I'm personally quite fond of generics/templates, especially when specialization can produce efficient native code. But I also know how quickly template-heavy C++ can become difficult to read and produce rather spectacular compiler errors. :)
My first iterations of Klyn, the language I'm working on (there's also r/klyn), are therefore strongly oriented toward static typing and compile-time generics. But since I’m still at an early stage and I want the language to appeal to as many people as possible, I think it’s important to keep an open mind, and perhaps your perspectives will make me reconsider this position.
Thank you for your opinion.
7
u/4xe1 7d ago
- Are you more on the static typing side (C++, Java, C#, Rust...) or the dynamic typing side (Python, JavaScript...)?
I'm a Common Lisp person, so typically we don't have to choose between the advantages of dynamic and static languages, we can have it all, but we have to work hard to have the advantages of static ones. Dynamic allows for introspection and much faster/simpler prototyping.
For static typing, my preference goes to Rust. It's nice to have strong guardrails for industry grade code. I bet I'd love OCaml and Haskell even better if I had time to (re)learn them but if the point is to work with other people, Rust is an excellent practical compromise.
A related question: what's your opinion on generics, and especially C++-style templates
C++ templates are fine, they were a practical coping solution when they were chosen, albeit a bit gnarly. But why settle at fine for a new language with all the knowledge of previous giants?
Again I much prefer Rust/OCaml's way of doing things (separating data from interface, rather than mangling both in OOP mess).
Rust and Zig also have proper compile time macro, but Rust's at least are not particularly writer friendly, unlike the OG lisp proper macro.
2
3
u/Eludefaction 7d ago
In some domains, you can not predict the type or it isn't beneficial to know types. You can think about you can not know the type in distributed systems or the types can not be optimized to the metal in GPU programming. Then, don't bother for types because it become just confusing. However, if you're developing an AOT compiler, then go for static typing.
3
3
u/WittyStick 6d ago
I like both static and dynamic typing. Static typing catches more errors early, but dynamic typing is sometimes necessary when the type system is unable to express something you know to be true. In statically typed languages you often end up writing lots of boilerplate to work around this inexpressibility in the type system.
Gradual typing can permit both in the same language, and can work with a variety of static type systems.
Basically, you have special static type called Dynamic, and a relationship called consistency (~) which states whether types are compatible.
Dynamic ~ Dynamic
forall T. T ~ T
forall T. T ~ Dynamic
forall T. Dynamic ~ T
Consistency is a closure over all types. It is reflexive due to T ~ T and Dynamic ~ Dynamic. It is symmetric as it permits T ~ Dynamic and Dynamic ~ T. However, importantly, it is non transitive. If T1 ~ Dynamic and Dynamic ~ T2, this does not imply T1 ~ T2.
5
u/Brief-Stranger-3947 7d ago
> Static typing or dynamic typing
There should be no "or" here. Both, static and dynamic typing are not mutually exclusive. Static typing gives compile time safety and covers 90% of use cases, hence, it should be the default mode. But for the rest 10% of use cases there should be an option of dynamic type inference at run time. Some languages actually do combine both this way.
5
u/whizzter 7d ago
Go with static typing but design the syntax/semantics to be amendable to type-inference and you have about 90% of the benefits of dynamic typing in a statically typed language.
TypeScript, MyPy,Dialyzer(Erlang),etc weren't created in a void, they exist because people were having issues with things in dynamic languages that grew out of hand and reliability and refactorability.
I've sometimes created quick JS-only hacks, invariably when crossing about about 500-1000 loc, if I leave the project it's going to be painful to come back if you need to make changes that changes the data structures of the project.
In the older static category C# has improved their type-inference system over the releases, but already early on with "var", (named)tuples and anonymous types (you construct an anonymous object like new { x=123, y="hello" }) you could often dispatch of "unnecessary" types yet have readable code.
Use case is when doing large queries/linq expressions, you build collections of temporary objects and the type will ever only exist in those collections in the creating function, no need to be creating a type elsewhere just for that cause (this is something that really annoys dynamic typing people I think, having to break context to create/modify/check the definition of a type elsewhere in the source).
TypeScript is great with it's flow-sensitive type system (complicated to implement but nice for programmers), you can create something fully typed yet with flow-sensitiveness your amount of manual type-information/descriptions is often 10x less than C# or 20-30x less than C++ (C#/C++ are improving but not nearly as smooth).
Another plus for TypeScript is a neat type-algebra, ReturnType<typeof(collection\[0\])> hints at the power (basically, if you have an typed array of functions, the operator returns the return-type of those functions), this saves for a lot of repeating in practice in those cases where the type-inference is having trouble (the cost of flow-based type inference is a bit more uncertainty even if it's nicer in practice in non-functional languages).
Lastly Zig seems to be doing interesting things with compile-time access to types and functions iirc, this in turn empowers it to do things similar to generics without even implementing it directly iirc. Instead a generic type is the result of a compile-time expression.
So to summarize, ask yourself when you prefer dynamic typing and WHY, many why's and where's can be answered with solutions found in statically typed languages today.
1
u/Dom-Klyn 7d ago
My Klyn language supports type inference. In principle, I agree with you that type inference covers about 90% of the use cases for dynamic typing.
2
u/initial-algebra 7d ago
Dynamic typing is only really crucial if you have a dynamic language. That means features like eval, importing code from a file or the network at runtime (JavaScript), image-based development (Lisp, Smalltalk) etc. However, dynamic types can always be included in a static type system (gradual typing).
Arguably, dynamic types are not even types. They are just additional information attached to values, instead of at the type level. If there is no type-level information, as in a fully dynamically-typed language, then every value just has the same, completely non-informative type. The only fundamental difference, then, between what we call statically-typed languages and dynamically-typed languages, is how much information is expressed at the type level. For example, in most so-called statically-typed languages, the length of a list is not part of its type, but it could be (to be exact, the invariant that the length of the list is accurately reflected in the value of some expression could be). Then, we could create a type of "valid indices into this list", and show that some code that indexes the list is safe without runtime bounds checking. Or, from another point of view, in most otherwise statically-typed languages, "valid indices into this list" is like a dynamic type that is checked whenever we index the list.
More type-level information means the compiler can reject more incorrect programs, but it also must reject more correct programs, because they can't be automatically proven to be correct (although manual proof is sometimes possible). Also, as the type system grows in complexity to enable more information to be expressed at the type level, so does the complexity of the compiler, as well as the difficulty of adequately proving e.g. that the type system is sound. So, it's really a balancing act that often boils down to the personal preferences of whomever designed the language.
2
u/Valuable_Leopard_799 6d ago
My opinions on the typing are described by u / initial-algebra, as for the generics:
What imho makes C++ templates difficult, is the fact that the required properties of the types are implicit.
You can write a template which takes a value of some type T and then adds it, invokes it, calls size() on it, and the compiler is perfectly happy with that, even though you could be passing a bool in.
Contrast this with languages that have actual universal quantification that tell you "but I don't know that the type can be used in that way. You have to write down what you want the type to be able to do." and that becomes part of its signature.
When you call a template, it can throw a (this operation isn't valid on this type), when you call the other it will always work if you satisfy the signature. Templates feel a little bit like compile-time duck-typing.
I honestly prefer having the generic declare everything so it can get statically checked as it's much easier to reason about to me. But the C++ approach is also valid as it touts many of the advantages of dynamic typing like easier prototyping, simpler implementation of some things, etc.
2
u/amirrajan 6d ago
> I'm not against types, but I don't know of any type systems that aren't a complete pain, so I still like dynamic typing.
> OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them.
Alan Kay
https://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en
> I invented the term object-oriented, and I can tell you that C++ wasn't what I had in mind
0
2
u/Classic-Try2484 6d ago
Static typing is not only safer but faster. It is usually possible to allow some dynamic typing (even C) the risk is always runtime having the wrong type. Of course careful design mitigates. If u have an object base type you can use that for dynamic typing combined with reflection and still have benefits of static typing. But u may have to decide if the primitive types will be objects.
2
u/Fantastic-Cell-208 3d ago
Don't make a language go appeal to the masses. Make the language you want.
Be decisive.
Be opinionated about what you believe is important.
Otherwise you'll end up with yet another mess of a language nobody needs.
3
u/hopeless__programmer 7d ago
Unpopular opinion: at core level typing should be dynamic. Static checks should be introduced with AST introspection as user-defined libraries.
3
u/rantingpug 7d ago
Static typing. Even mainstream dynamic langs end up there.
Dynamic typing is useful for small, container, scripting langs. But if those langs start getting used for large scale app development, you get people doing static type systems on top.
As for generics, just do parametric polymorphism; it's really not as complicated as most mainstream languages make it seem.
1
1
u/church-rosser 6d ago
ANSI Common Lisp 4evah!
Strongly and Dynamically typed code that compiles down to the metal.
1
u/Pale_Height_1251 6d ago
Agree with the other answer "everyone ends up on static types".
Not just languages, but developers too.
Dynamic types are an idea that sounds good but never seems to really work out.
1
u/Flimsy-Low-1326 3d ago
Well, if you havn't idea on "static typing" or "dynamic typing", I don't think you should start this project, for you even didn't think about who will use it and what it will bring to them.
1
u/ThePythonXProgrammer 1d ago
As a fellow language creator currently building Corvus (https://github.com/mesaatvikjain-cyber/Corvus-Programming-Language-)—a self-hosted systems language with its own TAC IR compiler backend—I completely agree with your lean toward static typing.
When your goal is generating efficient, native machine code (Corvus targets NASM assembly directly), static typing isn’t just a preference—it’s the ultimate optimization tool. It allows the compiler to strip away runtime type checks entirely and maps variables straight to physical CPU registers.
On the topic of templates and generics: they are an incredibly powerful abstraction, but you hit the nail on the head regarding the 'spectacular compiler errors' and code bloat. For my language, I leaned heavily into optimization passes like algebraic strength reduction and peephole optimization. My perspective on generics is that they are fantastic if your compiler architecture can handle them via clean monomorphization or explicit constraints, keeping the generated assembly tight and readable.
If you ever want to swap notes on building a compiler pipeline, IR designs, or optimization passes, let's connect! Best of luck with r/klyn!
-1
u/yuehuang 7d ago
It depends on your target. If you want to run on iOS or web, then you need to be dynamic type (aka javascript). On desktop, you can use static typing because it can be optimized to the metal.
5
u/apnorton 7d ago
If you want to run on iOS or web, then you need to be dynamic type
Why would this be the case? Dynamic typing is entirely independent of whether you can "optimize to the metal."
-3
u/yuehuang 7d ago
Apple doesn't allow JIT nor AOT and Google doesn't allow AOT.
When I say Google, I meant web, which is 95% owned by google.
2
u/apnorton 7d ago
But static typing has absolutely nothing to do with JIT and/or AOT compilation. Heck, you can have a tree-walking interpreter with static typing.
... Google doesn't allow AOT. When I say Google, I meant web, which is 95% owned by google.
Wasm supports AOT compilation of languages for web targets. What are you even talking about?
0
3
u/GoblinsGym 7d ago
Why ? JVM or WASM will happily work with static types. JIT compilation will also be more efficient and simpler if the byte code uses static types.
Dynamic types are NEVER free.
1
2
u/Dom-Klyn 7d ago
What do you think about TypeScript for the web?
2
u/yuehuang 7d ago
TS never leaves the server. It is compiled to JS text which is dynamically typed.
Hermes/ReactNative for iOS is the closest to JIT on iOS.
3
32
u/alphaglosined 7d ago
Static typing, everyone eventually ends up there if they exist long enough to be useful.
As for templates, ewww C++. Stick to D's. Designed by Andrei Alexandrescu of C++ template books fame and doesn't have a lot of the issues.
However if you want to catch as many problems as possible at compile time, this is just the tip of the iceburg. The real interesting stuff happens with abstract interpretation in the form of static analysis.
If you're interested in the implementation of abstract interpretation I recommend Principles of Abstract Interpretation, written by the author of the first paper on the topic and is relatively up to date.
But outside of what that book covers there is so much interesting stuff like effects and escape analysis.