in reply to usage of if on nested hash creating empty slot for non existing value

...->{...} ...->[...]
is really equivalent to
( ... //= {} )->{...} ( ... //= [] )->[...]

when they're found in an lvalue context (such as the argument of a function like defined).

You can disable this behaviour for the arguments of defined and exists by adding

no autovivification;

Ref: autovivification