2014-09-10 4 views
0

가끔씩 다른 메서드 호출의 끝 부분에 부작용 함수를 더 기능적인 방식으로 연결하려는 경우가 있지만 원래 형식을 Unit으로 변환하고 싶지는 않습니다. Option[Record]을 반환하는 데이터베이스를 레코드로 검색하는 read 메서드가 있다고 가정합니다.원래 형식을 반환하는 부작용 메서드가있는 형식이 있습니까?

def read(id: Long): Option[Record] = ... 

반환 Some(record)read 경우, 그 값을 캐시하고 이동 할 수 있습니다.

read(id).withSideEffect { record => 
    // Cache the record 
} 

어디 : 나는 위의 코드를 방지하고 무슨 일이 일어나고 있는지에 관해서는 좀 더 명확하게하기 위해 더 많은이 같은 끝낼 싶습니다

read(id).map { record => 
    // Cache the record 
    record 
} 

을하지만 : 나는 이런 식으로 뭔가를 할 수 withSideEffectread(id)과 동일한 값을 반환합니다. 높고 낮은 검색 후, 나는 이런 식으로 어떤 유형에 어떤 방법을 찾을 수 없습니다.

implicit class ExtendedOption[A](underlying: Option[A]) { 
    def withSideEffect(op: A => Unit): Option[A] = { 
     underlying.foreach(op) 
     underlying 
    } 
} 

나는 이와 같은 방법으로 간과 수있는 스칼라 유형이 있습니다 : 내가 가지고 올 수있는 가장 가까운 솔루션은 암시 마법을 사용? 그리고 그러한 방법을 사용하면 잠재적 인 설계상의 결함이 있습니까?

+0

스칼라는 특정 인스턴스에 해당하는 유형 인 "싱글 톤 유형"(객체와 혼동해서는 안 됨)을 지원합니다. 예를 들어'def f (a : A) : a.type' * 메소드는 제공된 A 인스턴스를 반환해야합니다. –

+1

디자인이 나에게 잘 어울린다. 나는 이것을 나 자신으로 사용한다. – samthebest

+1

[Kestrel 결합 자] (http://stackoverflow.com/questions/9671620/how-to-keep-return-value-when-logging-in-scala)에 대해 생각해 보셨습니까? 이 예제는이를 로깅에 사용하지만 쉽게 캐싱에 적용 할 수 있습니다. –

답변

1

Future.andThen (scaladoc)와 같은 뭔가를 할 것이라고는 부작용을 소요하고 유창 체인을 촉진하기 위해 현재 값의 미래를 반환합니다.

반환 유형이 this.type이 아닙니다.

도 약 duplicate questions도 참조하십시오.

+0

+1을 참조하십시오. 그것은 OP의 필요에 정확히 맞는 것 같습니다. –

0

부작용이있는 함수의 "명시 적 주석"에 대해 scalaz를 사용할 수 있습니다. scalaz 7.0.6에서는 IO Monad입니다 : http://eed3si9n.com/learning-scalaz/IO+Monad.html

scalaz 7.1에서는 더 이상 사용되지 않습니다. 내가 작업

val readAndCache = Task.delay(read(id)).map(record => cacheRecord(record); record) 
readAndCache.run // Run task for it's side effects 
+0

이 비추천에 관한 정보가 있습니까? 소스에 주석이 달거나 문서화되어 있지 않습니다. – Hugh

+0

지금 찾을 수 없습니다. Task가 IO를 대체해야한다는 것은 메일 링리스트의 토론이었습니다. 그러나 7.1에서 발생하지 않은 것처럼 보입니다. 둘 다 의미 론적으로 유사합니다. –