coco icon indicating copy to clipboard operation
coco copied to clipboard

Scope Guard Statements

Open redalastor opened this issue 14 years ago • 4 comments

The D programming language have a feature I'm fond off called Scope Guard Statements

Go also have a variant of that feature called defer.

The feature works like this:

r = acquire_resource()
scope(exit) {r.release()}

// Do stuff with r without worrying about releasing it

The scope guard block will be executed when the current scope is exited. Under the hood, it's just syntactic sugar for try / finally.

It's also possible to do scope(success) and scope(failure) which does the same thing but one runs if the scope exits without exception and the other when it exits with exception.

redalastor avatar Jul 28 '11 19:07 redalastor

Any proposed syntaxes, suggested compilations and/or use cases?

satyr avatar Jul 28 '11 20:07 satyr

I'm in favor of this.

In Python, this feature is called a context block and it uses the with statement:

    with open('readme.md', 'rU') as f:
        for line in f:
            print line.strip().lower()

which is sugar for:

    f = open('readme.md', 'rU')
    f.__enter__()
    try:
        for line in f:
            print line.strip().lower()
    finally:
        f.__exit__()

All the details as well as a ton of use-cases can be found in the with-statement PEP.

Unfortunately, JavaScript has uselessly commandeered the with keyword, and Coco has carried on that tradition by recycling it as IIFE sugar. As an alternative keyword, I'd suggest using or closing, both in the form using VAR = EXPR.

dsc avatar Sep 08 '11 05:09 dsc

Again, this proposal needs syntaxes/compilations/use-cases in JS.

satyr avatar Sep 08 '11 10:09 satyr

I think that this is most useful for I/O, and that's async in node. Therefore, I think this also needs to be able to span async stuff. As long as we don't have a bunch of special syntax for that, we IMO have to either mark the end somehow (which defeats the whole point of this), or we patch the callback so that it closes stuff. Contrived example:

getServerID = (server, cb) ->
  cbCalled = false
  cb calling (return if cbCalled; cbCalled = true)
  socket = net.connect 1234, server
  socket.setEncoding \utf8
  cb calling socket.destroy!
  <- socket.on \connect
  data = ''
  socket.on \data, (chunk) ->
    data += chunk
    cb data if (data.indexOf \\n) > -1
  socket.on \close, -> cb

Transformation:

<name> calling <function body>

is the same as

<tempvar> = <name>
<name> = ->
  <function body>
  <tempvar>...

Example:

cb calling (return if cbCalled; cbCalled = true)

is the same as

cb_ = cb
cb = ->
  return if cbCalled
  cbCalled = true
  cb_ ...

Or in JS:

var cb_ = cb;
cb = function() {
  if (cbCalled) return;
  cbCalled = true;
  cb_.apply(this, arguments);
};

Of course, there's probably some better name than calling.

thejh avatar Jan 08 '12 09:01 thejh