2012-01-08 7 views
4

노드를 생성하고 자식 노드를 가질 수있는 방법 treeNode을 정의했습니다. 나는이 방법을 사용하면do-nothing 핸들러를 by-name 매개 변수로 설정하는 방법은 무엇입니까?

def treeNode(text:String) (children: => Any) { 
    val b = new TreeNode(text) 
    children 
} 

, 내가 쓸 필요가 : 단순화 된 코드는

treeNode("aaa") { 
    treeNode("bbb") {} 
    treeNode("ccc") {} 
} 

당신은 그들이 아이가없는 리프 노드를 볼 수 있지만 그들은 비어 있어야 블록 {}. 당신이 통과 할 수 없습니다

treeNode("aaa") { 
    treeNode("bbb") 
    treeNode("ccc") 
} 

도움말 ~

답변

9

를 작성하여 treeNode 기능을 기반으로 작업을 분할 할 수있다; 문제가 있더라도 다중 매개 변수 블록이있는 함수는 에 최소한에 각 블록에 괄호 또는 중괄호가 있어야합니다.

암시 적 매개 변수 블록을 전혀 참조 할 필요가 없습니다. 불행하게도, 당신은 call-by-name 암시 적 매개 변수를 가질 수 없으며, 그렇다고해도 서명을 사용하면 임의의 암시 적 요소가 그 자리에서 작동 할 수 있습니다!

자, 완전성을 위해 보여줄 방법이 있지만, (단지 leafNode과 같은 다른 이름을 원하지 않는다고 가정하면) 거기에 {}이라는 꼬리표를 남겨 두는 것이 좋습니다.

다음 작업을 수행 할 때 원하는 구문을 정확하게 얻을 수 있습니다. 첫째, 당신은 암시 적 매개 변수를 필요로하지만, 당신은 래퍼 클래스 만들기 (이미 Function0를 사용할 수 있지만 다음 단계는 의도하지 않은 결과가있을 수 있습니다) :

trait AnyByName { def eval: Any } 
def treeNode(text: String)(implicit children: AnyByName) = (text,children.eval) 

지금 당신이 두 가지가 필요합니다

- 당신이 필요로하는 이름으로 Any을 새 특성으로 변환 할 수 있으려면 암묵적인 아무것도하지 않아도됩니다. 그래서 우리

implicit val nameForDoingNothing = new AnyByName { def eval =() } 
implicit def wrap_any_by_name(a: => Any) = new AnyByName { def eval = a } 

그리고 지금 우리는 당신이 후했다 행동 복구 :

scala> treeNode("Hi") 
res1: (String, Any) = (Hi,()) 

scala> treeNode("Hi") { treeNode("there") } 
res2: (String, Any) = (Hi,(there,())) 

합니다 (예를 들어, 당신은 아무것도 반환하지 않습니다를, 내가 여기에 작동하는지 표시합니다.)

그것은 당신이 아주 많이 사용 DSL 두 개의 이름이 받아 들일 수없는 것을 것으로 예상되는 경우 난 단지이 일을 건의 할 것입니다 이유입니다,하지만, 도구의 많은 그냥 {}의를 피하기 위해입니다. (또한 매우 많이 사용되기를 기대한다면 은 아마도 고통스런 이름으로 길어서 단지 node을 제안 할 것입니다.)

+0

대단히 감사합니다. 이해하고 시도하는 데 시간이 걸릴 것입니다. 감사합니다! – Freewind

+0

위대한 솔루션 ... 실제로 나는이 단계에서 너무 멀리 DSL을 얻지 못했을 것입니다. 아마도 다음 주에 이런 것들을 발견 할 것입니다. –

6

AFAICT :

매개 변수 children: => Any 기본 아무것도 실시하지 않는 값을 제공 할 수있는 방법은 내가 같은 코드를 쓸 수 있나요 기본적으로 빈 블록입니다.

, BTW 당신은 ​​정말 단순히 문제는 당신이 그것을 할 - 아무것도 (기본값) 값을 제공 할 수 없습니다 하지 또 다른 하나 def leaf(text:String) = treeNode(t) {}

관련 문제