试图了解一些scala语法,以及在何处找到其规格。在下面,我对statefulMapConcat感到困惑。
签名是这个:
def statefulMapConcat [T](f:()=> Out => immutable.Iterable [T]):代表[T]
我们有
"be able to restart" in {
Source(List(2, 1, 3, 4, 1))
.statefulMapConcat(() => {
var prev: Option[Int] = None
x => {
if (x % 3 == 0) throw ex
prev match {
case Some(e) =>
prev = Some(x)
(1 to e).map(_ => x)
case None =>
prev = Some(x)
List.empty[Int]
}
}
})
.withAttributes(ActorAttributes.supervisionStrategy(Supervision.restartingDecider))
.runWith(TestSink.probe[Int])
.request(2)
.expectNext(1, 1)
.request(4)
.expectNext(1, 1, 1, 1)
.expectComplete()
}
我不太满意
{
var prev: Option[Int] = None
x => {
if (x % 3 == 0) throw ex
prev match {
case Some(e) =>
prev = Some(x)
(1 to e).map(_ => x)
case None =>
prev = Some(x)
List.empty[Int]
}
}
对应于
Out =>不可变。Iterable[T]
有人可以帮我分解吗?
在我看来,x
对应于Out
,但随后我们在var prev: Option[Int] = None
之前声明了一个变量
我想了解这些scala魔术,并从何处获得解释
这里要理解的两个关键概念是
考虑以下块表达式
{
var prev: Option[Int] = None
42 // I am the last value of the block
}
因为块中的最后一个表达式的值为42
,所以整个块的值为42
类型的Int
。
类似地,考虑以下块表达式
{
var prev: Option[Int] = None
(x: Int) => { x + 1 } // I am also the last *value* of the block
}
因为块中的最后一个表达式的值为(x: Int) => { x + 1 }
,所以整个块的值为(x: Int) => { x + 1 }
类型的值Int => Int
。
在两种情况下,由于表达式var prev: Option[Int] = None
并非块中的最后一个表达式,因此它不会影响整个块的值的类型。
快速说明。实际上,当您将单个arg编写为块时,没有内部花括号:
scala> def f(g: () => String => Int) = g()("42")
f: (g: () => String => Int)Int
scala> f(() => _.toInt)
res0: Int = 42
scala> f { () => s => s.toInt }
res1: Int = 42
scala> f ( () => s => s.toInt )
res2: Int = 42
scala> f { val x = "0" ; () => val y = x + "0" ; s => (s+y).toInt }
res3: Int = 4200
显示-Vprint:parser
(2.12中的-Xprint
,它可以正确解析,即使分号可能使人眼花]乱:
val res3 = f({
val x = "0";
(() => {
val y = x.$plus("0");
((s) => s.$plus(y).toInt)
})
})
编辑:神奇捕获的变量在堆上:
scala> { var i = 42 ; (j: Int) => j + i }
res1: Int => Int = $$Lambda$892/0x00000001006ec840@6e981e78
scala> :javap -c -
Compiled from "<console>"
public class $line4.$read$$iw$$iw$ {
public static final $line4.$read$$iw$$iw$ MODULE$;
public static {};
Code:
0: new #2 // class $line4/$read$$iw$$iw$
3: dup
4: invokespecial #25 // Method "<init>":()V
7: putstatic #27 // Field MODULE$:L$line4/$read$$iw$$iw$;
10: bipush 42
12: invokestatic #33 // Method scala/runtime/IntRef.create:(I)Lscala/runtime/IntRef;
15: astore_0
16: aload_0
17: invokedynamic #52, 0 // InvokeDynamic #0:apply$mcII$sp:(Lscala/runtime/IntRef;)Lscala/runtime/java8/JFunction1$mcII$sp;
22: putstatic #54 // Field res1:Lscala/Function1;
25: return
public scala.Function1<java.lang.Object, java.lang.Object> res1();
Code:
0: getstatic #54 // Field res1:Lscala/Function1;
3: areturn
public static final int $anonfun$res1$1(scala.runtime.IntRef, int);
Code:
0: iload_1
1: aload_0
2: getfield #65 // Field scala/runtime/IntRef.elem:I
5: iadd
6: ireturn
public $line4.$read$$iw$$iw$();
Code:
0: aload_0
1: invokespecial #66 // Method java/lang/Object."<init>":()V
4: return
}