From my experience that is generally true with languages that have strong static type systems (like Haskell and Rust).
From my experience that is generally true with languages that have strong static type systems (like Haskell and Rust).
There isn't anything special about the first run, other than emotionally.
Also, if we define "run" as everything that happens when you feed that source program to the machine, then your first run actually bombed with compile errors.
You can't sit there pretending that the compile errors are the only mistakes you made, such that your first compile-error-free run that made it all the way to program startup and through to successful termination is also bug-free.
If you were that good, you wouldn't be making trivial errors flagged by a compiler.
One example would be loops and off-by-one errors. For the case of For-loops on arrays Ada's solution arguably does so via the type-system; in Ada arrays "know" their own length, start- and stop-index and these are query-able via attributes.
So, given Function Sum( Input : Integer_Array ) return Long_Long_Integer you could for-loop on the parameter, querying the 'Range attribute -- yielding a possible implementation of:
Function Sum( Input : Integer_Array ) return Long_Long_Integer is Begin Return Result : Long_Long_Integer := 0 do For Index in Input'Range loop Sum:= Sum + Long_Long_Integer( Input(Index) ); End Loop; end return; End Sum;
And the entire problem is avoided via the type-system.
They also encourage designing with types in order to enforce business logic, which is something you don't get in any of the dynamic languages.
Python doesn't force you to do those things if you dont need the reliability for a prototype or one-off code.
But if you want to make a reliable system, even convert your prototype into a reliable system, you can.