Program Tip

Scala에서 구문 설탕의 모든 인스턴스는 무엇입니까?

programtip 2020. 11. 27. 21:12
반응형

Scala에서 구문 설탕의 모든 인스턴스는 무엇입니까?


Scala에서 구문 설탕의 모든 인스턴스는 무엇입니까?

대부분 / 모두가 순전히 기호이므로 개념의 이름을 모르면 검색하기 어렵 기 때문에 검색하기가 어렵습니다.

할 것:

  • 암시 적 변환
  • _ 익명 함수 구문
  • 내가 잊고있는 다른 것들

기초:

  • a b 다음과 같다 a.b
  • a b c끝나는 a.b(c)경우를 제외 하고는와 동일합니다 . 이 경우 다음과 같습니다.b:a b cc.b(a)
  • a(b)동등 a.apply(b)이것은 익명 함수에 대한 다음의 정의는 동일 이유 : 브로 square1 = (X : INT) => X X 발 square2 = 새로운 기능 1 [INT, 지능 {DEF 적용 (X : INT) = X X}

    호출 할 때 square1(y), 당신은 실제로 호출 square1.apply(y)하는 square1으로로 지정해야합니다 Function1(또는 특성 Function2... 등)

  • a(b) = ca.update(b,c)Likewise 와 동일하며 , a(b,c) = d등가 a.update(b,c,d)입니다.

  • a.b = c와 동일합니다 a.b_=(c). 당신이 만들 때 val/를 var x클래스 / 객체에, 스칼라는 방법을 생성 x하고 x_=당신을 위해입니다. 당신이 자신을 정의 할 수 있습니다,하지만 당신은 정의하면 y_=당신이 있어야 정의 y, 또는 예를 들어, 컴파일되지 않습니다

    scala> val b = new Object{ def set_=(a: Int) = println(a) }
    b: java.lang.Object{def set_=(Int): Unit} = $anon$1@17e4cec
    
    scala> b.set = 5
    <console>:6: error: value set is not a member of java.lang.Object{def set_=(Int): Unit}
           b.set = 5
             ^
    
    scala> val c = new Object{ def set = 0 ; def set_=(a:Int) = println(a) }
    c: java.lang.Object{def set: Int; def set_=(Int): Unit} = $anon$1@95a253
    
    scala> c.set = 5
    5
    
  • -a에 대응 a.unary_-마찬가지로 대 +a, ~a!a

  • a <operator>= b, 여기서는 <operator>일부 특수 문자 집합은 메서드 가없는 경우 a = a <operator> b 에만 동일합니다. 예를 들어,a<operator>=

    class test(val x:Int) {
        def %%(y: Int) = new test(x*y)
    }
    
    var a = new test(10)
    a.x // 10
    a %%= 5 //Equivalent to a = a %% 5
    a.x // 50
    

Jaxkson의 답변 외에도 :

  • type F[A,B]로 사용할 수 있습니다 A F B.

예를 들면 :

type ->[A,B] = (A,B)
def foo(f: String -> String)
  • 사용 => type방법 정의에하는 함수 썽크에서 메서드 호출 내부 컴파일러 랩 표현한다.

예를 들면

def until(cond: => Boolean)(body: => Unit) = while(!cond) body

var a = 0
until (a > 5) {a += 1}

특수 클래스 : 튜플 및 기호

Rahul G가 언급했듯이 튜플과 기호는 약간 특별한 구문을 얻습니다.

  • 기호 : 구문 'xSymbol("x")
  • 튜플 : (p1,p2,..,pn)케이스 클래스의 줄임말Tuplen[T1,T2,..,Tn](p1,p2,..,pn)

예를 들어, 다음 두 가지는 동일합니다.

val tuple1 = ("Hello",1)
val tuple2 = Tuple2[String,Int]("Hello",1)

추출기 :

이 추출기에 사용되는 두 가지 방법이 있습니다, unapply그리고 unapplySeq. 이들은 여러 변수 할당 및 패턴 일치에 사용됩니다.

  • 첫 번째 사용 사례는 unapply가 일치해야하는 개체를 가져와 일치 Boolean하는지 여부에 따라를 반환하는 경우입니다. 예를 들어,

    trait Gender
    trait Male extends Gender
    trait Female extends Gender
    object Male extends Male
    object Female extends Female
    class Person(val g: Gender, val age: Int)
    
    object Adult {
        def unapply(p: Person) = p.age >= 18
    }
    
    def check(p: Person) = p match {
        case Adult() => println("An Adult")
        case _ => println("A Child")
    }
    
    //Will print: An Adult since Adult.unapply returns true.
    check(new Person(Female, 18))
    
    //Will print: A Child as it falls through to the _ case.
    check(new Person(Male, 17))
    

Honestly, I don't really get the purpose of the above syntax since it can be done almost just as easily by just putting the code in the case statements. Of course if you have a better example, leave a comment below

  • The general case where unapply takes some fixed-number of parameters and returns either an Option[T] for a single parameter or a Option[(p1,p2,...)] for multiple, i.e. a Tuple with the matched values, for example, continuing from the above code:

    object Person {
        def apply(g: Gender, age: Int) = new Person(g, age)
        def unapply(p: Person) = if(p.age < 0) None else Some((p.g, p.age))
    }
    
    //Using Person.apply as described in the Basics section
    val alice = Person(Female, 30)
    val bob = Person(Male, 25)
    
    //This calls Person.unapply(alice), which returns Some((Female, 30)).
    //alice_gender is assigned Female and alice_age 30.
    val Person(alice_gender, alice_age) = alice
    
    bob match {
        //Calls Person.unapply(bob), but sees that g is Male, so no match.
        case Person(Female, _) => println("Hello ma'am")
        //Calls Person.unapply(bob) and assigns age = bob.age, but it doesn't pass
        //the 'if' statement, so it doesn't match here either.
        case Person(Male, age) if age < 18 => println("Hey dude")
        //So bob falls through to here
        case _ => println("Hello Sir")
    }
    
    Person(Male,-1) match {
        //Person.unapply(Person.apply(Male,-1)) returns None because p.age < 0.
        //Therefore this case will not match.
        case Person(_, _) => println("Hello person")
        //Thus it falls through to here.
        case _ => println("Are you Human?")
    }
    

Note: Case classes do all those apply/unapply definitions for you (as well as other stuff) so use them whenver possible to save time and reduce code.

  • unapplySeq. This works similarly to unapply as above, except it must return an Option of some kind of sequence.

As a quick example,

scala> List.unapplySeq(List(1,2,3))
res2: Some[List[Int]] = Some(List(1, 2, 3))

Anonymous functions:

_ + _ is short for (a, b) => a + b


Context bounds desugar into implicit parameters, e.g. consider a function that leverages the Monoid type class:

def suml[T: Monoid](xs: List[T]) = {
  val T = implicitly[Monoid[T]]
  xs.foldLeft(T.mzero)(T.mplus)
}

where the : Monoid part is a context bound, gets translated to:

def suml[T](xs: List[T])(implicit evidence$1: Monoid[T]]) = {
  ...
}

therefore the following compiles, too:

def suml[T: Monoid](xs: List[T]) = {
  val T = evidence$1
  ...
}

참고URL : https://stackoverflow.com/questions/2662984/what-are-all-the-instances-of-syntactic-sugar-in-scala

반응형