이것은 반드시 스칼라 질문 일 필요는 없지만 변경 가능한 상태, 기능적 사고 및 그 종류를 피하는 것과 관련된 디자인 질문입니다. Scala를 사용하고 있습니다. 요구 사항이 주어지면변경 가능한 함수 알고리즘의 기능적 발견
:
입력 중 하나를 성공하거나 FAIL 1 10
최종 출력 사이의 임의의 숫자의 본질적으로 무한한 스트림에서 오는
이 수 특정 시간에 스트림에 '듣기'하는 여러 개체가있을 수 있으며 서로 다른 시간에 청취를 시작할 수 있으므로 모두 '첫 번째'숫자와 다른 개념을 가질 수 있습니다. 따라서 스트림에 대한 리스너는 스트림 자체에서 분리되어야합니다.
의사 코드 : 여기
if (first number == 1) SUCCEED
else if (first number >= 9) FAIL
else {
first = first number
rest = rest of stream
for each (n in rest) {
if (n == 1) FAIL
else if (n == first) SUCCEED
else continue
}
}
는 가능한 가변 구현 :
이sealed trait Result
case object Fail extends Result
case object Succeed extends Result
case object NoResult extends Result
class StreamListener {
private var target: Option[Int] = None
def evaluate(n: Int): Result = target match {
case None =>
if (n == 1) Succeed
else if (n >= 9) Fail
else {
target = Some(n)
NoResult
}
case Some(t) =>
if (n == t) Succeed
else if (n == 1) Fail
else NoResult
}
}
이 작동하지만 나에게 냄새가 난다. StreamListener.evaluate는 참조가 투명하지 않습니다. 그리고 NoResult 토큰의 사용은 옳다고 생각하지 않습니다. 그것은 명확하고 사용하기 쉽고/코드가 있지만 장점이 있습니다. 게다가 거기에는 기능적 해결책이 있어야합니다.
나는이 다른 가능한 옵션을 마련했습니다
(아마도 새) StreamListener을 반환 평가하는 데, 그러나 이것은 내가 '아무튼 StreamListener의 하위 유형을 결과 할 것이다 의미 기분 나빠.
평가할 때 Stream [Int]을 매개 변수로 사용하고 StreamListener가 실패 또는 성공을 결정하는 데 필요한만큼 Stream을 소비하도록 할 수 있습니다. 이 접근법에서 볼 수있는 문제는 리스너를 등록하는 클래스가 각 숫자가 생성 된 후에 각 리스너를 쿼리하고 실패 나 성공시 즉시 적절한 조치를 취해야한다는 것입니다. 이 방법을 사용하면 각 청취자가 평가를 완료 할 때까지 스트림 평가를 강제로 수행하기 때문에 이러한 현상이 발생할 수있는 방법을 알 수 없습니다. 단일 숫자 생성에 대한 개념은 없습니다.
표준 스칼라/FP 관용구가 있습니까?
감사합니다. 나는이 해결책을 많이 좋아한다. mutability를 호출 코드까지 이동시키는 것은 무엇을 의미합니까? 호출 코드가 StreamListeners의 목록을 유지하고 각 호출에 대해 evaluate 호출 결과를 매핑 한 다음 결과 목록을 (FinalizedResults, EverythingElse)로 분할하고 성공/실패를 처리 한 다음 그 자체로 새로운 상태를 만듭니다 미해결의 청취자 + 새롭게 등록 된 청취자. 이 접근 방법에 문제가 있는지 잠시 확인해야 할 것입니다. –
저는 전화 코드를 아주 멀리 생각하지 않았습니다. 네가 좋은 접근 방법 인 것처럼 들리네. –