2010-04-13 34 views
7

我是不是 Groovy專家,但我確實讀過「Groovy in Action」一書。在Groovy中,每個閉包都帶有一個「上下文」,其中閉包內的項目可以訪問像「this」,「owner」和「delegate」這樣的僞變量,讓項目知道誰叫閉包。這可以寫出這樣的DSL(在Groovy在行動):Scala關閉上下文

swing = new SwingBuilder() 
frame = swing.frame(title:'Demo') { 
    menuBar { 
    menu('File') { 
     menuItem 'New' 
     menuItem 'Open' 
    } 
    } 
    panel { 
    // ... 
    } 
} 

注意,「菜單欄」「知道」,它屬於「框架」,因爲它可以得到有關的所有者和委託上下文信息關閉。

這是可能在斯卡拉做?如果是這樣,怎麼樣?

+0

我曾經用一些方法模仿HTML生成器(而不是閉包的所有者/委託)。 http://gist.github.com/260426 http://gist.github.com/260446 – retronym 2010-04-13 16:26:11

+0

我在尋找更多的模式比特定的應用與Swing。作爲學習練習,我正在考慮與SWT一起嘗試。 – Ralph 2010-04-14 11:10:29

回答

16

一種方法是使用scala.util.DynamicVariable來跟蹤上下文。像SwingBuilder可以實現爲

import scala.util.DynamicVariable 
import javax.swing._ 

object SwingBuilder { 
    case class Context(frame: Option[JFrame], parent: Option[JComponent]) 
} 

class SwingBuilder { 
    import SwingBuilder._ 
    val context = new DynamicVariable[Context](Context(None,None)) 

    def frame(title: String)(f: =>Unit) = { 
    val res = new JFrame(title) 
    res.add(new JPanel()) 
    context.withValue(Context(Some(res),context.value.parent)){f;res} 
    } 

    def menuBar(f: =>Unit) = { 
    val mb = new JMenuBar() 
    context.value.frame.foreach(_.setJMenuBar(mb)) 
    context.withValue(Context(context.value.frame,Some(mb))){f;mb} 
    } 

    def menu(title: String)(f: =>Unit) = { 
    val m = new JMenu(title) 
    context.value.parent.foreach(_.asInstanceOf[JMenuBar].add(m)) 
    context.withValue(Context(context.value.frame,Some(m))){f;m} 
    } 

    def menuItem(title: String) = { 
    val mi = new JMenuItem(title) 
    context.value.parent.foreach(_.asInstanceOf[JMenu].add(mi)) 
    } 
} 

object Test { 
    def main(args: Array[String]) { 
    val builder = new SwingBuilder() 
    import builder._ 

    val f = frame("Demo") { 
     val mb = menuBar { 
     menu("File") { 
      menuItem("New") 
      menuItem("Open") 
     } 
     } 
    } 
    f.setVisible(true) 
    } 
} 
+3

斯卡拉永遠不會驚歎我:)...謝謝。 – Ralph 2010-04-13 16:05:09