Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在scala中,如何找到函数中定义的子例程的调用_Scala_Reflection - Fatal编程技术网

在scala中,如何找到函数中定义的子例程的调用

在scala中,如何找到函数中定义的子例程的调用,scala,reflection,Scala,Reflection,假设我有一个函数/方法: class A { def function() = { subroutine("A") ... subroutine("B") ... subroutine("C") } def subroutine(a: String) = { ... } } 是否可以使用Scala反射编程来查找function()中所有3个子程序调用(a:String),而不调用function()本身?(这可能需要一个很长的过程)您可以尝试通过一些很酷的功

假设我有一个函数/方法:

class A {

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

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

}

是否可以使用Scala反射编程来查找function()中所有3个子程序调用(a:String),而不调用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"


用例是什么?是否只想查找静态事件?例如,如果一个循环中多次调用一个循环会发生什么?Hi Paul:是的,我只想找到静态事件(编译时宇宙理论上可以处理),而不管它们是否实际被调用。你为什么要这样做?它是一种分析scala代码的工具,还是在程序运行时用于某些控制流的工具?它是一种控制流,是一个库,其中scala函数可以作为API参数进行“插值”,调用每个函数都需要一些初始化过程,这些过程应该在主API之前确定。非常感谢您向我介绍这个令人惊叹的库!但不幸的是,在我的例子中,函数“abs”是一个复杂的算法,由数千行用普通scala编写的代码组成,可能会被不同的人扩展。因此,解决方案只能证明其规模小得多的成本是合理的。
abs4.run(15, 20, 36, 48)
abs4.printHier