[SCALA] 스칼라 등 구현 ifTrue, ifFalse, ifSome, ifNone은 피하는 경우 (...) 단순 패턴 매칭
SCALA스칼라 등 구현 ifTrue, ifFalse, ifSome, ifNone은 피하는 경우 (...) 단순 패턴 매칭
스칼라, 나는 점진적으로 제어 흐름 지향적 인 방법으로 사고의 내 자바 / C 습관을 잃었으며, 가서 내가 먼저 관심 객체를 얻기 위해 사용되었다, 그리고 일반적으로 일치 또는지도 같은 것을 적용 () 또는 foreach는 () 모음. 지금 구조 내 코드의 좀 더 자연스럽고 더 투 포인트 방식 같은 느낌 때문에 나는 그것을 많이 좋아한다.
조금씩, 나는 내가 조건 같은 방법으로 프로그램 할 수달라고했습니다; 즉, 제 부울 값을 획득하고이를 다양한 일들을 일치. 본격적인 경기는, 그러나,이 작업에 대한 약간의 과잉을 보이지 않습니다.
비교:
obj.isSomethingValid match {
case true => doX
case false => doY
}
내가 가까이 자바 스타일로 쓸 것입니다 무슨 대 :
if (obj.isSomethingValid)
doX
else
doY
메시지 (및 그 변형) 및 ifFalse : 그럼 난 스몰 토크의 ifTrue를 기억해 냈습니다. 스칼라에서이 같은 뭔가를 쓸 수 있을까?
obj.isSomethingValid ifTrue doX else doY
변종 :
val v = obj.isSomethingValid ifTrue someVal else someOtherVal
// with side effects
obj.isSomethingValid ifFalse {
numInvalid += 1
println("not valid")
}
또한,이 스타일은 옵션 같은 간단한 두 가지 상태 유형에 사용할 수 있을까? 내가 사용 옵션에 더 관용적 방법, 수집 및 전화 필터 (),지도 ()로 처리하는 것입니다 그것을) (존재 알고 있지만, 종종 말에, 나는 몇 가지 DOX이 경우를 수행 할 것을 발견 그렇지 않은 경우 정의, 일부 도이된다. 뭔가 같은 :
val ok = resultOpt ifSome { result =>
println("Obtained: " + result)
updateUIWith(result) // returns Boolean
} else {
numInvalid += 1
println("missing end result")
false
}
나를 위해,이 (아직?) 본격적인 경기보다 더 보인다.
내가 생각 해낸 기본 구현을 제공하고; 이 스타일 / 기술 및 / 또는 더 나은 구현에 대한 일반적인 의견을 환영합니다!
해결법
-
==============================
1.첫째 :이 키워드이며, 역 따옴표를 사용하여 식별자 오히려 못생긴 나는 대신 다른 사용합니다 그래서, 볼 수 강제로 우리는 아마,하지 재사용 다른 수 있습니다.
첫째 :이 키워드이며, 역 따옴표를 사용하여 식별자 오히려 못생긴 나는 대신 다른 사용합니다 그래서, 볼 수 강제로 우리는 아마,하지 재사용 다른 수 있습니다.
여기에 구현하려는 시도이다. 먼저, 부울에 ifTrue 및 ifFalse을 추가 포주 - 내 - 라이브러리 패턴을 사용합니다. 그들은 지정된 조건이 실현되는 경우 평가해야 하나의 별 이름 매개 변수를 반환 타입 R에 매개 변수화하고 동의합니다. 그러나 그렇게함으로써, 우리는 다른 통화에 대해 허용해야합니다. 우리는 옵션 저장한다 [R]와 같은 수의 중간 결과를 Otherwise0 (0 설명한 이유 이상)이라는 새로운 객체를 반환 할 수 있도록. 그것은 현재의 조건 (ifTrue 또는 ifFalse)이 실현되는 경우 정의하고, 그렇지 않으면 빈입니다.
class BooleanWrapper(b: Boolean) { def ifTrue[R](f: => R) = new Otherwise0[R](if (b) Some(f) else None) def ifFalse[R](f: => R) = new Otherwise0[R](if (b) None else Some(f)) } implicit def extendBoolean(b: Boolean): BooleanWrapper = new BooleanWrapper(b)
지금,이 작품은 나에게 쓰기를 할 수 있습니다
someTest ifTrue { println("OK") }
그러나, 그렇지 않다면 다음 절없이, 그것은 물론, 형 R의 값을 반환 할 수 없습니다. 그래서 여기 Otherwise0의 정의는 다음과 같습니다
class Otherwise0[R](intermediateResult: Option[R]) { def otherwise[S >: R](f: => S) = intermediateResult.getOrElse(f) def apply[S >: R](f: => S) = otherwise(f) }
단지는 이전 ifTrue 또는 ifFalse에서 가져온 중간 결과가 정의되지 않은 경우 경우는 원 정확히 인의 통과라는 이름의 인수를 평가합니다. 타입 파라미터 화 [S> R은] S는, 예를 들면, 위 코드에서, R은 과일 추론 타입을 가지도록 지정된 변수의 실제 유형의 최의 일반적인 수퍼 될 것으로 추정되는 효과가있다 :
class Fruit class Apple extends Fruit class Orange extends Fruit val r = someTest ifTrue { new Apple } otherwise { new Orange }
는 별명도 당신이 코드의 짧은 청크 전부 다른 메소드 이름을 건너 뛸 수 있습니다) (적용 :
someTest.ifTrue(10).otherwise(3) // equivalently: someTest.ifTrue(10)(3)
마지막으로, 여기에 옵션에 해당하는 포주는 다음과 같습니다
class OptionExt[A](option: Option[A]) { def ifNone[R](f: => R) = new Otherwise1(option match { case None => Some(f) case Some(_) => None }, option.get) def ifSome[R](f: A => R) = new Otherwise0(option match { case Some(value) => Some(f(value)) case None => None }) } implicit def extendOption[A](opt: Option[A]): OptionExt[A] = new OptionExt[A](opt) class Otherwise1[R, A1](intermediateResult: Option[R], arg1: => A1) { def otherwise[S >: R](f: A1 => S) = intermediateResult.getOrElse(f(arg1)) def apply[S >: R](f: A1 => S) = otherwise(f) }
주 우리는 이제 우리가 편리하게 ifSome 함수 인수뿐만 아니라, 그렇지 않으면 ifNone 다음의 함수 인수에뿐만 아니라 미개봉 값을 통과 할 수 있도록하는 것이 Otherwise1이 필요하다는 것을.
-
==============================
2.너무 구체적으로 문제를보고 할 수있다. 당신은 아마 파이프 연산자 더 나을 것입니다 :
너무 구체적으로 문제를보고 할 수있다. 당신은 아마 파이프 연산자 더 나을 것입니다 :
class Piping[A](a: A) { def |>[B](f: A => B) = f(a) } implicit def pipe_everything[A](a: A) = new Piping(a)
지금 당신은 할 수
("fish".length > 5) |> (if (_) println("Hi") else println("Ho"))
틀림없이, 당신이 달성하려고하는 것과 아주 우아하지 않다, 그러나 놀랍게도 다양한 있다는 큰 장점을 가지고있는 - 당신이 첫 번째 (단지 논리 값 포함) 인수를 넣어 원하는 시간, 당신은 그것을 사용할 수 있습니다 .
또한, 당신은 이미 옵션 당신이 원하는 방법을 사용할 수 있습니다 :
Option("fish").filter(_.length > 5). map (_ => println("Hi")). getOrElse(println("Ho"))
이 것이 의미하는 것은 아니다 반환 값을 취할 수해서 당신이 그들을 피할 수 있습니다. 이 구문에 익숙해 조금 가지고 간다; 이것은 자신의 implicits을 만들 수있는 유효한 이유가 될 수 있습니다. 그러나 핵심 기능이있다. (당신이 당신의 자신을 만드는 경우에, 고려 배 [B] (F : A => B) (g :. => B) 대신에, 당신이 그것에 익숙해 일단 개입 키워드의 부족이 실제로 오히려 좋은)
편집 :이 있지만 | 파이프 표기법 다소 표준> I 실제로 메소드 이름으로 사용하기를 선호하기 때문에 다음 DEF 재사용 [B, C] (F : A => B) (g (A, B) => C ) = g (a, F (a))은보다 자연스럽게 보인다.
-
==============================
3.이유는 단지 다음과 같이 사용하지 마십시오 :
이유는 단지 다음과 같이 사용하지 마십시오 :
val idiomaticVariable = if (condition) { firstExpression } else { secondExpression }
?
IMO, 매우 관용적! :)
from https://stackoverflow.com/questions/5654004/implementing-iftrue-iffalse-ifsome-ifnone-etc-in-scala-to-avoid-if-and by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 누군가가 나에게 스칼라에서 암시 적 변환을 설명 할 수 있습니까? (0) | 2019.12.06 |
---|---|
[SCALA] SparkSQL - 읽기 마루 파일을 직접 (0) | 2019.11.30 |
[SCALA] "합니다 MyType"문제 :해야합니까 실제 클래스를 반환하는 스칼라에서 추상적 인 유형 (또는 제네릭)를 사용해야? (0) | 2019.11.28 |
[SCALA] 스칼라 : 목록에 튜플 요소를 변환하는 방법 (0) | 2019.11.28 |
[SCALA] 엉성한 부산물 패턴 매칭 (0) | 2019.11.28 |