Publish to my blog (weekly)

  • Serverless Messenger 개발을 위해 검토해볼만 한 기술 Microsoft Rome: https://blogs.windows.com/buildingapps/2017/05/16/announcing-project-rome-ios-sdk/#q1Imi7DtdxUSjElq.97

    • In each example we have a call to foldRight (which works on any List), using a “zero” value and a combiner function that are specific to the list’s element type. So let’s factor out the type-specific part:
    • So genericSum works for any type at all, as long as you supply an appropriate Combiner for that type. This is the typeclass pattern: Combiner is the typeclass, and the genericSum method demands evidence that A has an associated instance.
    • (implicit c: Combiner[A])
    • (implicit c: Combiner[A])
    • implicit val IntCombiner = intCombiner // from above
    • implicit val BooleanCombiner = new Combiner[Boolean] {  | def combine(a: Boolean, b: Boolean): Boolean = a && b  | def zero = true  | }
    • We can even use an implicit class to add this functionality as syntax. Because the Combiner instance in the constructor is implicit, it’s also implicit in the body of the class.
    • (implicit c: Combiner[A])
    • implicit class
    • // c will be passed along because it's implicit here
    • For cases like this there is a shortcut syntax called a context bound.
    • [A: Combiner]
    • implicit class
    • implicit def
    • [A]
    • [A]
    • implicit class
    • (implicit c: Combiner[A])
    • [A, B
    • (implicit ca: Combiner[A], cb: Combiner[B])
    • implicit def
    • TL;DR … Methods in Scala are not values, but functions are. You can construct a function that delegates to a method via η-expansion (triggered by the trailing underscore thingy).
    • Methods are not values.
    • However, by adding the η-expansion postfix operator (η is pronounced “eta”), we can turn the method into a function value. Note the type of f.
    • The effect of _ is to perform the equivalent of the following
    • In contexts where the compiler expects a function type, the desired expansion is inferred and the underscore is not needed:
    • List(1,2,3).map(add1 _)
    • List(1,2,3).map(add1)
    • val z = add1
    • val z: Int => Int = add1 z: Int => Int = <function1>
    • val z = add1 : Int => Int z: Int => Int = <function1>
    • Methods with no parameter list follow the same pattern, but in this case the compiler can’t tell us about the missing _ because the invocation is legal on its own.
    • def x = println("hi")
    • val z = x // ok hi z: Unit = ()
    • val z = x _ z: () => Unit = <function0>
    • z() hi
    • Note that unlike the method (which has no parameter list) the function value has an empty parameter list.
    • Methods with multiple parameters expand to equivalent multi-parameter functions:
    • (a: Int, b: Int)
    • plus _ res8: (Int, Int) => Int = <function2>
    • Methods with multiple parameter lists become curried functions:
    • (a: Int)(b: Int)
    • plus _ res11: Int => (Int => Int) = <function1>
    • 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):
    • Implicit parameters are passed at the point of expansion and do not appear in the type of the constructed function value:
    • (implicit evidence$1: Numeric[N])N
    • foo[String] _ <console>:9: error: could not find implicit value for evidence parameter of type Numeric[String]  foo[String] _
    • foo[Int] _ res3: Int => Int = <function1>
    • (implicit ev: Numeric[N])
    • (implicit ev: Numeric[N])N
    • bar[Int] _ res4: Int => Int = <function1>
    • The “by-nameness” of by-name parameters is preserved on expansion:
    • (a: => Unit)
    • (a: => Unit)Int
    • (=> Unit) => Int = <function1>
    • that η-expansion can capture a by-name argument and delay its evaluation:
    • () => Unit
    • Sequence (“vararg”) parameters become Seq parameters on expansion:
    • (as: Int*)
    • def x = foo _ x: Seq[Int] => Int
    • x(1,2,3) <console>:10: error: too many arguments for method apply: (v1: Seq[Int])Int in trait Function1  x(1,2,3)
    • x(Seq(1,2,3)) res2: Int = 6
    • Default arguments are ignored for the purposes of η-expansion; it is not possible to use named arguments to simulate partial application.
    • foo(42) _ <console>:9: error: not enough arguments for method foo: (n: Int, s: String)String. Unspecified value parameter s.  foo(42) _
    • what’s the difference between a parameter of type A and one of type => A?
    • A parameter of type A acts like a val (its body is evaluated once, when bound)
    • one of type => A acts like a def (its body is evaluated whenever it is used).
    • that the arguments to when are always evaluated, even if they are never used.
    • 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).
    • whenTrue: => A, whenFalse: => A
    • Scala defines && and || simply as methods with by-name parameters.
    • first as a val:
    • What if it’s a def?
    • what about lazy val?
    • what happens with a by-name parameter?
    • The by-name parameter behaves like the def above, not like lazy val. 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.
    • Second baz works because it's not a function literal, but a call-by-name parameter

Posted from Diigo. The rest of my favorite links are here.

댓글

이 블로그의 인기 게시물

Publish to my blog (weekly)

Publish to my blog (weekly)