If it is about the rules of syntactic sugar, then any expression of the form foo(bar) is either calling a method foo or calling the apply method on foo.
They look the same because the idea is that you should think of apply as calling (applying) a function.
If you are asking when or not use apply when design new classes, then ask yourself: “is this operation the most fundamental one of this type? Does it make sense to think that instances of this class are like functions from X to Y?”
In any case, AFAIK, there is no standard rule about when or not using apply; Some people like to write concise and elegant code, thus foo(bar) looks nice for them. Some others prefer longer but more descriptive names, thus they would rather foo.baz(bar)
hmm, that is where it is getting more complicated as to when to use and when not to use since there are no standard rules . And, to complicate it more, since it is not mentioned explicitly as in foo(bar) rather than foo.apply(bar).
Would you mind listing me some common patters where the apply is used frequently - some of them I listed here
Would you mind listing me some common patters where the apply is used frequently.
Only one, and you already mentioned it: “Function invocation”.
The thing is that in a functional language you can think of many things as functions.
An Array[T] is basically a (partial) function from Int to T.
A companion object of some type T is, usually, a function from C to T (where C are the types of the constructor parameters).
A Set[T] is basically a function from T to Boolean.
A Map[K, V] is basically a (partial) function from K to V.
etc.
So, as I said before if you can think of a class as a function then apply would be a valid choice.
In any case, if you still find it confusing, you can totally decide not to use it, again as I said, many people would prefer that.
Also, for what I have seen, except for companion objects(and the partially apply type trick, but that is an advanced use case you shouldn’t care for now) most people do not write custom apply methods. And the ones in the stdlib are pretty straight forward and known.