2012-07-03 2 views
2

foreach 문에서 패턴 일치 후 아무 것도 할 수 있습니까?
게시물 일치 단계를 수행하고 싶습니다. 예 : 변수를 설정합니다. 또한 foreach이 String => Unit이므로 Unit 반환을 원합니다. 기본적으로 Scala는 마지막 명령문을 반환하려고합니다. 업데이트]foreach에서 패턴 일치를 수행 한 다음 마지막 단계를 수행하십시오

Iteratee.foreach[String](_ match { 
     case "date" => out.push("Current date: " + new Date().toString + "<br/>") 
     case "since" => out.push("Last command executed: " + (ctm - last) + "ms before now<br/>") 
     case unknow => out.push("Command: " + unknown + " not recognized <br/>") 
    } // here I would like to set "last = ctm" (will be a Long) 
    ) 

: 새로운 코드와 컨텍스트 여기

몇 가지 코드입니다. 또한 새로운 질문이 추가되었습니다. :) 주석에 포함되어 있습니다.

def socket = WebSocket.using[String] { request => 

// Comment from an answer bellow but what are the side effects? 
// By convention, methods with side effects takes an empty argument list 
def ctm(): Long = System.currentTimeMillis 

var last: Long = ctm 

// Command handlers 
// Comment from an answer bellow but what are the side effects? 
// By convention, methods with side effects takes an empty argument list 
def date() = "Current date: " + new Date().toString + "<br/>" 
def since(last: Long) = "Last command executed: " + (ctm - last) + "ms before now<br/>" 
def unknown(cmd: String) = "Command: " + cmd + " not recognized <br/>" 

val out = Enumerator.imperative[String] {} 

// How to transform into the mapping strategy given in lpaul7's nice answer. 
lazy val in = Iteratee.foreach[String](_ match { 
    case "date" => out.push(date) 
    case "since" => out.push(since(last)) 
    case unknown => out.push(unknown) 
} // Here I want to update the variable last to "last = ctm" 
).mapDone { _ => 
    println("Disconnected") 
} 

(in, out) 
} 

답변

12

나는 당신의 ctm이 무엇인지 모르겠지만, 당신은 항상이 작업을 수행 할 수 있습니다 : 당신은 인자로 코드 블록을 사용하고자 할 때

val xs = List("date", "since", "other1", "other2") 

xs.foreach { str => 

    str match { 
     case "date" => println("Match Date") 
     case "since" => println("Match Since") 
     case unknow => println("Others") 
    } 

    println("Put your post step here") 
} 

참고하면 {} 대신 ()의를 사용해야합니다 foreach().

+3

더 쉽게 할 수 있습니다. 'xs foreach {case "date"=> ....}' – tilex

3

나는 당신의 질문에 답하지 않겠지 만, 스칼라에서 변수를 재 할당하는 것은 나쁜 습관이라는 점에 유의해야합니다. var을 피하기 위해 코드를 다시 작성하는 것이 좋습니다.

첫째, 다른 뭔가로 문자열을 변환 :

val strings = it map { 
    case "date" => "Current date: " + new Date().toString + "<br/>" 
    case "since" => "Last command executed: " + (ctm - last) + "ms before now<br/>" 
    case unknow => "Command: " + unknown + " not recognized <br/>" 
} 

다음으로,이

strings map { out.push(_) } 

그것은 push은 부작용의 구현처럼 보인다 밀어 넣습니다. 그러한 방법으로 프로그램을 예측할 수 없게 만들기 때문에 나쁜 것입니다.

def push(s: String) = { 
    ... 
    (ctm, last) 
} 

그리고이 좋아 사용 : 당신은 쉽게 push 반환에게 튜플을함으로써 부작용을 피할 수

val (ctm, last) = out.push(str) 

업데이트 : 물론 부작용의

이 프로그램을 편리하게 사용할 수 있도록하기 위해 필요하다 . 나는 외부 변수에 의존하는 방법이 pure보다 덜 예측 가능하다는 것을 의미했다. 부작용없이 방법을 테스트하는 것이 더 쉽습니다.

예. val 초를 var 초 이상으로 지정해야 프로그램이 더 기능적이고 상태를 유지할 수 있습니다. Stateless 알고리즘은 스레드로부터 안전하며 예측 가능합니다.

프로그램이 본질적으로 상태 유지 프로그램 인 것 같습니다. 적어도, 당신이 :) 수있는 "기능"과 무 상태로 유지하려고

문제의 내 제안 솔루션입니다 :

// By convention, methods with side effects takes an empty argument list 
def ctm(): Long = // Get current time 

// Command handlers 
def date() = "Current date: " + new Date().toString + "<br/>" 
def since(last: Long) = "Last command executed: " + (ctm() - last) + "ms before now<br/>" 
def unknown(cmd: String) = "Command: " + unknown + " not recognized <br/>"  

    // In your cmd processing loop 

    // First, map inputs to responses 
    val cmds = inps map { 
    case "date" => date() 
    case "since" => since(last) 
    case unk  => unknown(unk) 
    } 

    // Then push responses and update state 
    cmds map { response => 
    out.push(response) 
    // It is a good place to update your state 
    last = ctm() 
    } 

당신 때문에, 코드의 컨텍스트없이이를 테스트하기 어렵다 그것을 당신 자신의 필요에 맞추어야합니다. 나는 당신의 질문에 대답했기를 바랍니다.

+0

답장을 보내 주셔서 감사합니다. 그러나 몇 가지 질문/발언이 있습니다. 어떤면에서 부작용이 있다는 것을 의미합니까? out.push의 유일한 목적은 websocket에 대한보다 구체적인 쓰기를 부작용으로 만드는 것입니다. push는 소켓을 통해 String을 푸시하기 때문에 Unit을 반환하므로 거기에 튜플을 할당 할 수 없습니다. var 대신 val을 추천하는 것은 흥미 롭습니다. 내 기능적 기술이 부족할 수 있으며,이 맥락에서 업데이트 된 답변을 많이 주셔서 감사합니다. last는 websocket을 통해 recived 된 마지막 명령의 currentTimeInMillies를 보유해야하는 인스턴스 변수입니다. cdm은 def입니다 – Farmor

+0

그래, 나는 문맥이 막연하다는 것을 이해하고 큰 대답을 내 대답으로 업데이트했다. 당신의 대답은 훌륭합니다. 나는 아직도 부작용의 의미를 이해하지 못한다. 예를 들어 부작용이 date()가 원인 일까? 또한 Iteratee는지도를 지원하지 않습니까? – Farmor

+0

Iteratee는 어디에서 왔습니까? Iteratee.map을 사용해 보셨습니까? 컴파일되었거나 오류가 있습니까? – lambdas

관련 문제