Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
So far implicit parameters in Scala do not look good for me -- it is too close to global variables, however since Scala seems like rather strict language I start doubting in my own opinion :-).
Question: could you show a real-life (or close) good example when implicit parameters really work. IOW: something more serious than showPrompt, that would justify such language design.
Or contrary -- could you show reliable language design (can be imaginary) that would make implicit not neccessary. I think that even no mechanism is better than implicits because code is clearer and there is no guessing.
Please note, I am asking about parameters, not implicit functions (conversions)!
Updates
Global variables
Thank you for all great answers. Maybe I clarify my "global variables" objection. Consider such function:
max(x : Int,y : Int) : Int
you call it
max(5,6);
you could (!) do it like this:
max(x:5,y:6);
but in my eyes implicits works like this:
x = 5;
y = 6;
max()
it is not very different from such construct (PHP-like)
max() : Int
{
global x : Int;
global y : Int;
...
}
Derek's answer
This is great example, however if you can think of as flexible usage of sending message not using implicit please post an counter-example. I am really curious about purity in language design ;-).
In a sense, yes, implicits represent global state. However, they are not mutable, which is the true problem with global variables -- you don't see people complaining about global constants, do you? In fact, coding standards usually dictate that you transform any constants in your code into constants or enums, which are usually global.
Note also that implicits are not in a flat namespace, which is also a common problem with globals. They are explicitly tied to types and, therefore, to the package hierarchy of those types.
So, take your globals, make them immutable and initialized at the declaration site, and put them on namespaces. Do they still look like globals? Do they still look problematic?
But let's not stop there. Implicits are tied to types, and they are just as much "global" as types are. Does the fact that types are global bother you?
As for use cases, they are many, but we can do a brief review based on their history. Originally, afaik, Scala did not have implicits. What Scala had were view types, a feature many other languages had. We can still see that today whenever you write something like T <% Ordered[T], which means the type T can be viewed as a type Ordered[T]. View types are a way of making automatic casts available on type parameters (generics).
Scala then generalized that feature with implicits. Automatic casts no longer exist, and, instead, you have implicit conversions -- which are just Function1 values and, therefore, can be passed as parameters. From then on, T <% Ordered[T] meant a value for an implicit conversion would be passed as parameter. Since the cast is automatic, the caller of the function is not required to explicitly pass the parameter -- so those parameters became implicit parameters.
Note that there are two concepts -- implicit conversions and implicit parameters -- that are very close, but do not completely overlap.
Anyway, view types became syntactic sugar for implicit conversions being passed implicitly. They would be rewritten like this:
def max[T <% Ordered[T]](a: T, b: T): T = if (a < b) b else a
def max[T](a: T, b: T)(implicit $ev1: Function1[T, Ordered[T]]): T = if ($ev1(a) < b) b else a
The implicit parameters are simply a generalization of that pattern, making it possible to pass any kind of implicit parameters, instead of just Function1. Actual use for them then followed, and syntactic sugar for those uses came latter.
One of them is Context Bounds, used to implement the type class pattern (pattern because it is not a built-in feature, just a way of using the language that provides similar functionality to Haskell's type class). A context bound is used to provide an adapter that implements functionality that is inherent in a class, but not declared by it. It offers the benefits of inheritance and interfaces without their drawbacks. For example:
def max[T](a: T, b: T)(implicit $ev1: Ordering[T]): T = if ($ev1.lt(a, b)) b else a
// latter followed by the syntactic sugar
def max[T: Ordering](a: T, b: T): T = if (implicitly[Ordering[T]].lt(a, b)) b else a
You have probably used that already -- there's one common use case that people usually don't notice. It is this:
new Array[Int](size)
That uses a context bound of a class manifests, to enable such array initialization. We can see that with this example:
def f[T](size: Int) = new Array[T](size) // won't compile!
You can write it like this:
def f[T: ClassManifest](size: Int) = new Array[T](size)
On the standard library, the context bounds most used are:
Manifest // Provides reflection on a type
ClassManifest // Provides reflection on a type after erasure
Ordering // Total ordering of elements
Numeric // Basic arithmetic of elements
CanBuildFrom // Collection creation
The latter three are mostly used with collections, with methods such as max, sum and map. One library that makes extensive use of context bounds is Scalaz.
Another common usage is to decrease boiler-plate on operations that must share a common parameter. For example, transactions:
def withTransaction(f: Transaction => Unit) = {
val txn = new Transaction
try { f(txn); txn.commit() }
catch { case ex => txn.rollback(); throw ex }
}
withTransaction { txn =>
op1(data)(txn)
op2(data)(txn)
op3(data)(txn)
}
Which is then simplified like this:
withTransaction { implicit txn =>
op1(data)
op2(data)
op3(data)
}
This pattern is used with transactional memory, and I think (but I'm not sure) that the Scala I/O library uses it as well.
The third common usage I can think of is making proofs about the types that are being passed, which makes it possible to detect at compile time things that would, otherwise, result in run time exceptions. For example, see this definition on Option:
def flatten[B](implicit ev: A <:< Option[B]): Option[B]
That makes this possible:
scala> Option(Option(2)).flatten // compiles
res0: Option[Int] = Some(2)
scala> Option(2).flatten // does not compile!
<console>:8: error: Cannot prove that Int <:< Option[B].
Option(2).flatten // does not compile!
^
One library that makes extensive use of that feature is Shapeless.
I don't think the example of the Akka library fits in any of these four categories, but that's the whole point of generic features: people can use it in all sorts of way, instead of ways prescribed by the language designer.
If you like being prescribed to (like, say, Python does), then Scala is just not for you.
Sure. Akka's got a great example of it with respect to its Actors. When you're inside an Actor's receive method, you might want to send a message to another Actor. When you do this, Akka will bundle (by default) the current Actor as the sender of the message, like this:
trait ScalaActorRef { this: ActorRef =>
...
def !(message: Any)(implicit sender: ActorRef = null): Unit
...
}
The sender is implicit. In the Actor there is a definition that looks like:
trait Actor {
...
implicit val self = context.self
...
}
This creates the implicit value within the scope of your own code, and it allows you to do easy things like this:
someOtherActor ! SomeMessage
Now, you can do this as well, if you like:
someOtherActor.!(SomeMessage)(self)
or
someOtherActor.!(SomeMessage)(null)
or
someOtherActor.!(SomeMessage)(anotherActorAltogether)
But normally you don't. You just keep the natural usage that's made possible by the implicit value definition in the Actor trait. There are about a million other examples. The collection classes are a huge one. Try wandering around any non-trivial Scala library and you'll find a truckload.
One example would be the comparison operations on Traversable[A]. E.g. max or sort:
def max[B >: A](implicit cmp: Ordering[B]) : A
These can only be sensibly defined when there is an operation < on A. So, without implicits we’d have to supply the context Ordering[B] every time we’d like to use this function. (Or give up type static checking inside max and risk a runtime cast error.)
If however, an implicit comparison type class is in scope, e.g. some Ordering[Int], we can just use it right away or simply change the comparison method by supplying some other value for the implicit parameter.
Of course, implicits may be shadowed and thus there may be situations in which the actual implicit which is in scope is not clear enough. For simple uses of max or sort it might indeed be sufficient to have a fixed ordering trait on Int and use some syntax to check whether this trait is available. But this would mean that there could be no add-on traits and every piece of code would have to use the traits which were originally defined.
Addition:
Response to the global variable comparison.
I think you’re correct that in a code snipped like
implicit val num = 2
implicit val item = "Orange"
def shopping(implicit num: Int, item: String) = {
"I’m buying "+num+" "+item+(if(num==1) "." else "s.")
}
scala> shopping
res: java.lang.String = I’m buying 2 Oranges.
it may smell of rotten and evil global variables. The crucial point, however, is that there may be only one implicit variable per type in scope. Your example with two Ints is not going to work.
Also, this means that practically, implicit variables are employed only when there is a not necessarily unique yet distinct primary instance for a type. The self reference of an actor is a good example for such a thing. The type class example is another example. There may be dozens of algebraic comparisons for any type but there is one which is special.
(On another level, the actual line number in the code itself might also make for a good implicit variable as long as it uses a very distinctive type.)
You normally don’t use implicits for everyday types. And with specialised types (like Ordering[Int]) there is not too much risk in shadowing them.
Based on my experience there is no real good example for use of implicits parameters or implicits conversion.
The small benefit of using implicits (not needing to explicitly write a parameter or a type) is redundant in compare to the problems they create.
I am a developer for 15 years, and have been working with scala for the last 1.5 years.
I have seen many times bugs that were caused by the developer not aware of the fact that implicits are used, and that a specific function actually return a different type that the one specified. Due to implicit conversion.
I also heard statements saying that if you don't like implicits, don't use them.
This is not practical in the real world since many times external libraries are used, and a lot of them are using implicits, so your code using implicits, and you might not be aware of that.
You can write a code that has either:
import org.some.common.library.{TypeA, TypeB}
or:
import org.some.common.library._
Both codes will compile and run.
But they will not always produce the same results since the second version imports implicits conversion that will make the code behave differently.
The 'bug' that is caused by this can occur a very long time after the code was written, in case some values that are affected by this conversion were not used originally.
Once you encounter the bug, its not an easy task finding the cause.
You have to do some deep investigation.
Even though you feel like an expert in scala once you have found the bug, and fixed it by changing an import statement, you actually wasted a lot of precious time.
Additional reasons why I generally against implicits are:
They make the code hard to understand (there is less code, but you don't know what he is doing)
Compilation time. scala code compiles much slower when implicits are used.
In practice, it changes the language from statically typed, to dynamically typed. Its true that once following very strict coding guidelines you can avoid such situations, but in real world, its not always the case. Even using the IDE 'remove unused imports', can cause your code to still compile and run, but not the same as before you removed 'unused' imports.
There is no option to compile scala without implicits (if there is please correct me), and if there was an option, none of the common community scala libraries would have compile.
For all the above reasons, I think that implicits are one of the worst practices that scala language is using.
Scala has many great features, and many not so great.
When choosing a language for a new project, implicits are one of the reasons against scala, not in favour of it. In my opinion.
Another good general usage of implicit parameters is to make the return type of a method depend on the type of some of the parameters passed to it. A good example, mentioned by Jens, is the collections framework, and methods like map, whose full signature usually is:
def map[B, That](f: (A) ⇒ B)(implicit bf: CanBuildFrom[GenSeq[A], B, That]): That
Note that the return type That is determined by the best fitting CanBuildFrom that the compiler can find.
For another example of this, see that answer. There, the return type of the method Arithmetic.apply is determined according to a certain implicit parameter type (BiConverter).
It's easy, just remember:
to declare the variable to be passed in as implicit too
to declare all the implicit params after the non-implicit params in a separate ()
e.g.
def myFunction(): Int = {
implicit val y: Int = 33
implicit val z: Double = 3.3
functionWithImplicit("foo") // calls functionWithImplicit("foo")(y, z)
}
def functionWithImplicit(foo: String)(implicit x: Int, d: Double) = // blar blar
Implicit parameters are heavily used in the collection API. Many functions get an implicit CanBuildFrom, which ensures that you get the 'best' result collection implementation.
Without implicits you would either pass such a thing all the time, which would make normal usage cumbersome. Or use less specialized collections which would be annoying because it would mean you loose performance/power.
I am commenting on this post a bit late, but I have started learning scala lately.
Daniel and others have given nice background about implicit keyword.
I would provide me two cents on implicit variable from practical usage perspective.
Scala is best suited if used for writing Apache Spark codes. In Spark, we do have spark context and most likely the configuration class that may fetch the configuration keys/values from a configuration file.
Now, If I have an abstract class and if I declare an object of configuration and spark context as follows :-
abstract class myImplicitClass {
implicit val config = new myConfigClass()
val conf = new SparkConf().setMaster().setAppName()
implicit val sc = new SparkContext(conf)
def overrideThisMethod(implicit sc: SparkContext, config: Config) : Unit
}
class MyClass extends myImplicitClass {
override def overrideThisMethod(implicit sc: SparkContext, config: Config){
/*I can provide here n number of methods where I can pass the sc and config
objects, what are implicit*/
def firstFn(firstParam: Int) (implicit sc: SparkContext, config: Config){
/*I can use "sc" and "config" as I wish: making rdd or getting data from cassandra, for e.g.*/
val myRdd = sc.parallelize(List("abc","123"))
}
def secondFn(firstParam: Int) (implicit sc: SparkContext, config: Config){
/*following are the ways we can use "sc" and "config" */
val keyspace = config.getString("keyspace")
val tableName = config.getString("table")
val hostName = config.getString("host")
val userName = config.getString("username")
val pswd = config.getString("password")
implicit val cassandraConnectorObj = CassandraConnector(....)
val cassandraRdd = sc.cassandraTable(keyspace, tableName)
}
}
}
As we can see the code above, I have two implicit objects in my abstract class, and I have passed those two implicit variables as function/method/definition implicit parameters.
I think this is the best use case that we can depict in terms of usage of implicit variables.
Related
I've been using Scala at work, and I have a question related to implicit parameters.
Often I've seen executionContext defined in method definitions and also in class definitions.
At the same time I've seen classes that accepts case classes that contain configuration data (timeout, adapter, port, etc.) as regular parameters.
My question is why when passing configuration this parameter is not defined as implicit?
Or the other way around what if executionContext would be defined as a regular parameter?
I'm trying to understand when to use implicit parameter and when not to use them.
EDIT: maybe the example of passing a case class is not the best example, it was the first idea that comes to my mind
Conceptually, implicits are something "external" to the application logic, and explicit parameters are ... well ... explicit.
Consider a function def f(x: Double): Double = x*x
It is a pure function that transforms a given real number into another real number. It makes sense for x to be an explicit parameter, as it is an intrinsic part of what this function is.
Now, suppose, you were implementing some sort of approximate algorithm for multiplication, and wanted to control the precision with which you function computes the answer.
You could do def f(x: Double, precision: Int): Double = ???. It would work, but is inconvenient and kinda clumsy:
Function definition no longer expresses the conceptual "nature" of the function being a pure transformation on the set of real numbers
It makes it complicated at the call site, because everyone using your function must now be aware of this additional parameter to pass around (imagine, you are writing a library for non–engineer math majors to use, they understand abstract transformations and complex formulas, but could care less about numeric precision: how often do you think about precision when you need to compute an area of a square?).
It also makes existing code harder to read and modify
So, to make it prettier, you can do def f(x: Double)(implicit precision: Int) = ???. This has an advantage of saying exactly what you want: "I have a transformation double => double, that will use the implied precision when the actual result is computed). Those math majors can now write their abstract formulas the way they are used to: val area = square(x) without polluting their logic with annoying configurations they don't really care about.
When to use this exactly is, certainly, a question of opinion and taste (which is expressly forbidden on SO). Someone can certainly argue about the above example, that precision is actually a part of the transformation definition, because 5.429 and 5.54289 (results of f(2.33)(3) and f(2.33)(4) respectively) are two different numbers.
So, in the end of the day, you just gotta use your judgement and your common sense to make a decision for every case you come across.
When using existing libraries, there is another consideration. Consider:
def foo(f: Future[Int], ec: ExecutionContext) =
f.map { x => x*x }(ec)
.map { _.toString } (ec)
.foreach(println)(ec)
This would look a lot nicer and less messy if you made ec implicit, regardless of where you stand philosophically on whether to consider it a part of your transformation or not:
def foo(f: Future[Int])(implicit ec: ExecutionContext) =
f.map { x => x*x }.map(_.toString).foreach(println)
Implicits can be used when:
you need only one value of some type
it is unambiguous how such value would be defined
this includes both manual definition as well as using metaprogramming to generate the value based on e.g. how its type is defined
Futures and Akka decided that passing some "globals" as implicits is a reasonable use case, so they would pass as implicits:
ExecutionContext
ActorSystem, Materializer
various configs like Timeout
in general things which you don't want to be put into some static field, but which are passed around everywhere.
However, the rest of Scala world would solve this issue by using some abstraction that would pass these things under the hood, some sort of builders, via constructors, abstractions over (dependencies) => result functions, etc.
E.g. cats.effect.IO don't need to pass ExecutionContext around because it passes its scheduler around when you run it. Only when you want to explicitly change the pool things are being run on you have to use some method. In Monix running things also require you to pass Scheduler at the end, when whole computation is composed. So both approached let you give up on passing around all these ExecutionContexts. In case of Future it is necessary because you need to have control over thread pools, but you also evaluate things eagerly, and putting ec (futureA.flatMap(f)(ec)) manually would break for-comprehension.
As a result, outside Akka ecosystem and raw Futures, are more often used to carry around type-classes, as a mean to decouple business logic from particular implementation, allow adding support for new types without modifying code that uses these implementations, and so on. (There are tons of examples of type-classes in Scala so I'll skip it here).
Usually, when I read about people using implicits to pass configs around, it is just a matter of time before it ends up with grief. Akka and EC kind of requires them but you should just pass configs explicitly. You can group them into case classes to pass bunch of them around and it is not that much of an issue. You can also put all things required as implicits explicitly into one place and do:
case class Configs(dbEX: EC, mapEC: EC)
class SomeBehavior(configs: Configs) {
def someAction = {
if (...) {
implicit val ec: EC = configs.dbEC
...
} else {
implicit val ec: EC = configs.mapEC
...
}
}
}
to make them implicit only in the place that needs them. A good role of thumb is: do you care if there is something passed around that you don't see right in the code? Usually, the answer is, yes you do, you would prefer to see it, with only exceptions being cases when it would be somewhat obvious where does the value come from, or if you kinda knew that the value would be ok and you didn't bother where it came from.
There are a multitude of use-cases of implicit in Scala: under the hood, they boil down to leveraging the compiler's implicit resolution mechanism to fill in things that might not have explicitly been mentioned, but the use-cases are divergent enough that in Scala 3, each use-case (of those that survive into Scala 3...) gets encoded with a different keyword.
In the case of the execution context, implicit arguments are being used to mimic dynamic scope in a language which is normally statically scoped. The primary win from doing this is that it allows behavior further down the call stack to be decided-upon much further up the call stack without having to always explicitly pass on the behavior through the intervening layers of the stack (while providing a way for those intervening layers to cleanly force a different behavior).
Historically, a major example of this was for things like numeric precision. Many numeric operations end up being implemented through iterated refinement (e.g. when square-root was implemented in software, it might be implemented using Newton's method), which means there's a trade-off between speed of calculation and precision (suggesting accuracy). With dynamic scoping, there's a neat way to accomplish this: a global variable for the desired level of precision in mathematical results. Your numeric routine checks the value of that variable and governs itself accordingly. The difference from globals in a statically-scoped language is that when A calls B which calls C, if A sets the value of x to 1 and B sets it to 2, x will be 2 when checked in C or B, but once B returns to A, x will once again be 1 (in dynamically scoped languages, you can think of a global variable as really being a name for a stack of values, and the language implementation automatically pops the stack as appropriate).
Dynamic scoping was once fairly popular (especially so in Lisps before the mid/late 1970s); nowadays the only places you really see it are in Bourne shells (including bash), Emacs Lisp; while some languages (Perl and Common Lisp are probably the two main examples) are hybrids: a variable gets declared in a special way to make it dynamically or statically scoped. Static scoping has pretty clearly won: it's easier for the language implementation or the programmer to reason about.
The cost of that ease is that, in our numeric computation example, we end up with something like the following:
def newtonSqrt(x: Double, precision: Int): Double = ???
/** Calculates the length of the hypotenuse of a right triangle with legs of given lengths
*/
def hypotenuse(x: Double, y: Double, precision: Int): Double =
newtonSqrt(x*x + y*y, precision)
Thankfully, Scala supports default arguments, so we avoid having versions that use a default precision, too. Arguably, the precision is exposing an implementation detail (the fact that our calculations aren't necessarily perfectly mathematically accurate): the important thing is that the length of the hypotenuse is the square root of the sum of the squares of the legs.
In Scala, we can make the precision implicit:
// DON'T ACTUALLY PASS AN INT IMPLICITLY!!!!!!
def newtonSqrt(x: Double)(implicit precision: Int): Double = ???
def hypotenuse(x: Double, y: Double)(implicit precision: Int): Double =
newtonSqrt(x*x, y*y)
(It's actually really bad to ever pass a primitive or any type which could plausibly be used for something other than describing the behavior in question through the implicit mechanism: I'm doing it here for didactic clarity).
The compiler will effectively translate newtonSqrt(x*x + y*y) to (something very similar to) newtonSqrt(x*x + y*y, precision). Now callers to hypotenuse can decide to fix precision via an implicit val or to defer the choice to their callers by adding the implicit to their signature.
Dynamic scoping has long been controversial, so it's no surprise that even the constrained dynamic scoping this usage of implicit embeds is controversial. In Scala's case, it doesn't help that in many cases the tooling throws up its hands when it comes to helping you figure out implicits: most of the really furious compiler errors one encounters are related to missing implicits or collisions, and tracing to figure out which values are in the implicit scope at any time is not something the tooling has a history of helping people with. Thus there are many developers who have decided that explicitly threading through configuration is superior to using implicits.
It's largely a matter of taste and the situation whether this sort of behavior description is best passed implicitly or explicitly (and it's worth noting that the type-class pattern, especially without a hard requirement for coherence (that there be one and only one possible way to describe the behavior) as is typical in Scala, is just a special case of this behavior description).
I should also note that it isn't a binary choice between bundling a few settings into a case class vs. passing them implicitly: you can do both:
case class ProcessSettings(sys: ActorSystem, ec: ExecutionContext)
object ProcessSettings {
implicit def implicitly(implicit sys: ActorSystem, ec: ExecutionContext): ProcessSettings =
ProcessSettings(sys, ec)
}
def doStuff(x: SomeInput)(implicit settings: ProcessSettings)
I have a function with a type parameter and I want to find out whether the type parameter is an Option or not. I have read some blogposts, i.e. this one, about type classes in scala recently, so I came up with this solution:
case class OptionFinder[A](isOption: Boolean)
implicit def notOption[A]: OptionFinder[A] = OptionFinder(false)
implicit def hitOption[A]: OptionFinder[Option[A]] = OptionFinder(true)
def myFunction[A](value: A)(implicit optionFinder: OptionFinder[A]): String = {
if (optionFinder.isOption) {"Found Option!"} else {"Found something else."}
}
This works seemingly as desired:
scala> val x: Option[Int] = Some(3)
scala> myFunction(x)
res0: String = Found Option!
scala> val y: String = "abc"
scala> myFunction(y)
res1: String = Found something else.
In the case of Some(3) hitOption is the implicit parameter, even though notOption would match as well (with A = Option[Int]). Obviously the more specific is type chosen. But am I guaranteed that the compiler always chooses the more specific type? And how does that work in the compiler anyway? I did not find a documentation of this behavior yet.
Note: Maybe the title for this question is not best, I'll happily change it for a better one.
There is already a question about this: Scala: Implicit parameter resolution precedence. Which answers itself through a complicated blog post. I think the most important piece of information is in Martin Odersky's comment on the blog post:
Here's a more high-level explanation what goes on with implicit search
in Scala, and which corresponds to how the spec explains it, but in
slightly less formalistic language.
First, we look for implicits that are visible either as locals or as members of enclosing classes and packages or as imports - the
precise rule is that we should be able to access them using their name
only, without any prefix.
If no implicits are found in step 1, we look in the "implicit scope", which contains all sort of companion objects that bear some
relation to the type which we search for (i.e. companion object of the
type itself, of its parameters if any are given, and also of its
supertype and supertraits; the importance is to be as general as
possible without reverting to whole program analysis like Haskell
does).
If at either stage we find more than one implicit, disambiguation
kicks in. Disambiguation is exactly the same as for overloading
resolution. Static overloading resolution resolution rules are a bit
involved, and I won't repeat them here. If it's any consolation:
Java's rules and C#'s rules are considerably more complex than Scala's
in this area.
Now according to this explanation it are "the rules of static overloading resolution" which will disambiguate between notOption and hitOption. To be honest, I fail to see how.
This answer explains that indeed methods with more specific arguments have priority, but I don't know if or how that is related to the overloading rules.
If I were you I would not depend on this behavior too much, but use the easier to understand concept of implicit priority through inheritance. It's a good idea to put your implicits in the companion object anyway.
It boils down to the fact that implicits that are inherited have lower priority. So it's safe to put the implicit you fall back to if hitOption doesn't match in a trait that the companion object extends.
case class OptionFinder[A](isOption: Boolean)
object OptionFinder extends LowerPriority {
implicit def hitOption[A]: OptionFinder[Option[A]] = OptionFinder(true)
}
trait LowerPriority {
implicit def notOption[A]: OptionFinder[A] = OptionFinder(false)
}
def myFunction[A](value: A)(implicit optionFinder: OptionFinder[A]): String = {
if (optionFinder.isOption) {"Found Option!"} else {"Found something else."}
}
This should also work if you put your implicits in a non companion object MyImplicits and import them with import MyImplicits._.
So I'm trying to work through Norvig & Russell's "Artificial Intelligence, A Modern Approach" as a way to learn Scala. I have a pretty good grasp on the language basics at this point, but I still find myself often "fighting" the type system.
Long story short, breadth-first and depth-first search algorithms are the same aside from the mechanics of pushing/popping to their underlying collection. Depth-first would prepend new possibilities and use a Stack, while Breadth-first would append and use a Queue.
To keep my algorithm the same, I created a typeclass called "GiveGrab" (I know, horrible name) with the intention of pimping ... err ... enriching collections with these "default" push (give) and pop-like (grab) operations.For example, grab would result in a call to .dequeue() for queues, and .pop() for stacks.
Here's (a somewhat abbreviated version of) the code:
object Example extends App {
trait GiveGrab[A, M[A]] {
def give(x: A*): M[A]
def grab(): A
}
implicit class GiveGrabQueue[T](q: Queue[T]) extends GiveGrab[T,Queue[T]] {
override def give(x: T*) = q ++= x
override def grab() = q.dequeue()
}
class TestClass[T, X <% GiveGrab[T, Queue[T]]](var storage: X) {}
val test = new TestClass[Int, Queue[Int]](new Queue[Int]())
}
When trying to compile this, I get the following errors:
Error:(18, 39) scala.collection.mutable.Queue[T] takes no type parameters, expected: one
class TestClass[T, X <% GiveGrab[T, Queue[T]]](var storage: X) {}
^
Error:(13, 67) scala.collection.mutable.Queue[T] takes no type parameters, expected: one
implicit class GiveGrabQueue[T](q: Queue[T]) extends GiveGrab[T,Queue[T]] {
^
That said, it took me a lot of trial and error to even get to this point. I'm not sure if my trait is really supposed to be typed
trait GiveGrab[A, M[A]]
or
trait GiveGrab[A, M[_]]
or
trait GiveGrab[A, M]
The error "takes no type parameters, expected: one" doesn't make a whole lot of sense to me at this point, and there's only a handful of other posts about that message (some related to dependent types, and some related to the Play framework).
Somewhat related: is there a good article for understanding Scala type signatures? I read through Programming in Scala 2nd Ed, but it didn't really touch on this sort of type gymnastics (either that, or I just missed it.)
Edit: Typos
What #PatrykĆwiek proposed is not a workaround but actually what you are meant to be doing: M[A] in trait GiveGrab defines a type function. Roughly speaking this means: M is a type where you can apply a single type parameter to yield a concrete type. That the parameter is called A is pure coincidence. The following means the same:
trait GiveGrab[A,M[MyRandomName]] { ... }
In the definition of give, you actually use this type function to create a type, when saying M[A]. Therefore, as #PatrykĆwiek said, you should write Queue instead of Queue[T]. While Queue is precisely one of these type functions, Queue[T] is a concrete type and therefore doesn't apply to the definition of M.
The error message you get says exactly that: In the place of M, you are supposed to put a type that takes a parameter (like Queue), but you have put one which takes none (Queue[T] in your case, another example would be String or Int).
I want to come out a way to define a new method in some existing class in scala.
For example, I think the asInstanceOf[T] method has too long a name, I want to replace it with as[T].
A straight forward approach can be:
class WrappedAny(val a: Any) {
def as[T] = a.asInstanceOf[T]
}
implicit def wrappingAny(a: Any): WrappedAny = new WrappedAny(a)
Is there a more natural way with less code?
Also, a strange thing happens when I try this:
scala> class A
defined class A
scala> implicit def toA(x: Any): A = x
toA: (x: Any)A
scala> toA(1)
And the console hang. It seems that toA(Any) should not pass the type checking phase, and it can't when it's not implicit. And putting all the code into a external source code can produce the same problem. How did this happen? Is it a bug of the compiler(version 2.8.0)?
There's nothing technically wrong with your approach to pimping Any, although I think it's generally ill-advised. Likewise, there's a reason asInstanceOf and isInstanceOf are so verbosely named; it's to discourage you from using them! There's almost certainly a better, statically type-safe way to do whatever you're trying to do.
Regarding the example which causes your console to hang: the declared type of toA is Any => A, yet you've defined its result as x, which has type Any, not A. How can this possibly compile? Well, remember that when an apparent type error occurs, the compiler looks around for any available implicit conversions to resolve the problem. In this case, it needs an implicit conversion Any => A... and finds one: toA! So the reason toA type checks is because the compiler is implicitly redefining it as:
implicit def toA(x: Any): A = toA(x)
... which of course results in infinite recursion when you try to use it.
In your second example you are passing Any to a function that must return A. However it never returns A but the same Any you passed in. The compiler then tries to apply the implicit conversion which in turn does not return an A but Any, and so on.
If you define toA as not being implicit you get:
scala> def toA(x: Any): A = x
<console>:6: error: type mismatch;
found : Any
required: A
def toA(x: Any): A = x
^
As it happens, this has been discussed on Scala lists before. The pimp my class pattern is indeed a bit verbose for what it does, and, perhaps, there might be a way to clean the syntax without introducing new keywords.
The bit about new keywords is that one of Scala goals is to make the language scalable through libraries, instead of turning the language into a giant quilt of ideas that passed someone's criteria for "useful enough to add to the language" and, at the same time, making other ideas impossible because they weren't deemed useful and/or common enough.
Anyway, nothing so far has come up, and I haven't heard that there is any work in progress towards that goal. You are welcome to join the community through its mailing lists and contribute to its development.
In Scala, if I define a method called apply in a class or a top-level object, that method will be called whenever I append a pair a parentheses to an instance of that class, and put the appropriate arguments for apply() in between them. For example:
class Foo(x: Int) {
def apply(y: Int) = {
x*x + y*y
}
}
val f = new Foo(3)
f(4) // returns 25
So basically, object(args) is just syntactic sugar for object.apply(args).
How does Scala do this conversion?
Is there a globally defined implicit conversion going on here, similar to the implicit type conversions in the Predef object (but different in kind)? Or is it some deeper magic? I ask because it seems like Scala strongly favors consistent application of a smaller set of rules, rather than many rules with many exceptions. This initially seems like an exception to me.
I don't think there's anything deeper going on than what you have originally said: it's just syntactic sugar whereby the compiler converts f(a) into f.apply(a) as a special syntax case.
This might seem like a specific rule, but only a few of these (for example, with update) allows for DSL-like constructs and libraries.
It is actually the other way around, an object or class with an apply method is the normal case and a function is way to construct implicitly an object of the same name with an apply method. Actually every function you define is an subobject of the Functionn trait (n is the number of arguments).
Refer to section 6.6:Function Applications of the Scala Language Specification for more information of the topic.
I ask because it seems like Scala strongly favors consistent application of a smaller set of rules, rather than many rules with many exceptions.
Yes. And this rule belongs to this smaller set.