In short, the problem is not nulls per se, the problem is static type systems which does not allow you to specify if a certain value can be null or not.
But I hereby predict that soon people are going to declare that "nulls are bad" and eliminate them even in languages where they are totally fine.
Dynamically typed programs are usually informally "duck typed," since it's impossible to do something meaningful with truly arbitrary types most of the time. But just like in statically typed languages, there's always the very real possibility that your duck will instead be a null — and the bug is not the function returning a non-duck, it's you ever assuming you have something that quacks like a duck.
But of course you can make bugs involving nulls. The OP shows an example in a dynamic language where null is returned instead of the regular value if a lookup key is not found. Obviously this is ambiguous when the found value can also be null. But the problem is not the null per se, the problem is using a sentinel value to indicate a special condition when the same value is also a legitimate regular value. This is just bad API design.
There is a need for a nothing value in many cases and languages without an implicit null, such as Haskell, F# and Rust, employ an ‘option’ type. It’s a dedicated type that either contains a value or nothing. It forces you to declare when you expect a potential null and to check for it.
In numerical calculus: yes, most certainly. What do you expect the result of log(-1) to be? The alternative is to use specially tagged particular numbers as "no-data", and pray so that they do not appear naturally as the result of computations.
i pi, or more generally i pi n for odd n.