It can in fact be done just as you want. The other answerers surrendered too quickly. No white flags!
Package object foo { type HasLogger = { def logger: Logger } implicit def mkLog(x: HasLogger) = new { def loggingExceptions(body: => Unit): Unit = try body catch { case ex: Exception => println(ex) } } } package foo { case class Logger(name: String) { } // Doesn't compile: // class A { // def f = this. LoggingExceptions(println("hi")) // } // 1124. Scala:14: error: value loggingExceptions is not a member of foo.
A // def f = this. LoggingExceptions(println("hi")) // ^ // one error found // Does compile class B { def logger = Logger("B") def f = this. LoggingExceptions(println("hi")) def g = this.
LoggingExceptions(throw new Exception) } } object Test { def main(args: ArrayString): Unit = { val be = new foo. B b. F b.
G } } // output // // % scala Test // hi // java.lang.Exception.
1 for the example. This can be done, but it's inadvisable. It doesn't separate the logging concern as well as a Logging trait, requires "implicit magic", and incurs unnecessary compile-time (implicit search) and run-time (reflection) overhead.
The implementation hides the fact that the implicit conversion needs to be in scope, and in a more realistic codebase this would require an import statement in the client code. – Aaron Novstrup Nov 24 '10 at 20:57 2 Your list of negatives sums up to "I'd rather solve a different problem. " Well yeah, wouldn't we all.
– extempore Nov 24 '10 at 21:13 Not really. The fundamental problem is logging exceptions in a block of code within a class that has a logger. You can solve that problem the way the OP originally envisioned (with implicits), or you can solve it much more simply with a trait.
– Aaron Novstrup Nov 24 '10 at 21:56 I just re-read the question. Maybe the logging use case was just a motivating example to get at a more general technique? Sheepish grin – Aaron Novstrup Nov 24 '10 at 22:02 @Aaron The logging case was my actual problem to be solved, and I'm happy with the trait solution.
But it's also useful to know how to "simulate" how such a "implicit-this substitute" could work. – Jean-Philippe Pellet Nov 24 '10 at 23:03.
You could add a trait to all classes which want to use def loggingExceptions and in this trait add a self-type which expects def logger: Logger being available. Trait LoggingExceptions { this: { def logger: Logger } => def loggingExceptions(work: => Unit) { try { work } catch { case t: Exception => logger. Error(t.
GetMessage) } } } object MyObjectWithLogging extends OtherClass with LoggingExceptions { def logger: Logger = // ... def main { // ... loggingExceptions { // ... } } }.
Thanks, this works! But are there any other solutions that don't involve changing the declaration of all classes that wish to use loggingExceptions(...)? – Jean-Philippe Pellet Nov 24 '10 at 19:23 @JPP No, at the very least the callsite will need to have an implicit object of the expected type in scope.
For example, you could make the implicit parameter a Logger, and change the def logger to implicit def logger in the calling object. However, implicits should be avoided unless necessary, and a trait is a good fit for this problem. – Aaron Novstrup Nov 24 '10 at 19:47.
Debilski's answer will work, but I'm not sure I see a good reason to use a structural type (i.e. { def logger: Logger }) here. Doing so will incur extra runtime overhead whenever logger is invoked, since the implementation of structural types relies on reflection.
The loggingExceptions method is closely tied to logging, so I would just make it part of a Logging trait: trait Logging { def logger: Logger final def loggingExceptions(body: => Unit) = try body catch { case e: Exception => logger. Error(e. GetMessage) } } trait ConcreteLogging extends Logging { val logger = // ... } object MyObject extends SomeClass with ConcreteLogging { def main { // ... loggingExceptions { // ... } } }.
This syntactic sugar is described as a view bound, akin to an upper bound (CC : Null). Another common pattern in implicit parameters is the type class pattern. This pattern enables the provision of common interfaces to classes which did not declare them.
It can both serve as a bridge pattern -- gaining separation of concerns -- and as an adapter pattern. The Integral class you mentioned is a classic example of type class pattern. Another example on Scala's standard library is Ordering.
There's a library that makes heavy use of this pattern, called Scalaz. There is also a syntactic sugar for it, called a context bound, which is made less useful by the need to refer to the implicit. Context bounds are more useful when you just need to pass them to other methods that use them.
For example, the method sorted on Seq needs an implicit Ordering. Because OrderingT was implicitly passed to reverseSort, it can then pass it implicitly to sorted. Where do Implicits Come From?
When the compiler sees the need for an implicit, either because you are calling a method which does not exist on the object's class, or because you are calling a method that requires an implicit parameter, it will search for an implicit that will fit the need. This search obey certain rules that define which implicits are visible and which are not. The following table showing where the compiler will search for implicits was taken from an excellent presentation about implicits by Josh Suereth, which I heartily recommend to anyone wanting to improve their Scala knowledge.
Let's give examples for them. This is like the first example, but assuming the implicit definition is in a different file than its usage. See also how package objects might be used in to bring in implicits.
There are two object companions of note here. First, the object companion of the "source" type is looked into. For instance, inside the object Option there is an implicit conversion to Iterable, so one can call Iterable methods on Option, or pass Option to something expecting an Iterable.
FlatMap expects a TraversableOnce, which Option is not. The compiler then looks inside Option's object companion and finds the conversion to Iterable, which is a TraversableOnce, making this expression correct. The method sorted takes an implicit Ordering.
In this case, it looks inside the object Ordering, companion to the class Ordering, and finds an implicit OrderingInt there. Note that companion objects of super classes are also looked into. This is how Scala found the implicit NumericInt and NumericLong in your question, by the way, as they are found inside Numeric, not Integral.
This is required to make the type class pattern really work. Consider Ordering, for instance... it comes with some implicits in its companion object, but you can't add stuff to it. So how can you make an Ordering for your own class that is automatically found?
As we saw, the method sorted expects an OrderingA (actually, it expects an OrderingB, where B >: A). There isn't any such thing inside Ordering, and there is no "source" type on which to look. Obviously, it is finding it inside A, which is a type parameter of Ordering.
This is also how various collection methods expecting CanBuildFrom work: the implicits are found inside companion objects to the type parameters of CanBuildFrom. I haven't actually seen examples of this. I'd be grateful if someone could share one.
I'm pretty sure this was a joke.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.