- Notifications
You must be signed in to change notification settings - Fork4
macro for summoning implicit values
License
non/imp
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Imps have also been described as beingbound or contained in somesort of object, such as a sword or crystal ball. In other cases,imps were simply kept in a certain object and summoned only whentheir masters had need of them. Some even had the ability to granttheir owners wishes, much like agenie.
-- Wikipedia entry for "Imp"
This is a very small library that exists to scratch one itch.
It provides a zero-cost macro to summon implicit values.
One use of this is theimp
method, which is similar toimplicitly
(but without any of the latter's indirection). Previously, there werecases where context-bound syntax [1] or other indirection was notoptimal due to the cost associated withimplicitly
.
There is a convention when creating type classes in Scala to provideanapply
method on the companion object, to access an implicit typeclass instance. Thesummon
macro can be used here to create a moreefficient form of this method.
([1] By context-bound, I mean declaring a type parameter as[A: Magma]
, which corresponds to[A]
with an(implicit ev: Magma[A])
parameter also.)
Imp supports Scala 2.10, 2.11, 2.12, and 2.13. If you use SBT,you can include Imp via the followingbuild.sbt
snippets:
libraryDependencies+="org.spire-math"%%"imp"%"0.4.0"%"provided"// if you want to use the imp.summon macro you'll need this too:libraryDependencies+="org.scala-lang"%"scala-reflect"% scalaVersion.value%"provided"
Imp also supports scala.js, which you can use via the following snippet:
libraryDependencies+="org.spire-math"%%%"imp"%"0.4.0"%"provided"
These dependencies are bothcompile-time only -- there is no runtimecost (in jars, size, execution time, etc) imposed by Imp.
Here's an example which creates a reversed ordering instance:
importimp.impvalreversed= imp[Ordering[Int]].reverse// equivalent to: Ordering.Int.reverse// better than: implicitly[Ordering[Int]].reverse
Here's a definition of theMagma
type class which usesimp.summon
:
importimp.summonimportlanguage.experimental.macrostraitMagma[A] {defcombine(x:A,y:A):A}objectMagma {defapply[A:Magma]:Magma[A]= macro summon[Magma[A]]// better than: def apply[A](implicit ev: Magma[A]): Magma[A] = ev// (even using @inline and final)implicitvalIntMagma:Magma[Int]=newMagma[Int] {defcombine(x:Int,y:Int):Int= x+ y }}Magma[Int].combine(3,4)// equivalent to: Magma.IntMagma.combine(3, 4)// also equivalent to: imp[Magma[Int]].combine(3, 4)// better than: implicitly[Magma[Int]].combine(3, 4)
Dmitry Petrashko has argued persuasively that modern Hotspotoptimizations mean that Imp is unnecessary. See theimp-bench repository formore information on his benchmarks.
More recently, Gabriel Volpe wrote somebenchmarkswhich did find a difference between usingimplicitly
andimp
(andwhich also discusses some interesting compiler flags to try).
All code is available to you under the MIT license, available athttp://opensource.org/licenses/mit-license.php and also in theCOPYING file.
See theCode of Conduct
Copyright Erik Osheim, 2016-2019.
About
macro for summoning implicit values