2015-11-13 67 views
2

假设我有一个功能/方法定义子程序的调用:Scala中,如何找到在功能

class A { 

def function() = { 
    subroutine("A") 
    ... 
    subroutine("B") 
    ... 
    subroutine("C") 
} 

def subroutine(a: String) = { ... } 

} 

是否有可能使用的Scala反射编程查找子程序的所有3次调用(一个:字符串)在函数(),而不调用函数()本身? (这可能需要很长的过程)

+0

有什么用例?你只想找到静态事件?例如,如果一个人在一个循环中被多次调用,或者因为一个条件而根本没有被调用,会发生什么? –

+0

嗨保罗:是的,我只是想找到静态的发生(理论上编译时间的宇宙可以处理),无论它们是否实际调用。 – tribbloid

+0

你为什么要这样做?它是一个分析scala代码的工具,还是用于程序运行时的一些控制流程? – jazmit

回答

1

你可以尝试通过一些很酷的功能工具来解决这个问题,而不需要自省。

让我们使用scalaz library它有特殊的类型Arrow这是抽象的Function
它可以做几乎任何你通常做的功能。
因此,让我们定义不仅包含函数的特殊类型,而且以可读的方式调用层次结构。

import scalaz._ 
import scalaz.syntax.tree._ 
import scalaz.std.function._ 
import scalaz.syntax.arrow._ 
import scalaz.std.string._ 

case class Subroutine[-A, +B](hier: Seq[Tree[String]], run: A => B) { 
    def named(name: String) = Subroutine(Seq(name.node(hier: _*)), run) 

    def printHier = hier.map(_.drawTree).mkString("\n" + "V" * 15 + "\n") 
} 

object Subroutine { 
    def named[A, B](tag: String)(run: A => B) = Subroutine(Seq(tag.leaf), run) 

    implicit def anon[A, B](run: A => B) = Subroutine(Seq.empty, run) 

    implicit object subroutineArrow extends Arrow[Subroutine] { 
    def arr[A, B](f: (A) => B): Subroutine[A, B] = anon(f) 

    def first[A, B, C](f: Subroutine[A, B]): Subroutine[(A, C), (B, C)] = 
     Subroutine(f.hier, f.run.first[C]).named("$1->") 

    override def second[A, B, C](f: Subroutine[A, B]): Subroutine[(C, A), (C, B)] = 
     Subroutine(f.hier, f.run.second[C]).named("$2->") 

    def id[A]: Subroutine[A, A] = anon(identity) 

    def compose[A, B, C](f: Subroutine[B, C], g: Subroutine[A, B]): Subroutine[A, C] = 
     Subroutine(g.hier ++ f.hier, f.run compose g.run) 
    } 
} 

现在让我们来定义一些子程序

import Subroutine._ 

val square = { (x: Double) => x * x } named "square" 
val sqrt = math.sqrt _ named "sqrt" 

val sum = Subroutine.named[(Double, Double), Double]("sum"){ case (x, y) => x + y} 

val abs = ((square *** square) >>> sum >>> sqrt) named "abs" 

从这里可以确认

abs.run(3,4) 

给出结果5.0

abs.printHier 

给像

"abs" 
| 
+- "$1->" 
| | 
| `- "square" 
| 
+- "$2->" 
| | 
| `- "square" 
| 
+- "sum" 
| 
`- "sqrt" 

甚至有趣的调用顺序定义

def pack22[X] = Subroutine.anon[(X, X, X, X), ((X, X), (X, X))] { case (a, b, c, d) => ((a, b), (c, d)) } 

val abs4 = ((abs *** abs) >>> abs <<< pack22[Double]) named "abs4" 

和评估

abs4.run(15, 20, 36, 48) 

abs4.printHier 
+0

非常感谢我向我介绍这个惊人的库!但不幸的是,在我的情况下,函数“abs”是一个用普通的scala编写的数千行代码的复杂算法,并且可能由不同的人扩展。所以解决方案只能证明其规模小得多。 – tribbloid