Required arguments shouldn’t have defaults; optional arguments should have defaults. In other words, an argument should have a default if and only if it’s optional.
It’s common for functions to use NULL to mean that the argument is optional, but the computation of the default is non-trivial:
Hence fun_b is signaling to the user that arg is required, fun_a is signaling to the user that arg is optional. From this, the fun_b formulation is bad practice, even though you can make it work if you really want.
My guess here is that the data argument of ggplot is kind of non-optional. Making a plot with no data is relatively meaningless. The reason they made this argument optional is because it can be provided later, in the geom:
ggplot() +
geom_point(aes(x,y), data = data)
So not having a default of NULL could wrongly signal that it's optional.
A similar situation in my opinion is when you have S3 classes. For example boxplot:
boxplot(x, ...)
## S3 method for class 'formula'
boxplot(formula, data = NULL, ...
Here x or formula are compulsory, but only one is enough.
To me, these situations are similar in that you have an argument that is compulsory in principle (it has to be given somewhere), but optional in practice (the implementation should account for the fact it might be missing in one place and provided in another). From the user point of view, it's not optional.
I just had a look into the history and it looks like ggplot had data = NULL until classes were reimplemented in #6364 a month ago. Also geom_point sets NULL as default as well.