开发者

How are "Closures" such a powerful abstraction that object systems and fundamental control structures are implemented using it?

Here is a quote from programming scala chapter 1:

Closures are such a powerful abstraction that object systems and fundamental control structures are often implemented using them

Apparently the statement is not specifically about Scala but Closures in general but I can not make much sense from it. Perhaps it is some pearl of wisdom only meant for those mighty compiler writers!

So who uses Closures to implement fundamental control structures and why?

Edit: I remember reading something about custom control structures in groovy "using the closure as the last parameter of method call" syntax and making the structure available to your code using meta-classes or use keyword with Categories. Could it be something related?

Edit: I found the following reference of the groovy custom control structures syntax here (slide 38):

Custom control structures

Thanks to closures

  • When closures are last, t开发者_如何学Chey can be put “out” of the parentheses

    surrounding parameters

  • unless(account.balance > 100.euros, { account.debit 100.euros })
  • unless(account.balance > 100.euros) { account.debit 100.euros }
  • Signature def unless(boolean b, Closure c)

Apparently what groovy is offering is a syntactic sugar for making the Closure based custom control structures appear like first-class control structures offered by the language itself.


I commented on the case of control structures. Let me comment on closures as objects. Consider what happens when you call a method on an object; it has access not only to the argument list, but also the fields of the object. That is, the method/function closes over the fields. This isn't that different from a "bare" function (i.e., not an object method) that closes over variables in scope. However, the object syntax provides a nice abstraction and modularity mechanism.

For example, I could write

case class Welcome(message: String) {
  def greet(name: String) = println(message + ", " + name)
}
val w = Welcome("Hello")
w.greet("Dean")

vs.

val message = "Hello"
val greet = (name: String) => println(message + ", " + name)
greet("Dean")

Actually, in this example, I could remove the "case" keyword from Welcome, so that message doesn't become a field, but the value is still in scope:

class Welcome2(message: String) {    // removed "case"
  def greet(name: String) = println(message + ", " + name)
}
val w = new Welcome2("Hello")        // added "new"
w.greet("Dean")

It still works! Now greet closes over the value of the input parameter, not a field.

var welcome = "Hello"
val w2 = new Welcome2(welcome)
w2.greet("Dean")     // => "Hello, Dean"
welcome = "Guten tag"
w2.greet("Dean")     // => "Hello, Dean"  (even though "welcome" changed)

But if the class refers to a variable in the outer scope directly,

class Welcome3 {                  // removed "message"
  def greet(name: String) = println(welcome + ", " + name) // reference "welcome"
}
val w3 = new Welcome3
w3.greet("Dean")                  // => "Guten tag, Dean"
welcome = "Buon giorno"
w3.greet("Dean")                  // => "Buon giorno, Dean"

Make sense?


There are three fundamental control structures:

Sequence

a = 1
b = 2
c = a + b

Conditions

if (a != b) {
  c = a + b
} else {
  c = a - b
}

Iterations/loops

for (a <- array) {
  println(a)
}

So, I guess they mean that internally many languages use closures for control structures (you can look the last two structures).

As an example:

if (a < b) {
  for (i = a; a < b; a++) {
    println(i)
    c = i * i
  }
} else {
  c = a - b
}

So for is a closure inside the if closure, and else is a closure too. That's how I understand it. They create a closure for the first if if the condition is true, create the closure inside the braces, call it. Then create a closure for the for loop and call it while the condition is true.

And I guess there is no list of languages which use closures internally.

Update:

Just as an example, this is how you can implement your own for loop in Scala (o is cyrillic, so it will compile):

def fоr(start: Unit, condition: => Boolean, increment: => Unit)(body: => Unit): Unit = {
  if (condition) {
    body
    increment
    fоr(0, condition, increment)(body)
  }
}

var i = 0

fоr (i = 0, i < 1000, i += 1) {
  print(i + " ")
}

So actually this is how it can be implemented in other languages on the inner level.


I would say that "closures are such a powerful abstraction..." because unlike standard methods, you have a reference to the calling object, regardless of the scope in which the closure has been called.

In Groovy, for example, you can add a new method, "capitalize" to String type:

String.metaClass.capitalize = {  
    delegate[0].upper() + delegate[1..-1].lower()  
}   
"hello".capitalize() // "Hello"

Or, you can do something more complex, like create a domain specific language (DSL) using closures.

class ClosureProps {

       Map props = [:]  
       ClosureProps(Closure c) {  
           c.delegate = this // pass closure scope to "this"
           c.each{"$it"()} // iterate through closure, triggering missingMethod()
       }  
       def methodMissing(String name, args) {  
           props[name] = args.collect{it} // collect extracted closure properties
       }  
       def propertyMissing(String name) {  
           name  
       }  
}  

Example

class Team {

        // the closure
        static schema = {  
            table team  
            id teamID  
            roster column:playerID, cascade:[update,delete]  
        }  
}  
def c = new ClosureProps(Team.schema)  
println c.props.id // prints "teamID"


a) Please try at least googling topics before asking questions.

b) Once you have done that, please ask specific questions.

c) Lexical closures are functions that have access to a lexical environment not available where they are invoked. As such, their parameters can be used to select messages, and pass parameters with those messages. For general control structures, they are not sufficient, unless they can affect the call stack, in the manner of continuations.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜