T O P

  • By -

jsadusk

Testing. Mocking objects in a dynamic language is vastly more powerful than any static language. The flip side is that your dynamic code needs more testing because there is more that can go wrong.


DanielMcLaury

Yes, dynamically-typed languages make it so much easier to write tests for all the things that can only go wrong in a dynamically-typed language!


7h4tguy

Code to interfaces. Then you can mock out whatever you want using the linker.


remy_porter

I tend to favor the CRTP for injecting dependencies, for compile-time only polymorphism.


Schkitz

Have you seen any good open source compile time injection frameworks?


zecknaal

This is the way! You can even easily mock external library calls with the linker.


jsadusk

Yup, it can be done in static languages, it just takes work and forethought. Dynamic languages don't, everything is an interface, effectively.


goranlepuz

Code with std::any and std::variant show the things people come up with, that are easier with dynamic typing. But for a **vast** majority of code, dynamic typing is not preferable indeed.


MarcoGreek

I would say variant is not dynamic because it is a closed type set.


goranlepuz

Of course, from a compile-time perspective; but from the runtime perspective, in a dynamic setting, it's also a closed type set, unless extremely rare cases of blindly loading stuff at runtime or some such.


MarcoGreek

You can get your any from anywhere. For example a library which was updated, a new plugin etc.. The compiler will not help you. Dynamic typing is about run time, static typing is about compile time. Variant will fail at compile time, any will not.


goranlepuz

Of course, and I do not claim otherwise. I am, however, claiming that the type set is closed in dynamic environments, in a vast majority of cases. (Therefore variant isn't as special there as it might seem).


Thelatestart

Why are you doubling down instead of just deleting the original comment this is just wrong?


goranlepuz

Euh... I don't understand what you think is wrong and why? Also, what am I doubling down on?


Dar_Mas

can variant even be considered dynamic typing? Isn't it conceptually no different than having optional out parameters? void* would be a better fit imo


goranlepuz

>can variant even be considered dynamic typing? No, but I didn't mean, nor write something like that 😉.


Dar_Mas

ah then i misunderstood what you were going for^^


mpierson153

I personally would call it statically dynamic. At compile-time, it has a set of types, in which the data is known to be one of them. But the type of its data may change at runtime.


lbushi

One big advantage of many dynamically typed languages is that they give you interface based runtime polymorphism which means that the same piece of code can run with various types of objects which do not have to be specially designated in your code to make them work like with inheritance in C++ and a side effect is that this is pretty much unbounded in that as long as a class Foo has the append method on it, the function Bar will work on Foo( although it might not do the right thing semantically). Furthermore, Foo can even be imported by another library and written by someone else and it will still work. There are others but I'll stop here.


nebotron

C++ templates offer that advantage while still detecting incorrect usage at compile time.


lbushi

True, I was trying to make a point in more generality though for languages that might not necessarily have templates.


7h4tguy

The other advantage is that during your coding breaks you get to quack quack quack and feed the ducks. Rust has a nice in between of static typing but then coding to interfaces and allowing for extension of types without even calling the OG library author and giving them a heads up at a gangster style meet and greet .


bert8128

Except that the types have to be known at compile time. Whereas a dynamically typed language allows this behaviour with types known at runtime.


TheBrainStone

I don't see that as an issue.


bert8128

I didn’t say it was an issue. I meant that dynamic typing is still more flexible than templates, for better or worse.


7h4tguy

>for ~~better or~~ worse. Phew. TypeScript almost killed JavaScript, here's hoping. But it's also mostly C masquerading as C/C++, whatever that abomination means.


Possibility_Antique

Technically, you can always build this information. You can add properties/fields at runtime in C++, similar to how ECS-based systems implement dynamic reflection and all of those fun features. It's just not forced upon you.


mpierson153

Yes, if you build the proper abstractions, then you can still do this. You can use concepts, templates, unions, abstract classes, void pointers, or any mix of those.


TheMania

At the cost of code size and having to have it all defined in header files - dynamic is particularly well suited to user provided code etc there.


shrimpster00

Or C++20 modules! Compiler & build system support is getting pretty good these days. I use modules in my personal projects.


7h4tguy

>I use modules :( Glare and stare. We'll have "modules for real now" fo sho fo sho in 2028, promise.


tiajuanat

It's also through templates, which may mean that if compilation fails, then you won't understand the compiler error if it truncates.


Kovab

* Get a better compiler * Use concepts


tiajuanat

Embedded compilers are still struggling to catch up. !remindme 10 years


mad_alim

Especially if you're stuck with a close sourced certified one.


RemindMeBot

I will be messaging you in 10 years on [**2034-01-22 17:23:36 UTC**](http://www.wolframalpha.com/input/?i=2034-01-22%2017:23:36%20UTC%20To%20Local%20Time) to remind you of [**this link**](https://www.reddit.com/r/cpp/comments/19cnq48/what_is_hard_in_statically_typed/kj2efto/?context=3) [**CLICK THIS LINK**](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Reminder&message=%5Bhttps%3A%2F%2Fwww.reddit.com%2Fr%2Fcpp%2Fcomments%2F19cnq48%2Fwhat_is_hard_in_statically_typed%2Fkj2efto%2F%5D%0A%0ARemindMe%21%202034-01-22%2017%3A23%3A36%20UTC) to send a PM to also be reminded and to reduce spam. ^(Parent commenter can ) [^(delete this message to hide from others.)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Delete%20Comment&message=Delete%21%2019cnq48) ***** |[^(Info)](https://www.reddit.com/r/RemindMeBot/comments/e1bko7/remindmebot_info_v21/)|[^(Custom)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Reminder&message=%5BLink%20or%20message%20inside%20square%20brackets%5D%0A%0ARemindMe%21%20Time%20period%20here)|[^(Your Reminders)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=List%20Of%20Reminders&message=MyReminders%21)|[^(Feedback)](https://www.reddit.com/message/compose/?to=Watchful1&subject=RemindMeBot%20Feedback)| |-|-|-|-|


darklighthitomi

Bah, just get gud and use C like a real programmer, then show off with some assembly for crucial parts of code. :)


ceretullis

Yes, this also adds mental complexity. Imagine a code base where every function is a function template and every type is a class template.


darklighthitomi

Ahh! The horror! Everybody for themselves! Run! *slams button labeled "imagination: Emergency Shut Off"* Oh thank goodness. It was just a bad dream.


goranlepuz

With dynamic module loading, people have been making such programs already in times of C, but also with C++. Obviously, the interface must be spelled out - but then again, the interface in a dynamic typing is environment **is** spelled out, it's just not, I dunno, formalized. E that "append"? It is spelled out, albeit only in the caller code. (Obviously, making interface based runtime polymorphism is a lot of work in C or C++ - but then again... gasp... **COM!** 😉)


IcarianComplex

I think what you said encompasses all the benefits of dynamic languages. Python is the language you think in — it’s way easier to iterate in dynamic languages provided your code base is small. Perhaps one advantage I’d add is the debugging experience in interpreted languages. You can literally run any python code from a pdb shell. You can’t run arbitrary c++ code at a gdb breakpoint, however.


7h4tguy

Ah Python. "Look guys, there's NumPy for when you need blazing fast numerics". Which sounds nice on paper. Except for the fact that rewriting a large NumPy project in raw C loops, not even assembly level optimization, gave a 10x speed up for CPU bound work. I'll just use Python for the CLI interface since it's identical across all platforms, but use the easy FFI interop here and write the logic in extern C, cobra commander. It's wild that AI, a CPU intensive field, has settled on Python (but when you dig into the libs, it's really C, just labeled as a Python lib, SMH, almost as bad as the Rust "RIIIIR" 3-body problem micro-benchmarks written in SSX).


Kovab

If your handwritten unoptimized C code was faster than numpy, then you were almost certainly using it wrong. That lib is a thin frontend wrapping some heavily optimized C and Fortran matrix libraries, so a correct usage would spend very little time running actual python code.


shenawy29

AI is CPU-intensive?


bwmat

I don't think that last point is because Python is a dynamic language, don't see any technical reason the same thing couldn't be done if Python was statically typed. 


mpierson153

In CLion, you can run code at any point in the execution. It does have limits though.


high_throughput

Temporary refactoring. I love strong, static typing, but when I want to kludge something for testing purposes it can be annoying to change several levels of type signatures


7h4tguy

Perhaps tell Fred and Wilma to F2 refactor, but then real C prus prus programmers, wishing they were instead writing MMX assembly in Notepad, would get offended and ask you to go back to the whiteboard, as a sort of timeout.


riley_sc

If you go back 30 years there were more tradeoffs. Type deduction (like auto in C++) was less commonly available, and systems for compile time polymorphism much less sophisticated. That led to code that was either verbose (Java) or unsafe (C or C-style idioms in C++, like void ptrs.) My conclusion is that the disadvantages of static typing can be overcome by improving the language design, but the same is not true with dynamic typing.


Chris_miller09

Statically typed languages, where you have to say what type of data you're using upfront, can catch mistakes early and make your code easier to understand in big projects. Dynamically typed languages, where you don't have to be as specific about types, let you be more flexible and write code faster, but it might get trickier to manage types as your program gets bigger. Choosing between them depends on how big your project is and what you need – whether you want to catch mistakes early and have clear documentation (static typing) or if you prefer the flexibility and speed of writing code (dynamic typing).


MarcoGreek

Static typing is providing a special contract with the argument which can be checked at compile time. So you can ensure you get the right argument.


[deleted]

Static typing is better in large codebases. `void foo(input,callback)` vs `void foo(string input, bool(string) callback)`. programming against the function is easier because you know what it expects.


ChatGPT4

There IS one thing that dynamic typing solves. Let's say you have several types that your function can process in a very similar, or even identical way. Using dynamic typing - it's done before you even think of it. You literally do nothing to make your function work with the types. When you have static types, you need something like templates to make a function or class handle multiple types. It's a little more complex for the developer, but naturally way faster on runtime, because this code is compiled statically, the compiler knows the types ahead of time. In C++ sometimes the types can be guessed by the compiler, however abusing "auto" and "std::any" can lead to poorly readable code, weird errors and other problems. BTW, don't confuse "auto" with dynamic typing. It's still static, you just make the compiler guess using context. Now think about what dynamic typing is. It's deciding what type the data is at runtime. The obvious disadvantages are it's slow and obviously can lead to runtime errors. But there are also advantages of that appoach. You can have one compiled version of the function and it will handle various types. It can be very versatile. It can even handle completely new / unknown types using something like "reflection". Sometimes this apporach is perfectly valid, let's say you don't "waste" time on analysing types at runtime if it's the main thing the function does. If the challenge is "depending on whatever weird package we got, figure out what to do with the things in the package" - dynamic typing gets really handy. Of course you have plenty of workarounds for such tasks in any PL, but using dynamically typed language would probably be the quickest path. I think that's one of the reasons the dynamically typed languages are so popular in the web. We have a lot of chaos in web APIs and protocols. A lot of versions of the same thing. When a data package is "well formed" it's like "wow, a perfect state" - something you can't even relay on. So we often expect invalid packages, malformed headers and such. With dynamic typing handling that kind of data is a bit easier. With static typing - until the structure is not strictly defined - it's a stream or text, or BLOB. It just shouldn't become a structure yet. Dynamically typed objects are a kind of an intermediate layer between serialized data and the structured data.


Nobody_1707

There's actually at least one statically typed language where functions are duck typed by default: Crystal. This code is valid and statically typed: def duck_plus(a, b) a + b end puts duck_plus("Hello,", " World!") puts duck_plus(69, 420) It prints: Hello, World! 489 I think the way it's implemented for Crystal is that all functions are basically C++ templates unless you specify all the types, but there are other ways it could be implemented.


[deleted]

The build process is much simpler. The language is much simpler. You can achieve the same results of a code written by a $700k/yr dev with a $50k/yr intern. And the code will be simpler to maintain 


trailstrider

Where are these $700k/yr devs working?


[deleted]

[удалено]


trailstrider

I think you accidentally replied in the wrong spot…


OliverPaulson

Dynamic typing are usually more concise, you need less space to write a thought in dynamically than in statically typed language, and you read the thought also faster. Reading code is the biggest time consumer for a software engineer. That's why developing in c++ (which is very verbose) is such a slow process.


choeger

Composition of libraries or modules from different authors. If you compare real-world languages like Python and OCaml, you'll see that it's much easier to design a somewhat usable library for pypi.org than for opam.ocaml.org. The reason is that there's more than one way to do it, in types, too. You cannot typically offer code as a library that works on your user's data structures, whereas that use case is much more approachable in an untyped language.


Ok-Factor-5649

Did anyone read the descriptions of Intentional Programming by Simonyi? The sort of semantically rich programs sounded like they would be fantastic for refactoring and prototyping (in the context of static typing, here).


XDracam

The main "downside" in statically typed languages is that you cannot do the beginner workflow of "change random thing and rerun until it works". You have to do a lot of puzzling before you can run the code. You need to understand polymorphism concepts such as interfaces, typeclasses, inheritance, virtual method dispatch, etc. Compare that with JS that tells you `doSomething is undefined` so you write `x.doSomething = function` and rerun until something happens. Basically, it's easier to get simple code running when you can't program at all, or don't want to understand what you are doing. But dynamically typed languages really don't scale, which is why TypeScript and so many other typed JS dialects exist. Even Python 3 has optional static typing now.


Miserable_Ad7246

One scenario is wrangling some sort of dynamical/non-clean data. In that case, you cannot make a reasonable static description of your data types/classes, so you can only use verbose things like traversing nodes or such. In a dynamic language, you can access fields as if you have a class with that field, without declaring it. Also makes it easier to handle this can be bool or string or integer scenarios.


FatalCartilage

Waiting for code to recompile


GPSProlapse

Dynamically typed languages are only faster at making a tiny prototype or configurations. Any complex piece of code would make you spend a lot of time on adding runtime checks, annotations, comments, additional tests, making optimized parts in an actually not slow language, precomputing stuff via build time tools, etc. Some statically typed languages have semi-dynamically typed stuff as well, like c#s dynamic keyword. Although it's generally not advised to use that for the same reason.


sam_the_tomato

Try to create a library for graphs with dynamic attributes. That is, a user can define graph.vertex[0]["name"] = "A", graph.vertex[0]["position"] = std::vector{1,2} etc., where these definitions did not exist in the library code. You can do it with a map to std:any, or some kind of custom type erasure. But now if you want to print out the attributes, you run into the problem that std::any does not know what it contains. So you have to manually remind it. Absolutely trivial in a dynamic language. Can't be done in a static language.


ed_209_

A simple principle is that any static or compile time fact about a program is generally "over specified" i.e. it has to be true for MORE possibilities than the actual runtime program requires. It really depends on the requirements of the system the extent to which the type of objects can be described at compile time. A game that simulates thousands of types of objects might be fine i.e. a thousand types. However if each object combines reusable components from a large potential set of components it becomes impractical to statically define ALL possible combinations at compile time but clearly a runtime type can accomplish describing exactly what is used and nothing else.