I have read about how the fail-fast style of programming in languages like Erlang end up with much shorter programs than the defensive style found in most other languages. Is this correct for all types of programs and what is the reasoning for this?
The fail-fast style of programming is focused on better code readability and debugging. The user experience is a secondary target: a user may experience strange error messages or program failures, but the greater quality of code allows programmers to easily find the bug and correct the issue.
Defensive style programming, instead, focuses on validation input from user and from other portions of code. The code is more verbose, because the programmer has to carefully verify input and fail gracefully in case of error. This lead to more code (from the programmers' point of view) and a more robust application (from the users' point of view).
Fail-fast programs aren't necessarily shorter than defensive style programs: it depends on the implementation and the measures needed to make your defensive code safe.
In the case of Erlang, the fail-fast programs are usually shorter because of the declarative style and how the VM makes sure to generate error cases for you. As an example, in the function:
day(1) -> sunday;
day(2) -> monday;
day(3) -> tuesday;
day(4) -> wednesday;
day(5) -> thursday;
day(6) -> friday;
day(7) -> saturday;
Any unexpected value passed to the function will result in an error that can be caught and handled by another process (ie.: a supervisor). Such errors will also never endanger the system as a whole and don't require code to be added to the function itself -- it's all done outside of the normal execution path by predetermined behaviors.
In a dynamic language where fail-fast isn't the norm, you would have to manually check the boundaries and throw an exception yourself. Then you must catch the exception locally (top-level try ... catches included) if you don't want the whole system to go down. The error handling code usually has to be inserted throughout the normal execution path.
In a static language where fail-fast isn't the norm, then how long your code will be will highly depend on the type system you have. If the language allows to define types where the edge cases end up checked for you by the compiler, then you usually do not have to handle this inside the code, outside of nondeterministic events (files not working, unexpected user input, etc.) In languages with such type systems, many errors will be caught before runtime and so you won't have as many defensive cases.
When error handling can't be avoided, languages supporting fail-fast idioms (like Erlang) will allow for arguably clearer code than languages that don't (static or not), mainly because the code for special cases isn't mixed in with the code for the ideal execution path.