在scala的自定义控制结构中声明变量

declare variable in custom control structure in scala

我想知道是否有办法在自定义控制结构的参数列表中创建临时变量。

基本上,我想创建一个类似于
for 循环,我可以在其中创建一个变量 i,并且只能在循环体中访问 i:

1
2
3
4
for(i<- 1 to 100) {
   //loop body can access i here
}
//i is not visible outside

我想在我的代码中做类似的事情。例如,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
customControl ( myVar <-"Task1") {
    computation(myVar)
}

customControl ( myVar <-"Task2") {
    computation(myVar)
}
def customControl (taskId:String) (  body: => Any) = {
    Futures.future {
        val result = body

        result match {
            case Some(x) =>
                logger.info("Executed successfully")
                x
            case _ =>
                logger.error(taskId +" failed")
                None
        }

    }
}

现在,我通过在自定义控制结构之外声明一个变量来解决这个问题,这看起来不太优雅。

1
2
3
4
5
6
7
8
9
val myVar ="Task1"
customControl {
    computation(myVar)
}

val myVar2 ="Task2"    
customControl {
    computation(myVar2 )
}


你可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import scala.actors.Futures

def custom(t: String)(f: String => Any) = {
  Futures.future {
    val result = f(t)

    result match {
      case Some(x) =>
        println("Executed successfully")
        x
      case _ =>
        println(t +" failed")
        None
    }

  }
}

然后你可以得到这样的语法,这不完全是你所要求的,但是你不用在单独的行上声明变量:

1
2
3
4
5
6
7
8
9
10
11
scala> custom("ss") { myvar => println("in custom" + myvar); myvar +"x" }
res7: scala.actors.Future[Any] = <function0>
in custom ss
ss failed

scala> custom("ss") { myvar => println("in custom" + myvar); Some(myvar +"x") }
in custom ss
Executed successfully
res8: scala.actors.Future[Any] = <function0>

scala>

注意,内置的 for (x <- expr) body 只是

的语法糖

1
expr foreach (x => body)

因此,可以通过定义自定义 foreach 方法来实现您想要的(使用现有的 for 语法)。

还请注意,已经有一个适用于字符串的 foreach 方法。你可以这样做:

1
2
3
case class T(t: String) {
  def foreach(f: String => Unit): Unit = f(t)
}

注意:您也可以将上面 f 的结果类型从 Unit 更改为 Any,它仍然可以工作。

这会让你做类似

的事情

1
2
for (x <- T("test"))
  print(x)

这只是一个微不足道的(和无用的)示例,因为现在 for (x <- T(y)) f(x) 只是缩写(或者更确切地说是"延长")f(y)。当然,通过将上述foreach定义中的f的参数从String改成别的东西,并从字符串t做相应的翻译到这个类型,你可以达到更有用的效果。