Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I mimic Scala SIP-18-syle imports?

Tags:

scala

Scala SIP 18 provides a way to force users to provide an import statement to use certain advanced or unsafe language features. For instance, in order to use higher kinded types, you need to

import scala.language.higherKinds

or you will get a compiler warning telling you you are using an advanced feature.

Is there any way that I can reproduce or mimic this behavior in my own library? For example I may have:

trait MongoRepository[E <: Entity] {
  val casbahCollection: com.mongodb.casbah.MongoCollection
}

I have made the casbahCollection public to expose the underlying collection to the user in case they need it. But it's really not something I want my users to do because it's a leaky abstraction. So I want to force them to do something like this:

import my.library.mongo.leakyAbstraction

Before doing something like this:

widgetRepo.casbahCollection.find()

Is it possible? Is there some way I might provide a similar behavior that's a little more effective than just placing a big ugly warning in the docs?

like image 681
john sullivan Avatar asked Feb 10 '23 11:02

john sullivan


1 Answers

You could fake it with an implicit, similar to the way Await.result works in scala.concurrent.

First create a sealed trait that represents a "permit" to directly access your DAO:

@implicitNotFound("Import my.library.mongo.leakyAbstraction to directly access Mongo")
sealed trait CanAccessMongo

And then an object that extends it:

implicit object leakyAbstraction extends CanAccessMongo

These must be in the same file. By making CanAccessMongo sealed, code outside the same file will not be able to extend it.

Then in MongoRepository make cashbahCollection a function (change val to def). You'll probably want a private val that actually creates it, but we need the function to limit access.

def cashbahCollection(implicit permit: CanAccessMongo) = ...

Now users of your library will have to bring leakyAbstraction into scope in order to call that function. If they don't, they'll get the error message specified in implicitNotFound.

The obvious downside is that all your library code will have to have leakyAbstraction in scope as well.

like image 67
Ryan Avatar answered Feb 15 '23 23:02

Ryan