Skip to content

Commit

Permalink
Version 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
cvogt committed Mar 3, 2016
0 parents commit 40746f2
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
target
42 changes: 42 additions & 0 deletions build/build.scala
@@ -0,0 +1,42 @@
import cbt._
import java.net._
import java.io.File
import scala.collection.immutable.Seq

class Build(context: cbt.Context) extends cbt.PublishBuild(context){
override def scalaVersion = "2.11.7"

override def version = "1.0"
override def artifactId = "lens_2.11"
override def groupId = "ai.x"

object monocle{
val version = "1.2.0"
val org = "com.github.julien-truffaut"
val core = org %% "monocle-core" % version
val generic = org %% "monocle-generic" % version
val macro_ = org %% "monocle-macro" % version
val all = Seq(core, generic, macro_)
}

override def dependencies = super.dependencies ++ monocle.all
override def scalacOptions = super.scalacOptions ++ Seq( "-language:experimental.macros" )

override def url = new URL("http://github.com/xdotai/lens")
override def licenses = Seq(
License("Two-clause BSD-style license",
new URL("http://github.com/xdotai/lens/blob/master/LICENSE.txt"))
)
override def developers = Seq(
Developer("cvogt", "Jan Christopher Vogt", "-5", new URL("https://github.com/cvogt/"))
)
override def scmUrl = "git@github.com:xdotai/lens.git"
override def scmConnection = "scm:git:git@github.com:xdotai/lens.git"
override def description = "Convenient ad-hoc lens Syntax on top of Monocle"
override def pomExtra =
<inceptionYear>2016</inceptionYear>
<organization>
<name>x.ai</name>
<url>http://x.ai</url>
</organization>
}
35 changes: 35 additions & 0 deletions lens.scala
@@ -0,0 +1,35 @@
package ai.x.lens

import scala.reflect.macros.blackbox.Context
import scala.language.experimental.macros
import monocle._
import monocle.syntax.ApplyLens

object `package`{
implicit class ImplicitBoundLens[T]( v: T ) {
def lens = BoundLens( v )
}
}

object BoundLens {
def apply[S]( value: S ) = new BoundLens( ApplyLens[S, S, S, S]( value, Lens.id ) )
}

/** Syntactic sugar around an ApplyLens */
class BoundLens[S, A]( val applyLens: ApplyLens[S, S, A, A] ) extends AnyVal {
def apply[C]( field: A => C ): BoundLens[S, C] = macro BoundLensMacros.apply[S, A, C]
def set( value: A ): S = applyLens.set( value )
def modify( diff: A => A ): S = applyLens.modify( diff )
}

object BoundLensMacros {
def apply[S, A: c.WeakTypeTag, C]( c: Context )( field: c.Expr[A => C] ) = {
import c.universe._
c.Expr[BoundLens[S, C]]( q"""
new _root_.ai.x.lens.BoundLens(
${c.prefix.tree}.applyLens composeLens
_root_.monocle.macros.GenLens[${c.weakTypeOf[A]}](${field})
)
""" )
}
}
17 changes: 17 additions & 0 deletions test/Test.scala
@@ -0,0 +1,17 @@
object Main extends App{
// usage example
import ai.x.lens.ImplicitBoundLens
case class Inner( i: Int )
case class Outer( inner: Inner, s: String )
val o = Outer(Inner(5), "foo")

val actual =
o.lens(_.s).set("bar")
.lens(_.inner.i).modify(_+1) // .lens calls can be chained nicely

val expected = Outer(Inner(6),"bar")

assert( expected == actual, s"$expected == $actual" )

println(Console.GREEN + "Success" + Console.RESET)
}
10 changes: 10 additions & 0 deletions test/build/build.scala
@@ -0,0 +1,10 @@
import cbt._
import java.net._
import java.io.File
import scala.collection.immutable.Seq

class Build(context: cbt.Context) extends cbt.DefaultBuild(context) with mixins.Test{
override def scalaVersion = "2.11.7"

override def scalacOptions = super.scalacOptions ++ Seq( "-language:higherKinds" )
}

0 comments on commit 40746f2

Please sign in to comment.