by name parameter & _的用法
Posted satyrs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了by name parameter & _的用法相关的知识,希望对你有一定的参考价值。
关于byname byvalue何时计算的问题
A by-name parameter acts like a def
.
Scala has a solution to this problem called by-name parameters. By declaring a parameter as a: => A
(note that the space after the :
is necessary) we are telling Scala to evaluate a
only when it is used (which may be never). So let’s fix our method.
def when[A](test: Boolean, whenTrue: A, whenFalse: A): A = test match { case true => whenTrue case false => whenFalse } scala> when(1 == 2, "foo", "bar") res13: String = bar scala> when(1 == 1, "foo", "bar") res14: String = foo // Ok so far, but... scala> when(1 == 1, println("foo"), println("bar")) foo bar def when[A](test: Boolean, whenTrue: => A, whenFalse: => A): A = test match { case true => whenTrue case false => whenFalse } // Try that again... scala> when(1 == 1, println("foo"), println("bar")) foo scala> when(1 == 2, println("foo"), println("bar")) bar
When we talk about laziness we mean that an expression is reduced by need, as is the case with lazy val
in Scala.
val a = { println("computing a"); util.Random.nextInt(10) } def a = { println("computing a"); util.Random.nextInt(10) } List(a, a, a, a, a)//及时计算 def five[A](a: => A): List[A] = List(a, a, a, a, a) five { println("computing a"); util.Random.nextInt(10) }//by name 也及时计算 lazy val a = { println("computing a"); util.Random.nextInt(10) } def five[A](a: => A): List[A] = { lazy val b = a; List(b, b, b, b, b) } five { println("computing a"); util.Random.nextInt(10) } //这里lazy后不计算 //lazy val is computed once like any other val, but not until its value is needed.
So although we used by-name parameters to implement lazy behavior for our when
function above, this is dependent on only referencing each parameter once.
A parameter is strict if its argument is always evaluated, regardless of calling convention; in our five
function above our parameter is both by-name and strict.
reference a by-name parameter without forcing its evaluation:can apply η-expansion (put an underscore after the identifier) to turn it into a function value.
所以说,when中实现了lazy是因为对每个parameter只引用一次。
若需要引用by-name parameter,但又不想计算,则可以在identifier后加上_转为function value。_作用是we construct a Function1
instance that delegates to our method. (val f = add1 _)
scala> def foo(a: => Unit): () => Unit = a _ foo: (a: => Unit)() => Unit scala> val z = foo(println("hi")) z: () => Unit = <function0> scala> z() hi
以下几个情景使用 _ :
函数的类的实例赋给val(不用_则需要声明类型信息, 调用新名称时需要()),map以函数作参对每一个元素操作,
多个参数时:如果有默认arguments则不能partial application
Values in scala cannot have type parameters; when η-expanding a parameterized method all type arguments must be specified (or they will be inferred as non-useful types): 即所有类型参数必须指明,否则为无用类型
val g = new Function1[Int, Int] { def apply(n: Int): Int = add1(n) }
scala> List(1,2,3).map(add1 _) res5: List[Int] = List(2, 3, 4) scala> List(1,2,3).map(add1) res6: List[Int] = List(2, 3, 4)
scala> val z = add1//需要赋予类型信息
<console>:8: error: missing arguments for method add1;
follow this method with `_‘ if you want to treat it as a partially applied function
val z = add1
^
scala> val z: Int => Int = add1
z: Int => Int = <function1>
scala> val z = add1 : Int => Int
z: Int => Int = <function1>
scala> "foo".substring _
<console>:8: error: ambiguous reference to overloaded definition,
both method substring in class String of type (x$1: Int, x$2: Int)String
and method substring in class String of type (x$1: Int)String
match expected type ?
"foo".substring _
^
scala> "foo".substring _ : (Int => String)
res14: Int => String = <function1>
scala> def x = println("hi")
x: Unit
scala> val z = x // ok
hi
z: Unit = ()
scala> val z = x _
z: () => Unit = <function0>
scala> z()
hi
-----------
scala> def plus(a: Int, b: Int): Int = a + b plus: (a: Int, b: Int)Int scala> plus _ res8: (Int, Int) => Int = <function2>
scala> def plus(a: Int)(b: Int): Int = a + b
plus: (a: Int)(b: Int)Int
scala> plus _
res11: Int => (Int => Int) = <function1>
scala> plus(1)
<console>:9: error: missing arguments for method plus;
follow this method with `_‘ if you want to treat it as a partially applied function
plus(1)
^
scala> plus(1) _
res13: Int => Int = <function1>
scala> val x = plus _ x: Int => (Int => Int) = <function1> scala> x(1) // no underscore needed res0: Int => Int = <function1>
-------------#implicit members
scala> def foo[N:Numeric](n:N):N = n foo: [N](n: N)(implicit evidence$1: Numeric[N])N scala> foo[String] _ <console>:9: error: could not find implicit value for evidence parameter of type Numeric[String] foo[String] _ ^ scala> foo[Int] _ res3: Int => Int = <function1> scala> def bar[N](n:N)(implicit ev: Numeric[N]):N = n bar: [N](n: N)(implicit ev: Numeric[N])N scala> bar[Int] _ res4: Int => Int = <function1>
-------------
scala> def foo(n: Int = 3, s: String) = s * n
foo: (n: Int, s: String)String
scala> foo _
res19: (Int, String) => String = <function2>
scala> foo(42) _
<console>:9: error: not enough arguments for method foo: (n: Int, s: String)String.
Unspecified value parameter s.
foo(42) _
以上是关于by name parameter & _的用法的主要内容,如果未能解决你的问题,请参考以下文章
Caused by: java.security.InvalidKeyException: Illegal key size or default parameters
hive的 order by & distribute by & cluter by
AndroidStudio启动异常:Caused by: java.lang.IllegalArgumentException: Argument for @NotNull paramet
异常Caused by: java.lang.IllegalStateException: Method has too many Body parameters