[SCALA] 스칼라의 숨겨진 기능
SCALA스칼라의 숨겨진 기능
모든 스칼라 개발자가 알아야 할 것을 스칼라의 숨겨진 기능은 무엇입니까?
답변을 당 하나 개의 숨겨진 기능하시기 바랍니다.
해결법
-
==============================
1.좋아, 내가 하나 더 추가했다. 스칼라의 모든 정규식 객체는 경기 그룹에 액세스 할 수 있습니다 추출기 (위 oxbox_lakes에서 답을 참조)이있다. 그래서 당신이 뭔가를 같이 할 수 있습니다 :
좋아, 내가 하나 더 추가했다. 스칼라의 모든 정규식 객체는 경기 그룹에 액세스 할 수 있습니다 추출기 (위 oxbox_lakes에서 답을 참조)이있다. 그래서 당신이 뭔가를 같이 할 수 있습니다 :
// Regex to split a date in the format Y/M/D. val regex = "(\\d+)/(\\d+)/(\\d+)".r val regex(year, month, day) = "2010/1/13"
당신이 패턴 매칭 및 추출기를 사용하여 사용하지 않는 경우 두 번째 줄은 혼란 보인다. 당신이 발 또는 VAR을 정의 할 때마다, 어떤 키워드 다음에 오는 것은 단순히 오히려 식별자하지만 패턴이 아니다. 이 작품 이유 :
val (a, b, c) = (1, 3.14159, "Hello, world")
오른손 식은 Tuple3 [INT, 더블, 문자열] 패턴과 일치 할 수 생성 (A, B, C).
대부분의 시간을 당신의 패턴은 단일 객체의 멤버 인 추출기를 사용합니다. 예를 들어, 같은 패턴을 작성하는 경우
Some(value)
당신은 암시 적으로 Some.unapply 추출기를 호출하고 있습니다.
그러나 당신은 또한 패턴의 클래스 인스턴스를 사용할 수 있습니다, 그리고 여기에 무슨 일이 일어나고있다. 발 정규식은 정규식의 인스턴스이며, 당신이 패턴을 사용할 때, 당신은 암시 적으로 regex.unapplySeq를 호출하고 서열 [문자열]에 일치하는 그룹을 추출, (적용 취소 unapplySeq이 응답의 범위를 벗어 대) 의 요소는 변수의 년, 월, 일하기 위해 할당됩니다.
-
==============================
2.타입 정의 구조 - 즉, 그것이 지원하는 방법에 의해 설명 된 타입. 예를 들면 :
타입 정의 구조 - 즉, 그것이 지원하는 방법에 의해 설명 된 타입. 예를 들면 :
object Closer { def using(closeable: { def close(): Unit }, f: => Unit) { try { f } finally { closeable.close } } }
그것은 근접 메소드가보다 닫혀 파라미터의 종류가 다른 정의되지 않은 것을 알
-
==============================
3.이 기능이 없다면 당신은, 예를 들어, 다른 목록을 반환 목록을 통해 기능을 매핑, 또는 다른 나무를 반환하는 나무를 통해 기능을 매핑의 생각을 표현할 수 있습니다. 하지만 당신은 높은 가지 않고 일반적으로이 아이디어를 표현할 수 없습니다.
이 기능이 없다면 당신은, 예를 들어, 다른 목록을 반환 목록을 통해 기능을 매핑, 또는 다른 나무를 반환하는 나무를 통해 기능을 매핑의 생각을 표현할 수 있습니다. 하지만 당신은 높은 가지 않고 일반적으로이 아이디어를 표현할 수 없습니다.
높은 종류로, 당신은 다른 유형의 매개 변수화있어 모든 종류의 아이디어를 캡처 할 수 있습니다. (-> *) 하나 개의 파라미터를 취하는 타입 생성자 종류의 것으로 알려졌다. 예를 들어, 목록. 다른 종류의 생성자를 반환하는 타입의 생성자는 종류 (-> * -> * *)의 수라고합니다. 예를 들어, 기능 1. 그러나 스칼라, 우리는 더 높은 종류가있다, 그래서 우리는 다른 종류의 생성자에 매개 변수화하는 타입 생성자를 가질 수 있습니다. (> * - -> *) * () 그래서 그들은 같은 종류의 것.
예를 들면 :
trait Functor[F[_]] { def fmap[A, B](f: A => B, fa: F[A]): F[B] }
이제, 당신이 펑터 [목록]이있는 경우, 당신은 목록을 통해 매핑 할 수 있습니다. 당신이 펑터 [트리]이 있다면, 당신은 나무를 통해 매핑 할 수 있습니다. 당신이 종류의 A의은 Functor [A]를해야하지만 더 중요한 것은, (* -> *), 당신은 A. 이상의 기능을 매핑 할 수 있습니다
-
==============================
4.당신이 패턴 지저분한 ELSEIF 경우 --다른 스타일의 코드를 대체 할 수 추출기. 나는이 정확히 숨겨지지 않습니다 것을 알고 있지만 난 정말 그들의 힘을 이해하지 않고 몇 달 동안 스칼라를 사용하고있다. (긴) 예를 들어 나는 대체 할 수있다 :
당신이 패턴 지저분한 ELSEIF 경우 --다른 스타일의 코드를 대체 할 수 추출기. 나는이 정확히 숨겨지지 않습니다 것을 알고 있지만 난 정말 그들의 힘을 이해하지 않고 몇 달 동안 스칼라를 사용하고있다. (긴) 예를 들어 나는 대체 할 수있다 :
val code: String = ... val ps: ProductService = ... var p: Product = null if (code.endsWith("=")) { p = ps.findCash(code.substring(0, 3)) //e.g. USD=, GBP= etc } else if (code.endsWith(".FWD")) { //e.g. GBP20090625.FWD p = ps.findForward(code.substring(0,3), code.substring(3, 9)) } else { p = ps.lookupProductByRic(code) }
내 의견으로는 훨씬 명확하다이,로
implicit val ps: ProductService = ... val p = code match { case SyntheticCodes.Cash(c) => c case SyntheticCodes.Forward(f) => f case _ => ps.lookupProductByRic(code) }
나는 백그라운드에서 마술의 조금을 할 필요가 ...
object SyntheticCodes { // Synthetic Code for a CashProduct object Cash extends (CashProduct => String) { def apply(p: CashProduct) = p.currency.name + "=" //EXTRACTOR def unapply(s: String)(implicit ps: ProductService): Option[CashProduct] = { if (s.endsWith("=") Some(ps.findCash(s.substring(0,3))) else None } } //Synthetic Code for a ForwardProduct object Forward extends (ForwardProduct => String) { def apply(p: ForwardProduct) = p.currency.name + p.date.toString + ".FWD" //EXTRACTOR def unapply(s: String)(implicit ps: ProductService): Option[ForwardProduct] = { if (s.endsWith(".FWD") Some(ps.findForward(s.substring(0,3), s.substring(3, 9)) else None } }
그러나 취재는 재치있는 장소로 비즈니스 로직의 일부를 분리한다는 사실에 대한 가치가있다. 다음과 같이 내 Product.getCode 방법을 구현할 수 있습니다 ..
class CashProduct { def getCode = SyntheticCodes.Cash(this) } class ForwardProduct { def getCode = SyntheticCodes.Forward(this) }
-
==============================
5.스칼라 유형을 구체화 것처럼하는 매니페스트는 런타임에 유형 정보를 얻기에 방법의 일종이다.
스칼라 유형을 구체화 것처럼하는 매니페스트는 런타임에 유형 정보를 얻기에 방법의 일종이다.
-
==============================
6.스칼라 2.8에서는 패키지 scala.util.control.TailCalls을 (실제로는 트램펄린입니다)를 사용하여 꼬리 재귀 적 방법을 가질 수 있습니다.
스칼라 2.8에서는 패키지 scala.util.control.TailCalls을 (실제로는 트램펄린입니다)를 사용하여 꼬리 재귀 적 방법을 가질 수 있습니다.
예 :
def u(n:Int):TailRec[Int] = { if (n==0) done(1) else tailcall(v(n/2)) } def v(n:Int):TailRec[Int] = { if (n==0) done(5) else tailcall(u(n-1)) } val l=for(n<-0 to 5) yield (n,u(n).result,v(n).result) println(l)
-
==============================
7.자동 반사없이 필드에 지정되지 않은, 인덱스 액세스를 제공, 제품의 특성을 믹스 인 케이스 클래스 :
자동 반사없이 필드에 지정되지 않은, 인덱스 액세스를 제공, 제품의 특성을 믹스 인 케이스 클래스 :
case class Person(name: String, age: Int) val p = Person("Aaron", 28) val name = p.productElement(0) // name = "Aaron": Any val age = p.productElement(1) // age = 28: Any val fields = p.productIterator.toList // fields = List[Any]("Aaron", 28)
이 기능은 toString 메소드의 출력을 변경하는 간단한 방법을 제공합니다 :
case class Person(name: String, age: Int) { override def productPrefix = "person: " } // prints "person: (Aaron,28)" instead of "Person(Aaron, 28)" println(Person("Aaron", 28))
-
==============================
8.scalac -Xprint : 그것은 정확히 확실히에서 광고 기능을 숨겨,하지만 아니에요.
scalac -Xprint : 그것은 정확히 확실히에서 광고 기능을 숨겨,하지만 아니에요.
사용의 그림으로 다음과 같은 소스를 고려 :
class A { "xx".r }
scalac -Xprint으로이 컴파일 : TYPER의 출력 :
package <empty> { class A extends java.lang.Object with ScalaObject { def this(): A = { A.super.this(); () }; scala.this.Predef.augmentString("xx").r } }
Predef.scala 존재 암시 데프 augmentString의 응용이다 공지 scala.this.Predef.augmentString ( "XX"). R.
scalac -Xprint : <상> 일부 컴파일러 단계 이후 구문 트리를 인쇄합니다. 사용할 수있는 단계가 scalac -Xshow-단계 사용을 참조하십시오.
이 무대 뒤에서 무슨 일이 일어나고 있는지 배울 수있는 좋은 방법입니다.
함께 시도
경우 클래스 X (A : INT, B : 문자열)
타이 퍼 단계를 사용하는 것은 정말 얼마나 유용 느낌.
-
==============================
9.당신은 당신의 자신의 제어 구조를 정의 할 수 있습니다. 그것은 정말 기능과 객체와 몇 가지 문법 설탕을, 그러나 그들은보고 진짜처럼 행동.
당신은 당신의 자신의 제어 구조를 정의 할 수 있습니다. 그것은 정말 기능과 객체와 몇 가지 문법 설탕을, 그러나 그들은보고 진짜처럼 행동.
예를 들어, 다음 코드 (COND)까지 해달라고 {...}하지 않는 한 (COND) 및 해달라고 {...}을 정의한다 :
def dont(code: => Unit) = new DontCommand(code) class DontCommand(code: => Unit) { def unless(condition: => Boolean) = if (condition) code def until(condition: => Boolean) = { while (!condition) {} code } }
이제 다음을 수행 할 수 있습니다 :
/* This will only get executed if the condition is true */ dont { println("Yep, 2 really is greater than 1.") } unless (2 > 1) /* Just a helper function */ var number = 0; def nextNumber() = { number += 1 println(number) number } /* This will not be printed until the condition is met. */ dont { println("Done counting to 5!") } until (nextNumber() == 5)
-
==============================
10.스칼라 2.8에 주석을 @switch :
스칼라 2.8에 주석을 @switch :
예:
scala> val n = 3 n: Int = 3 scala> import annotation.switch import annotation.switch scala> val s = (n: @switch) match { | case 3 => "Three" | case _ => "NoThree" | } <console>:6: error: could not emit switch for @switch annotated match val s = (n: @switch) match {
-
==============================
11.몰라이 정말 숨겨진, 그러나 나는 꽤 좋은 찾을 경우.
몰라이 정말 숨겨진, 그러나 나는 꽤 좋은 찾을 경우.
이 개 유형의 매개 변수를 Typeconstructors는 중위 표기법으로 쓸 수있다
object Main { class FooBar[A, B] def main(args: Array[String]): Unit = { var x: FooBar[Int, BigInt] = null var y: Int FooBar BigInt = null } }
-
==============================
12.스칼라 2.8 기본을 소개하고 스칼라 클래스를 구분하기 위해 추가하는 새로운 "복사"방법의 추가 가능하게 인수를 지명했다. 당신이 정의하는 경우 :
스칼라 2.8 기본을 소개하고 스칼라 클래스를 구분하기 위해 추가하는 새로운 "복사"방법의 추가 가능하게 인수를 지명했다. 당신이 정의하는 경우 :
case class Foo(a: Int, b: Int, c: Int, ... z:Int)
당신은 당신이 말하는 단지 수 있습니다 만 다른 "N"값으로, 기존의 푸처럼 새로운 푸를 만들려면 :
foo.copy(n = 3)
-
==============================
13.스칼라 2.8에 당신은 당신의 일반적인 클래스 / 메소드에 @specialized 추가 할 수 있습니다. 이것은 (AnyVal 확장) 기본 형식의 클래스의 특별한 버전을 만들 및 취소 필요한 복싱 / 언 박싱의 비용을 절약 할 수 : 클래스 푸 [T를 @specialized] ...
스칼라 2.8에 당신은 당신의 일반적인 클래스 / 메소드에 @specialized 추가 할 수 있습니다. 이것은 (AnyVal 확장) 기본 형식의 클래스의 특별한 버전을 만들 및 취소 필요한 복싱 / 언 박싱의 비용을 절약 할 수 : 클래스 푸 [T를 @specialized] ...
당신은 AnyVals의 하위 집합을 선택할 수 있습니다 : 클래스 푸 [@specialized (INT, 불리언) T] ...
-
==============================
14.언어를 확장. 난 항상 자바에서이 같은 것을 (하지 수)하고 싶었다. 하지만 스칼라에서 내가 할 수 있습니다 :
언어를 확장. 난 항상 자바에서이 같은 것을 (하지 수)하고 싶었다. 하지만 스칼라에서 내가 할 수 있습니다 :
def timed[T](thunk: => T) = { val t1 = System.nanoTime val ret = thunk val time = System.nanoTime - t1 println("Executed in: " + time/1000000.0 + " millisec") ret }
다음 쓰기 :
val numbers = List(12, 42, 3, 11, 6, 3, 77, 44) val sorted = timed { // "timed" is a new "keyword"! numbers.sortWith(_<_) } println(sorted)
그리고 얻다
Executed in: 6.410311 millisec List(3, 3, 6, 11, 12, 42, 44, 77)
-
==============================
15.통화 별 이름 매개 변수 (! 편집 :이 다음 게으른 매개 변수 다릅니다) 지정할 수있는 기능을하고 함수에 의해 사용되는 때까지 평가되지 않습니다 (편집 : 사실, 그것은 그 때마다 재평가한다 익숙한). 자세한 내용은이 FAQ를 참조
통화 별 이름 매개 변수 (! 편집 :이 다음 게으른 매개 변수 다릅니다) 지정할 수있는 기능을하고 함수에 의해 사용되는 때까지 평가되지 않습니다 (편집 : 사실, 그것은 그 때마다 재평가한다 익숙한). 자세한 내용은이 FAQ를 참조
class Bar(i:Int) { println("constructing bar " + i) override def toString():String = { "bar with value: " + i } } // NOTE the => in the method declaration. It indicates a lazy paramter def foo(x: => Bar) = { println("foo called") println("bar: " + x) } foo(new Bar(22)) /* prints the following: foo called constructing bar 22 bar with value: 22 */
-
==============================
16.당신은 세미콜론으로 추론 문제를 유발하지 않고 로컬 블록을 소개하는 로컬로 사용할 수 있습니다.
당신은 세미콜론으로 추론 문제를 유발하지 않고 로컬 블록을 소개하는 로컬로 사용할 수 있습니다.
용법:
scala> case class Dog(name: String) { | def bark() { | println("Bow Vow") | } | } defined class Dog scala> val d = Dog("Barnie") d: Dog = Dog(Barnie) scala> locally { | import d._ | bark() | bark() | } Bow Vow Bow Vow
로컬로 "Predef.scala"에 정의되어 있습니다 :
@inline def locally[T](x: T): T = x
인라인이기 때문에, 그것은 추가적인 오버 헤드를 부과하지 않습니다.
-
==============================
17.초기 초기화 :
초기 초기화 :
trait AbstractT2 { println("In AbstractT2:") val value: Int val inverse = 1.0/value println("AbstractT2: value = "+value+", inverse = "+inverse) } val c2c = new { // Only initializations are allowed in pre-init. blocks. // println("In c2c:") val value = 10 } with AbstractT2 println("c2c.value = "+c2c.value+", inverse = "+c2c.inverse)
산출:
In AbstractT2: AbstractT2: value = 10, inverse = 0.1 c2c.value = 10, inverse = 0.1
-
==============================
18.당신은 '과'키워드 구조 유형을 구성 할 수
당신은 '과'키워드 구조 유형을 구성 할 수
object Main { type A = {def foo: Unit} type B = {def bar: Unit} type C = A with B class myA { def foo: Unit = println("myA.foo") } class myB { def bar: Unit = println("myB.bar") } class myC extends myB { def foo: Unit = println("myC.foo") } def main(args: Array[String]): Unit = { val a: A = new myA a.foo val b: C = new myC b.bar b.foo } }
-
==============================
19.익명 함수에 대한 자리 표시 자 구문
익명 함수에 대한 자리 표시 자 구문
스칼라 언어 사양에서 :
SimpleExpr1 ::= '_'
스칼라 언어 변경에서 :
_ + 1 x => x + 1 _ * _ (x1, x2) => x1 * x2 (_: Int) * 2 (x: Int) => x * 2 if (_) x else y z => if (z) x else y _.map(f) x => x.map(f) _.map(_ + 1) x => x.map(y => y + 1)
이 사용 당신이 뭔가를 같이 할 수있는 :
def filesEnding(query: String) = filesMatching(_.endsWith(query))
-
==============================
20.암시 적 정의, 특히 변환.
암시 적 정의, 특히 변환.
예를 들어, 그것을 중간 대체함으로써, 크기에 맞게 입력 문자열을 포맷하는 함수를 추정 "..."
def sizeBoundedString(s: String, n: Int): String = { if (n < 5 && n < s.length) throw new IllegalArgumentException if (s.length > n) { val trailLength = ((n - 3) / 2) min 3 val headLength = n - 3 - trailLength s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length) } else s }
당신은 무엇을 변환하는 toString 메소드를 사용 물론, 임의의 문자열로 그것을 사용하고 있습니다. 하지만이처럼 쓸 수있다 :
def sizeBoundedString[T](s: T, n: Int)(implicit toStr: T => String): String = { if (n < 5 && n < s.length) throw new IllegalArgumentException if (s.length > n) { val trailLength = ((n - 3) / 2) min 3 val headLength = n - 3 - trailLength s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length) } else s }
그리고, 당신은이 작업을 수행하여 다른 종류의 클래스를 전달할 수 :
implicit def double2String(d: Double) = d.toString
지금 당신은 이중 전달이 함수를 호출 할 수 있습니다 :
sizeBoundedString(12345.12345D, 8)
마지막 인수는 암시 적이며, 때문에 암시 드 선언의 자동으로 전달되고있다. 그것으로부터 문자열로 암시 적 변환이 있기 때문에 또한, "S"안에 sizeBoundedString 문자열로 취급되고있다.
이러한 유형의 Implicits 더 나은 예기치 않은 변환을 방지하기 위해 드문 유형에 대한 정의된다. 또한 명시 적 변환을 통과 할 수 있으며, 그것은 여전히 암시 sizeBoundedString 내부에 사용됩니다 :
sizeBoundedString(1234567890L, 8)((l : Long) => l.toString)
또한 여러 암시 인수를 가질 수 있지만, 당신은 그들 중 하나를 통과 그들 모두에 합격하거나, 안 중 하나. 암시 적 변환에 대한 바로 가기 구문이있다 :
def sizeBoundedString[T <% String](s: T, n: Int): String = { if (n < 5 && n < s.length) throw new IllegalArgumentException if (s.length > n) { val trailLength = ((n - 3) / 2) min 3 val headLength = n - 3 - trailLength s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length) } else s }
이 정확히 같은 방식으로 사용된다.
Implicits 어떤 값을 가질 수 있습니다. 그들은 도서관 정보를 숨기기 위해, 예를 들어, 사용할 수 있습니다. 예를 들어, 다음의 예를 보자
case class Daemon(name: String) { def log(msg: String) = println(name+": "+msg) } object DefaultDaemon extends Daemon("Default") trait Logger { private var logd: Option[Daemon] = None implicit def daemon: Daemon = logd getOrElse DefaultDaemon def logTo(daemon: Daemon) = if (logd == None) logd = Some(daemon) else throw new IllegalArgumentException def log(msg: String)(implicit daemon: Daemon) = daemon.log(msg) } class X extends Logger { logTo(Daemon("X Daemon")) def f = { log("f called") println("Stuff") } def g = { log("g called")(DefaultDaemon) } } class Y extends Logger { def f = { log("f called") println("Stuff") } }
이 예에서는 Y 개체에서 "F"를 호출하면 기본 데몬에 로그를 전송하고, 데몬 X 데몬 X의 인스턴스에 대한 것입니다. 그러나 X의 인스턴스에 g를 호출하면 명시 적으로 부여 DefaultDaemon에 로그를 보낼 것입니다.
이 간단한 예제는 과부하 및 개인 상태와 다시 기록 할 수 있지만, implicits 개인 상태를 필요로하지 않으며, 수입과 문맥하게 할 수있다.
-
==============================
21.어쩌면 너무 숨겨진,하지만 난이 유용하다 생각하지 :
어쩌면 너무 숨겨진,하지만 난이 유용하다 생각하지 :
@scala.reflect.BeanProperty var firstName:String = _
이것은 자동으로 빈 규칙을 일치하는 필드에 대한 getter와 setter를 생성합니다.
또한, 설명에 대한 developerWorks
-
==============================
22.폐쇄의 암시 적 인수.
폐쇄의 암시 적 인수.
함수 인수 단지 방법과 암시 적으로 표시 될 수있다. 암시 적 매개 변수가 암시 해상도 볼 수와 자격이 함수 본문의 범위 내에서 :
trait Foo { def bar } trait Base { def callBar(implicit foo: Foo) = foo.bar } object Test extends Base { val f: Foo => Unit = { implicit foo => callBar } def test = f(new Foo { def bar = println("Hello") }) }
-
==============================
23.스칼라의 스트림 무한 데이터 구조를 구축 : http://www.codecommit.com/blog/scala/infinite-lists-for-the-finitely-patient
스칼라의 스트림 무한 데이터 구조를 구축 : http://www.codecommit.com/blog/scala/infinite-lists-for-the-finitely-patient
-
==============================
24.결과 유형은 암시 적 해상도에 따라 달라집니다. 이렇게하면 여러 파견의 형태를 제공 할 수 있습니다 :
결과 유형은 암시 적 해상도에 따라 달라집니다. 이렇게하면 여러 파견의 형태를 제공 할 수 있습니다 :
scala> trait PerformFunc[A,B] { def perform(a : A) : B } defined trait PerformFunc scala> implicit val stringToInt = new PerformFunc[String,Int] { def perform(a : String) = 5 } stringToInt: java.lang.Object with PerformFunc[String,Int] = $anon$1@13ccf137 scala> implicit val intToDouble = new PerformFunc[Int,Double] { def perform(a : Int) = 1.0 } intToDouble: java.lang.Object with PerformFunc[Int,Double] = $anon$1@74e551a4 scala> def foo[A, B](x : A)(implicit z : PerformFunc[A,B]) : B = z.perform(x) foo: [A,B](x: A)(implicit z: PerformFunc[A,B])B scala> foo("HAI") res16: Int = 5 scala> foo(1) res17: Double = 1.0
-
==============================
25.스칼라는 해당 클래스의 인스턴스를 초기화하는 문을 포함하는 클래스 (생성자)의 몸 익명의 하위 클래스를 만들 수 있습니다.
스칼라는 해당 클래스의 인스턴스를 초기화하는 문을 포함하는 클래스 (생성자)의 몸 익명의 하위 클래스를 만들 수 있습니다.
더 간결하게 그 특성을 UI 구성 요소를 생성하고 선언 할 수로 (예 스윙 angel이라는 경우) 컴포넌트 기반의 사용자 인터페이스를 구성 할 때이 패턴은 매우 유용하다.
자세한 내용은 http://spot.colorado.edu/~reids/papers/how-scala-experience-improved-our-java-development-reid-2011.pdf를 참조하십시오.
여기 angel이라는 버튼을 작성하는 예이다 :
val button = new Button("Click me"){ setWidth("20px") setDescription("Click on this") setIcon(new ThemeResource("icons/ok.png")) }
-
==============================
26.당신이에 println과 printerr 방법을 포함하는 로거를 사용한다고 가정하지만, 당신은 단지 오류 메시지에 대한 하나를 사용하여 표준 출력에 대한 좋은 오래된 Predef.println을 유지하려는. 이 작업을 수행 할 수 있습니다 :
당신이에 println과 printerr 방법을 포함하는 로거를 사용한다고 가정하지만, 당신은 단지 오류 메시지에 대한 하나를 사용하여 표준 출력에 대한 좋은 오래된 Predef.println을 유지하려는. 이 작업을 수행 할 수 있습니다 :
val logger = new Logger(...) import logger.printerr
로거는 또한 수입 및 사용하고자하는 다른 열두 방법을 포함하는 경우, 그것은을 나열하는 불편된다. 대신 시도해 볼 수도 있습니다 :
import logger.{println => donotuseprintlnt, _}
그러나 이것은 여전히 수입 멤버의 목록을 "오염". 동네 짱 강력한 와일드 카드를 입력 :
import logger.{println => _, _}
그리고 그냥 옳은 일을 ™을 할 것입니다.
-
==============================
27.당신은 런타임 동안 점검 할 것 부가 기능 제약을 정의 할 수 있습니다 (PREDEF에 정의) 방법을 필요로한다. 당신은 또 다른 트위터 클라이언트를 개발하고 당신이 140 개 문자로 트윗 길이를 제한 할 필요가 있다고 상상해보십시오. 또한 당신은 빈 트윗을 게시 할 수 없습니다.
당신은 런타임 동안 점검 할 것 부가 기능 제약을 정의 할 수 있습니다 (PREDEF에 정의) 방법을 필요로한다. 당신은 또 다른 트위터 클라이언트를 개발하고 당신이 140 개 문자로 트윗 길이를 제한 할 필요가 있다고 상상해보십시오. 또한 당신은 빈 트윗을 게시 할 수 없습니다.
def post(tweet: String) = { require(tweet.length < 140 && tweet.length > 0) println(tweet) }
이제 예외가 발생합니다 부적절 길이 인수 게시물을 호출 :
scala> post("that's ok") that's ok scala> post("") java.lang.IllegalArgumentException: requirement failed at scala.Predef$.require(Predef.scala:145) at .post(<console>:8) scala> post("way to looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong tweet") java.lang.IllegalArgumentException: requirement failed at scala.Predef$.require(Predef.scala:145) at .post(<console>:8)
각에 설명을 추가 할 경우에도 여러 요구 사항을 작성하거나 할 수 있습니다 :
def post(tweet: String) = { require(tweet.length > 0, "too short message") require(tweet.length < 140, "too long message") println(tweet) }
이제 예외 자세한 있습니다 :
scala> post("") java.lang.IllegalArgumentException: requirement failed: too short message at scala.Predef$.require(Predef.scala:157) at .post(<console>:8)
또 하나의 예는 여기에있다.
당신은 때마다 요구 사항이 실패하는 작업을 수행 할 수 있습니다 :
scala> var errorcount = 0 errorcount: Int = 0 def post(tweet: String) = { require(tweet.length > 0, {errorcount+=1}) println(tweet) } scala> errorcount res14: Int = 0 scala> post("") java.lang.IllegalArgumentException: requirement failed: () at scala.Predef$.require(Predef.scala:157) at .post(<console>:9) ... scala> errorcount res16: Int = 1
-
==============================
28.추상적 인 재정의 방법과 특성은 널리 많은 사람들로 광고하지 않는 스칼라의 기능입니다. 추상 재정의 수정과 방법의하고자하는 것은 일부 작업을하고 슈퍼에 대한 호출을 위임하는 것입니다. 그리고 이러한 특성은 추상적 인 재정 방법의 구체적인 구현과 혼합에 있어야합니다.
추상적 인 재정의 방법과 특성은 널리 많은 사람들로 광고하지 않는 스칼라의 기능입니다. 추상 재정의 수정과 방법의하고자하는 것은 일부 작업을하고 슈퍼에 대한 호출을 위임하는 것입니다. 그리고 이러한 특성은 추상적 인 재정 방법의 구체적인 구현과 혼합에 있어야합니다.
trait A { def a(s : String) : String } trait TimingA extends A { abstract override def a(s : String) = { val start = System.currentTimeMillis val result = super.a(s) val dur = System.currentTimeMillis-start println("Executed a in %s ms".format(dur)) result } } trait ParameterPrintingA extends A { abstract override def a(s : String) = { println("Called a with s=%s".format(s)) super.a(s) } } trait ImplementingA extends A { def a(s: String) = s.reverse } scala> val a = new ImplementingA with TimingA with ParameterPrintingA scala> a.a("a lotta as") Called a with s=a lotta as Executed a in 0 ms res4: String = sa attol a
내 예는 정말로 훨씬 더 가난한 망 AOP보다 동안, 나는 미리 정의 된 수입, 사용자 정의 바인딩 및 classpathes와 스칼라 인터프리터 인스턴스를 구축하는 것이 훨씬 내 취향에 이러한 스택 특성을 사용했다. 스택 형 형질은 가능한 유용한 수입이 있고 범위는 사용자 스크립트 varibles 다음 LuceneLibs와 JsonLibs 새로운 InterpreterFactory의 라인을 따라 내 공장을 생성하고했다.
from https://stackoverflow.com/questions/1025181/hidden-features-of-scala by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 중첩 된 구조를 업데이트 할 클리너 방법 (0) | 2019.10.29 |
---|---|
[SCALA] (왜) 우리는 캐시를 호출하거나 RDD에 유지해야합니까 (0) | 2019.10.29 |
[SCALA] 업데이트 된 행에 dataframe 행을지도하는 동안 인코더 오류 (0) | 2019.10.29 |
[SCALA] 스칼라 2.8 컬렉션 라이브러리는 "역사에서 가장 긴 유서"의 경우인가? [닫은] (0) | 2019.10.29 |
[SCALA] 어떻게 스파크에서 CSV 파일에서 헤더를 건너 뛸 수 있습니까? (0) | 2019.10.29 |