From fd1ca1e63c876046936f681be26730a301da8ff2 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sun, 20 Feb 2011 06:51:57 +0000 Subject: Moved unlift to the Function companion object, ... Moved unlift to the Function companion object, which might have been better in the first place. Had to make a minor change to genprod, and then I couldn't escape that unscathed. Finished the not very complete undertaking I found there to update the scaladoc. Lots of little changes to the generated text and code. I changed genprod to only put a unique stamp on Function0 so we can stop having a 100 file diff everytime an i is dotted somewhere. Closes #3825, no review. --- src/build/genprod.scala | 165 ++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 91 deletions(-) (limited to 'src/build/genprod.scala') diff --git a/src/build/genprod.scala b/src/build/genprod.scala index c95346ad94..d1c610d046 100644 --- a/src/build/genprod.scala +++ b/src/build/genprod.scala @@ -15,7 +15,7 @@ * @author Burak Emir, Stephane Micheloud, Geoffrey Washburn, Paul Phillips * @version 1.1 */ -object genprod { +object genprod extends Application { val MAX_ARITY = 22 def arities = (1 to MAX_ARITY).toList @@ -48,16 +48,12 @@ object genprod { def covariantSpecs = "" def contravariantSpecs = "" def contraCoArgs = typeArgsString((targs map (contravariantSpecs + "-" + _)) ::: List(covariantSpecs + "+R")) - def constructorArgs = (targs).map( _.toLowerCase ) mkString "," - def fields = (mdefs, targs).zipped.map(_ + ":" + _) mkString "," - def funArgs = (vdefs, targs).zipped.map(_ + ":" + _) mkString "," + def constructorArgs = (targs).map( _.toLowerCase ) mkString ", " + def fields = (mdefs, targs).zipped.map(_ + ": " + _) mkString ", " + def funArgs = (vdefs, targs).zipped.map(_ + ": " + _) mkString ", " - def genprodString = "// generated by genprod on %s %s %s".format(now, withFancy, withMoreMethods) - def now = new java.util.Date().toString() + def genprodString = " See scala.Function0 for timestamp." def moreMethods = "" - def descriptiveComment = "" - def withFancy = if (descriptiveComment.isEmpty) "" else "(with fancy comment)" - def withMoreMethods = if (moreMethods.isEmpty) "" else "(with extra methods)" def packageDef = "scala" def imports = "" @@ -69,29 +65,27 @@ object genprod { ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ - -%s +// GENERATED CODE: DO NOT EDIT.%s package %s %s -""".trim.format(genprodString, packageDef, imports) + "\n\n" +""".trim.format(genprodString, packageDef, imports) } - def main(args: Array[String]) { - if (args.length != 1) { - println("please give path of output directory") - exit(-1) - } - val out = args(0) - def writeFile(node: scala.xml.Node) { - import scala.tools.nsc.io._ - val f = Path(out) / node.attributes("name").toString - f.parent.createDirectory(force = true) - f.toFile writeAll node.text - } - - allfiles foreach writeFile + def args = arguments + if (args.length != 1) { + println("please give path of output directory") + exit(-1) + } + val out = args(0) + def writeFile(node: scala.xml.Node) { + import scala.tools.nsc.io._ + val f = Path(out) / node.attributes("name").toString + f.parent.createDirectory(force = true) + f.toFile writeAll node.text } + + allfiles foreach writeFile } import genprod._ @@ -101,17 +95,16 @@ import genprod._ zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz */ object FunctionZero extends Function(0) { + override def genprodString = "\n// genprod generated these sources at: " + new java.util.Date() override def covariantSpecs = "@specialized " - override def descriptiveComment = functionNTemplate.format("currentSeconds", "anonfun0", + override def descriptiveComment = functionNTemplate.format("javaVersion", "anonfun0", """ - * val currentSeconds = () => System.currentTimeMillis() / 1000L + * val javaVersion = () => sys.props("java.version") * - * val anonfun0 = new Function0[Long] { - * def apply(): Long = System.currentTimeMillis() / 1000L + * val anonfun0 = new Function0[String] { + * def apply(): String = sys.props("java.version") * } - * - * println(currentSeconds()) - * println(anonfun0()) + * assert(javaVersion() == anonfun0()) * """) override def moreMethods = "" } @@ -123,41 +116,28 @@ object FunctionOne extends Function(1) { override def descriptiveComment = functionNTemplate.format("succ", "anonfun1", """ * val succ = (x: Int) => x + 1 - * * val anonfun1 = new Function1[Int, Int] { * def apply(x: Int): Int = x + 1 * } - * - * println(succ(0)) - * println(anonfun1(0)) + * assert(succ(0) == anonfun1(0)) * """) override def moreMethods = """ - /** Returns a function taking one argument that applies this function to `g` applied to the argument. - * @return a function `f` such that `f(x) == apply(g(x))` + /** Composes two instances of Function1 in a new Function1, with this function applied last. + * + * @tparam A the type to which function `g` can be applied + * @param g a function A => T1 + * @return a new function `f` such that `f(x) == apply(g(x))` */ def compose[A](g: A => T1): A => R = { x => apply(g(x)) } - /** Returns a function taking one argument that applies `g` to this function applied to the argument. - * @return a function `f` such that `f(x) == g(apply(x))` - */ - def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) } - - /** Turns a function `A => Option[B]` into a `PartialFunction[A, B]`. Important note: - * this transformation implies the original function will be called 2 or more - * times on each logical invocation, because the only way to supply an implementation - * of isDefinedAt is to call the function and examine the return value. + /** Composes two instances of Function1 in a new Function1, with this function applied first. * - * @see PartialFunction#lift - * @return a partial function which is defined for those inputs - * where this function returns Some(_) and undefined where - * this function returns None. + * @tparam A the result type of function `g` + * @param g a function R => A + * @return a new function `f` such that `f(x) == g(apply(x))` */ - def unlift[R1](implicit ev: R <:< Option[R1]): PartialFunction[T1, R1] = new PartialFunction[T1, R1] { - def apply(x: T1): R1 = ev(Function1.this.apply(x)).get - def isDefinedAt(x: T1): Boolean = Function1.this.apply(x).isDefined - override def lift = Function1.this.asInstanceOf[T1 => Option[R1]] - } + def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) } """ } @@ -172,14 +152,11 @@ object FunctionTwo extends Function(2) { * val anonfun2 = new Function2[Int, Int, Int] { * def apply(x: Int, y: Int): Int = if (x < y) y else x * } - * - * println(max(0, 1)) - * println(anonfun2(0, 1)) + * assert(max(0, 1) == anonfun2(0, 1)) * """) } -object Function -{ +object Function { def make(i: Int) = apply(i)() def apply(i: Int) = i match { case 0 => FunctionZero @@ -190,10 +167,10 @@ object Function } class Function(val i: Int) extends Group("Function") with Arity { - val functionNTemplate = """ - * In the following example, the definition of - * %s is a shorthand for the anonymous class - * definition %s: + def descriptiveComment = "" + def functionNTemplate = """ + * In the following example, the definition of %s is a + * shorthand for the anonymous class definition %s: * * {{{ * object Main extends Application { %s } @@ -203,17 +180,16 @@ class Function(val i: Int) extends Group("Function") with Arity { def apply() = { {header} -/** Function with {i} parameter{s}. +/** A function of {i} parameter{s}. * {descriptiveComment} */ trait {className}{contraCoArgs} extends AnyRef {{ self => - /** - * Applies this function to the argument{s}. - * @return the results of application of this function to the passed-in argument{s} + /** Apply the body of this function to the argument{s}. + * @return the result of function application. */ def apply({funArgs}): R - override def toString() = {toStr} {moreMethods} + override def toString() = {toStr} }} } @@ -235,24 +211,24 @@ trait {className}{contraCoArgs} extends AnyRef {{ self => // f(x1,x2,x3,x4,x5,x6) == (f.curried)(x1)(x2)(x3)(x4)(x5)(x6) def curryComment = { """ - /** - * Returns a curried version of this function. - * @return a function `f` such that `f%s == apply%s` + /** Creates a curried version of this function. + * + * @return a function `f` such that `f%s == apply%s` */ """.format(xdefs map ("(" + _ + ")") mkString, commaXs) } def tupleMethod = { def comment = """ - /** - * Returns a version of this function that takes a [[scala.Tuple%d]] as its argument - * instead of %d arguments. - * @return a function `f` such that `f(%s) == f(Tuple%d%s) == apply%s` + /** Creates a tupled version of this function: instead of %d arguments, + * it accepts a single [[scala.Tuple%d]] argument. + * + * @return a function `f` such that `f(%s) == f(Tuple%d%s) == apply%s` */ -""".format(i,i,commaXs, i, commaXs, commaXs) +""".format(i, i, commaXs, i, commaXs, commaXs) def body = "case Tuple%d%s => apply%s".format(i, commaXs, commaXs) - comment + " def tupled: Tuple%d%s => R = {\n %s\n }\n".format(i, invariantArgs, body) + comment + " def tupled: Tuple%d%s => R = {\n %s\n }".format(i, invariantArgs, body) } def curryMethod = { @@ -528,8 +504,15 @@ object TupleThree extends Tuple(3) { """ } -class Tuple(val i: Int) extends Group("Tuple") with Arity -{ +class Tuple(val i: Int) extends Group("Tuple") with Arity { + private def idiomatic = + if (i < 2) "" + else " Note that it is more idiomatic to create a %s via `(%s)`".format(className, constructorArgs) + + private def params = ( + 1 to i map (x => " * @param _%d Element %d of this Tuple%d".format(x, x, i)) + ) mkString "\n" + // prettifies it a little if it's overlong def mkToString() = { def str(xs: List[String]) = xs.mkString(""" + "," + """) @@ -545,10 +528,9 @@ class Tuple(val i: Int) extends Group("Tuple") with Arity {header} /** A tuple of {i} elements; the canonical representation of a [[scala.{Product.className(i)}]]. - * {descriptiveComment} * - * @constructor Create a new tuple with {i} elements. Note that it is more idiomatic to create a {className} via `({constructorArgs})`. -{to.map { index => " * @param _" + index + " element " + index + " of this `Tuple`\n" }} + * @constructor Create a new tuple with {i} elements.{idiomatic} +{params} */ case class {className}{covariantArgs}({fields}) extends {Product.className(i)}{invariantArgs} @@ -586,8 +568,7 @@ object ProductTwo extends Product(2) class Product(val i: Int) extends Group("Product") with Arity { val productElementComment = """ - /** - * Returns the n-th projection of this product if 0 < n <= productArity, + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * * @param n number of the projection to be returned @@ -603,7 +584,11 @@ class Product(val i: Int) extends Group("Product") with Arity { } def proj = { (mdefs,targs).zipped.map( (_,_) ).zipWithIndex.map { case ((method,typeName),index) => - " /** Returns a projection of element %d of this product.\n * @return a projection of element %d */\n def %s: %s\n\n".format(index+1,index+1,method,typeName) + """| /** A projection of element %d of this Product. + | * @return A projection of element %d. + | */ + | def %s: %s + |""".stripMargin.format(index + 1, index + 1, method, typeName) } mkString } @@ -615,12 +600,10 @@ object {className} {{ }} /** {className} is a cartesian product of {i} component{s}. - * {descriptiveComment} * @since 2.3 */ trait {className}{covariantArgs} extends Product {{ - /** - * The arity of this product. + /** The arity of this product. * @return {i} */ override def productArity = {i} -- cgit v1.2.3