The base type in R is a vector. A number such as 3.14 is simply a vector of length 1. So functions are vectorized by default (as long as you don't do any operations that are explicitly not vectorizable).
Once you get your head around everything being a vector, R can be a lot of fun.
I love Julia but I wish I didnt need to explicitly broadcast functions across a vector.
I was annoyed by that at first, but eventually came to appreciate how Julia's semantics for when broadcasting is or is not required for operations on scalars, vectors, and matrices map to the underlying math. I.e., for an N x N matrix `A`
5 * A
does not require broadcasting because multiplication of a matrix by a scalar is mathematically well-defined, whereas
5 + A
(assuming you want element-wise addition) does require broadcasting, i.e.,
5 .+ A
because addition of a vector and a matrix is not mathematically well-defined.
I do understand why they do it, and numpy can play a bit fast and loose which can be confusing, but I miss reading elegent vector-by-default R code.
The Julia approach also has some drawbacks, I was writing some code the other day and forgot to broadcast exp() across a matrix. exp(A) and exp.(A) gives very different results but it's not immediately obvious looking at code, especially when the code is a mixture of broadcasted and native matrix function calls which dots peppered all over the place.
Well, again I'd say that's just like the above examples. The exponential of a (square) matrix is indeed a very well defined object [1] with semantics perfectly consistent with the exponential of a scalar. On the other hand, broadcasting exp over a matrix is a very different operation, which doesn't really have any meaning in a linear algebra sense.
I understand it's an easy mistake to make when you're used to R or Numpy, but I'd say it's their fault you're making this mistake, not Julia's.
If you re-read my comment you will see I am not criticizing the language, it makes mathematical sense.
I was pointing out one downside of the broadcast syntax, is that a typo can lead to non-obvious errors in calculations. R avoids this with a expm() function.
Don't get me wrong, I love using Julia, it makes turning maths into code easy, and this is not even close to a deal breaker.
"one downside of autovectorization, is that a typo can lead to non-obvious errors in calculations. When I want the exponential of a matrix, I might accidentally write exp(M) and get unwanted vectorization. This is a typo that can lead to non-obvious errors in calculations. Julia avoids this with a exp.(M) syntax."
I think the potential for typos is symmetric here between julia and R. I think what's asymmetric though is that Julia's broadcasting is more extensible, less and hoc and more general than R's auto-vectorization since it can be done over arbitrary containers and you can control precisely what calls broadcast.
______________________________
Sorry if this comes off as confrontational, that's not my intention. I just think this is a very interesting and fruitful corner of language design.
Once you get your head around everything being a vector, R can be a lot of fun.
I love Julia but I wish I didnt need to explicitly broadcast functions across a vector.