There is another underlying issue with this proposal (incase it wasn’t completely clear when communicating earlier) which is that its not solving an underlying issue with implicits, rather its creating a new pattern/keyword for something that is currently already possible which only works in same cases, and not others (which means we are still screwed in the cases it doesn’t cover). Let me illustrate, lets assume that we have the following code
class UserClient(implicit executionContext: ExecutionContext) {
def getUser(id: String)(implicit correleationId: CorrelationId): Future[User] = ???
def query(offset: Int = 0, limit: Int = 100)(implicit correleationId: CorrelationId): Future[List[User]] = ???
}
This kind of code is very typical in backend style Scala code. Now in this case, the ExecutionContext
is the “environment” which is what this SIP is trying to address (lets ignore the fact that you can also pass ExecutionContext
in the methods for now). So yes, we now have new syntax and new keywords to work with the fact that we can pass the ExecutionContext
in different way.
However we still have the problem with CorrelationId
, for those that are wondering what a it is you can read https://blog.rapid7.com/2016/12/23/the-value-of-correlation-ids/ but the tl;dr is, a CorrelationId
is just a unique ID that a webserver gets a request is made against it and its expected for it to pass this ID along everywhere to help in diagnosing/tracing issues in distributed microservices; hence the UserClient
needs to pass this CorrelationId
along in all requests its making.
Importantly this is not an environment/context, the value of this variable is going to be different everytime getUser
/query
are called (unlike ExecutionContext
, which really is a context that often has the same value for the lifetime of an application). Using implicit
is still the right abstraction to use, because its very rare to ever manually provide a CorrelationId
(this is typically only done in tests) but using the CorrelationId
as an environment is just wrong.
So what if we somehow need to change getUser
/query
wrt implicits/default parameters/overrides/currying (and still keep the CorrelationId
implicit). Well this SIP may solve this however its still inconsistent with the ExecutionContext
(hence why I call it a scapegoat) and we still have the same issues that we are currently stuck with in Scala2.
Hence the fundamental issues with the SIP, we are “solving” (solving is in quotation marks because this solution is already possible) a subset of issues by creating an entirely new syntax (which already raises question marks since this issue as well as others should be treated more like a bug report rather than a new feature) instead of fixing the QoL issues now.
I would rather solve the underlying issues with mixing default parameters/overrides/implicits rather than just avoid this problem and say that everything is an “environment” or “context” and give a completely new syntax for it.
This SIP appears to work CorrelationId
above, but if this is the case then its completely unclear and inconstant how given
works since the SIP doesn’t work with constructors, so we have different syntax for the same thing in different places. Its not at all clear (either in the definition or how its used) on what level of scoping this definition applies. With current implicits, its really clear. Having the implicit ExecutionContext
in the class constructor parameter list makes it will take the implicit ExecutionContext
when you instantiate UserClient
and then it will persist there, however having implicit CorrelationId
in a method means that every call of the method requires its own instance of CorrelationId
. Note that if you remove all of the implicit keywords in my example, this is exactly the same; ergo nothing has changed apart from us having to supply parameters explicitly (thats what gives it the clarity). With this SIP, its very unclear what the intent is, not everything is an environment. Saying that the implicit
keyword is “overused” is like saying that the val
keyword is overused, alone its not a justification of an argument.
EDIT: Yes the whole definition of environment is a bit loose, at the end of the day we are just dealing with currying/application of parameters. The point is we are introducing extra incosistant rules to solve one subset of issues.