20100513

A Pattern for Non-Local Returns in Javascript

A week or two ago, someone on reddit was complaining about javascripts lack of non-local returns and stating the language was poor as it couldn't be extended to include them.

So, for fun, I wrote a quick implementation of non-local returns in javascript. Probably inefficient as hell, but functional nontheless.

// javascript non-local return
<html><body><script language="javascript">

var WithNonLocalReturn = function( block ){
var ex_t = function(){
var hidden = null ;

this.set = function( retval ){
hidden = retval ;
};

this.get = function( retval ){
return hidden ;
};
};

var ex = new ex_t() ;

var valid = true ;

var leave = function( retval ){
if( valid ){
ex.set( retval ) ;
throw ex ;
} else {
throw ( ""
+ "It is invalid to call the non-local return"
+ "outside the stack of the creating WithNonLocalReturn"
) ;
}
};

try {
return block( leave ) ;
} catch( e ) {
if( e instanceof ex_t ){
return e.get() ;
} else {
throw e ;
}
} finally {
valid = false ;
}
};

var Each = function( iterable , fn ){
for( k in iterable ){
fn( iterable[ k ] ) ;
}
};

alert( WithNonLocalReturn( function( nonLocallyReturn ){
Each( [ 1, 2, 3, 4, 5, 6, 7, 8, 9] ,
function( i ){
alert( 'Testing : ' + i ) ;
if( i == 6 ){
nonLocallyReturn( 'Success : ' + i ) ;
}
});

return 'Failure' ;
}));

</script>


For fun they're nestable and since you name the value-returning function, you can easily and readably select what level nesting to return to. Or horrifically pass a non-local-return through as a sort of continuation down the stack of an otherwise rational bit of logic.

alert( WithNonLocalReturn( function( dontDoThis ){
return 'lolwut'.replace( /lol/g , dontDoThis ) ;
}));


One should probably avoid doing that.

20100308

Go Language is lovely

I've been playing with Google's go language for the last week or so, and I have to say its a lovely language. I generally grab the mailing list for anything new I get into, and today someone was looking for a way to wait for a set of go-routines to complete before continuing on in the main thread. Seeing as how common this sort of thing is, I decided to write up a quick library for it.

To use the library first issue a dispatch.New() to acquire a new dispatch mechanism. Then attach any number ( technically upto uint ) of processes to it it via dispatchInstance.Go( func(){ other_process_here() } ). Any number of other processes ( still technically uint ) can wait on the runners to finish before executing.

Anyway, here it is, and hope it's useful for someone.

In dispatch.go :

package dispatch

import "sync"

type Manager interface {
Go( func() )
Wait()
}

type manager struct {
lock sync.Mutex
running uint
waiting uint
wakeup chan bool
}

func New() *manager {
m := new(manager)
m.wakeup = make(chan bool)
return m
}

func (m *manager) Go( fn func() ) {
m.lock.Lock()
m.running++
m.lock.Unlock()

go func(){
fn()

m.lock.Lock()
m.running--
if (m.running == 0) && (m.waiting > 0) {
oc := m.wakeup
nc := make(chan bool)
i := m.waiting
go func(){
for ; i > 0 ; i-- {
oc <- true
}
}()
m.wakeup = nc
m.waiting = 0
}
m.lock.Unlock()
}()
}

func (m *manager) Wait() {
wait := false

m.lock.Lock()
if m.running > 0 {
m.waiting++
wait = true
}
m.lock.Unlock()

if wait {
<- m.wakeup
}
}


And some example usage in main.go :

package main

import "fmt"
import "rand"
import "time"

import "./dispatch"

func main () {
w := dispatch.New()

for i := 0 ; i < 100 ; i++ {
c := i
w.Go( func(){
time.Sleep( rand.Int63n( 1000000000 ) )
fmt.Print( c , "\n" )
w.Go( func(){
time.Sleep( rand.Int63n( 1000000000 ) )
fmt.Print( c , " - second effect\n")
})
})
}

fmt.Print( "All Launched\n" )

w2 := dispatch.New()

for i := 0 ; i < 5 ; i++ {
c := i
w2.Go( func(){
w.Wait()
time.Sleep( rand.Int63n( 1000000000 ) )
fmt.Print("[ " , c , "] This should happen after the first set\n")
})
}

fmt.Print( "Second set all launched\n" )

w.Wait()

for i := 10 ; i < 15 ; i++ {
c := i
w.Go( func(){
time.Sleep( rand.Int63n( 1000000000 ) )
fmt.Print("[ " , c , "] reusing first queue\n")
})
}

fmt.Print( "Main thread past first set\n" )

w2.Wait()

fmt.Print( "Main thread past second set\n" )

w.Wait()

fmt.Print( "Main thread past reuse of first queue\n" )

}


I really like this language. It feels like somebody took many of the best facets of C, javascript and erlang and tucked them into a single package. The static duck-typing is beautiful.

About Me

(2) the subculture of the compulsive programmer, whose ethics prescribe that one silly idea and a month of frantic coding should suffice to make him a life-long millionaire. --ewd1036