// "favor composition over inheritance" ~Effective Java class Parent { def getAll() { String resp = "" 2.times { resp += get(it) } return resp } def get(def i) { "get PARENT $i\n" } } class Child1 extends Parent { def get(def i) { "get CHILD $i\n" // is used by parent's getAll } } class Child2 { @Delegate Parent p = new Parent() // decorated Parent instance def get(def i) { "get CHILD $i\n" // not used by parent's getAll } } Parent c1 = new Child1() assert c1.getAll() == "get CHILD 0\nget CHILD 1\n" // calls child's get() assert c1.get(0) == "get CHILD 0\n" //Parent c2 = new Child2() // Child2 is not a Parent! Child2 c2 = new Child2() assert c2.getAll() == "get PARENT 0\nget PARENT 1\n" // calls parent's get() assert c2.get(0) == "get CHILD 0\n"
Thursday, November 15, 2012
@Delegate vs. Extends
Monday, November 5, 2012
DNS lookup - timed
int maxTimeout = 30000 int minTimeout = 15000 List domainList = [ 'gmail.com', 'google.co.uk', 'google.com', 'bbc.co.uk', 'cnn.com', 'java.oracle.com', 'facebook.com', 'twitter.com', 'oracle.com', 'zen.co.uk', 'java.net', 'www.scala-lang.org', 'plus.google.com', 'guardian.co.uk', 'linkedin.com', 'www.typesafe.com', 'www.yahoo.com', 'www.ibm.com', 'www.apache.org', 'www.adobe.com', 'www.microsoft.com', 'www.stackoverflow.com', 'www.apple.com', 'groovy.codehaus.org', 'java.oracle.com', 'www.telegraph.co.uk', 'www.jroller.com', 'www.dell.com', 'www.samsung.com', 'www.amazon.co.uk', 'docs.oracle.com', 'www.infoq.com', 'www.devoxx.com', 'www.qconlondon.com', 'www.smashingmagazine.com', 'en.wikipedia.com' ] int count = 1 while (true) { int idx = (int)( Math.random() * domainList.size ) println "[$count] nslookup ${domainList[idx]}" def process = "nslookup ${domainList[idx]}".execute() println "Found text ${process.text}" int sleepTime = (int)( minTimeout + Math.random() * ( maxTimeout - minTimeout)) Thread.sleep( sleepTime ); ++count }
Monday, October 29, 2012
Resolve an HTTP Redirect
// source: https://gist.github.com/3899754 def findRealUrl(url) { HttpURLConnection conn = url.openConnection() conn.followRedirects = false conn.requestMethod = 'HEAD' if(conn.responseCode in [301,302]) { if (conn.headerFields.'Location') { return findRealUrl(conn.headerFields.Location.first().toURL()) } else { throw new RuntimeException('Failed to follow redirect') } } return url }
Wednesday, August 1, 2012
match/when implemented with Groovy's GEP-3
//WOW! https://gist.github.com/3002724 // No commas def a = 'tim' def nocom = match( a ) { when 'dave' 'Hi Dave' when 'tim' 'Hi Tim' otherwise 'none of the above' } assert nocom == 'Hi Tim' // Commas a = 'William' def com = match( a ) { when 'dave', 'Hi Dave' when 'tim', 'Hi Tim' otherwise 'none of the above' } assert com == 'none of the above' // Lists (can't use commas) a = [1,3] def list = match( a ) { when [1,2] 'One and two' when [1,3] 'One and three' when [2,1] 'Two and one' } assert list == 'One and three' // Wildcard Lists (can't use commas) a = [1,2,3] def wild = match( a ) { when [1,3,2] 'One, three and two' when [1,_] 'One and something' when [1,_,3] 'One, something and three' when [1,_,_] 'One, something and something' otherwise 'Something else' } assert wild == 'One, something and three' // Closures as the when/results String toRoman( int num ) { match( num ) { when { it >= 100 } { "C" + toRoman( num - 100 ) } when { it >= 90 } { "XC" + toRoman( num - 90 ) } when { it >= 50 } { "L" + toRoman( num - 50 ) } when { it >= 40 } { "XL" + toRoman( num - 40 ) } when { it >= 10 } { "X" + toRoman( num - 10 ) } when { it >= 9 } { "IX" + toRoman( num - 9 ) } when { it >= 5 } { "V" + toRoman( num - 5 ) } when { it >= 4 } { "IV" + toRoman( num - 4 ) } when { it >= 1 } { "I" + toRoman( num - 1 ) } otherwise "" } } assert "I" == toRoman( 1 ) assert "II" == toRoman( 2 ) assert "IV" == toRoman( 4 ) assert "V" == toRoman( 5 ) assert "VI" == toRoman( 6 ) assert "IX" == toRoman( 9 ) assert "X" == toRoman( 10 ) assert "XVII" == toRoman( 17 ) assert "XXXVIII" == toRoman( 38 ) assert "CCCXCIX" == toRoman( 399 ) /////////////////////////// // Implementation below... def match( v, c ) { new Matcher( var:v, closure:c ).match() } class Matcher { def var Closure closure Listcases = [] Otherwise otherwise def propertyMissing( name ) { if( name == '_' ) { new Any() } else { def w = new When() cases << w w } } def when( condition ) { cases << new When( condition:condition ) } def when( condition, result ) { cases << new When( condition:condition, result:result ) } def otherwise( result ) { this.otherwise = new Otherwise( result:result ) } public match() { closure.delegate = this closure.resolveStrategy = Closure.DELEGATE_ONLY closure() def ret = cases.find { it.condition instanceof Closure ? it.condition( var ) : it.condition == var }?.result ?: otherwise?.result ret instanceof Closure ? ret() : ret } } class When { def condition def result def getAt( List a ) { condition = a ; this } def call( result ) { this.result = result } def propertyMissing( String result ) { this.result = result } } class Otherwise { def result } class Any { boolean equals( other ) { true } } println 'DONE'
Sunday, July 15, 2012
GPars DataflowQueues
//source: http://jaxenter.com/tutorial-gpars-making-parallel-systems-groovy-and-java-friendly-43529-2.html //a sample code build process // //source: http://jaxenter.com/tutorial-gpars-making-parallel-systems-groovy-and-java-friendly-43529-2.html //a sample code build process // import static groovyx.gpars.dataflow.Dataflow.operator import groovyx.gpars.dataflow.* def _checkout = { String a -> Thread.sleep( (Long)Math.random() * 5 ); // a bit of random delay for fun println ">checking out...$a" return "checkout-$a" } def _compileSources = { a -> println ">compiling...$a" return "compileSources-$a" } def _generateAPIDoc = { a -> println ">api Docs...$a" return "generateAPIDoc-$a" } def _generateUserDocumentation = { a -> println ">user Docs...$a" return "generateUserDocumentation-$a" } def _packageProject = { project, api, doc -> println ">packaging...$project $api $doc" return "packageProject-$project $api $doc" } def _deploy = { a -> println ">deploying...$a" return (!!Math.round(Math.random())) } /* We need a Broadcaster and Queues to wire elements together */ def checkedOutProjects_B = new DataflowBroadcast() def urls_Q = new DataflowQueue() def compiledProjects_Q = new DataflowQueue() def apiDocs_Q = new DataflowQueue() def userDocs_Q = new DataflowQueue() def packages_Q = new DataflowQueue() def done_Q = new DataflowQueue() /* Here's the composition of individual build steps into a process */ operator(inputs: [urls_Q], outputs: [checkedOutProjects_B], maxForks: 3) { url -> bindAllOutputs _checkout(url) } operator([checkedOutProjects_B.createReadChannel()], [compiledProjects_Q]) { projectRoot -> bindOutput _compileSources(projectRoot) } operator(checkedOutProjects_B.createReadChannel(), apiDocs_Q) { projectRoot -> bindOutput _generateAPIDoc(projectRoot) } operator(checkedOutProjects_B.createReadChannel(), userDocs_Q) { projectRoot -> bindOutput _generateUserDocumentation(projectRoot) } operator([compiledProjects_Q, apiDocs_Q, userDocs_Q], [packages_Q]) { project, api, doc -> bindOutput _packageProject(project, api, doc) } def deployer = operator(packages_Q, done_Q) { packagedProject -> boolean ok = _deploy(packagedProject) println "! Deployed? $ok" bindOutput (ok) } /* add data, start the machine a rollin! */ 5.times { urls_Q << "url #$it" } 5.times { urls_Q << "url #${++it*5}" } /* Now we're set up, and can just wait for the build to finish */ println "==Starting the build process. This line MIGHT NOT be printed out first ...==" //deployer.join() //Wait for the last operator in the network to finish??
Thursday, July 12, 2012
GBench - easy code benchmarking
//source: http://nagaimasato.blogspot.jp/2012/07/gbench-031-released.html //requires Groovy 2.0.0+ @Grab('com.googlecode.gbench:gbench:0.3.1-groovy-2.0') import gbench.BenchmarkBuilder import groovy.transform.CompileStatic int fib(int n) { if (n < 2) return n return fib(n - 1) + fib(n - 2) } @CompileStatic int fib2(int n) { if (n < 2) return n return fib2(n - 1) + fib2(n - 2) } new BenchmarkBuilder().run { int n = 20 "Normal Version" { fib n } "@CompileStatic Version" { fib2 n } }.prettyPrint()
Wednesday, July 11, 2012
Conceptual Map/Reduce Example
//inspiration: http://hamletdarcy.blogspot.ca/2008/01/mapreduce-for-mere-mortals.html // general purpose function def mapReduceFunc = { data, mapFunction, reduceFunction -> def mappedData = data.collect(mapFunction) reduceFunction(mappedData) } // the data Map dictionary = [ abacus: "a device for making arithmetic calculations", arc: "any unbroken part of the circumference of a circle", beaver: "a large, amphibious rodent of the genus Castor" ] // the mapping function impl def startingCharacter = { pair -> pair.value = pair.key[0].toLowerCase() return pair } // the reducing function impl def countCharacters = { dataMap -> Map result = [:] ('a'..'z').each{ result[it] = 0 } dataMap.each { pair -> result[pair.value]++ } return result } // put it all together! def result1 = mapReduceFunc(dictionary, startingCharacter, countCharacters) println result1 //// TWEAK THE I/O FUNCS! //// // the mapping function impl startingCharacter = { pair -> return pair.key[0].toLowerCase() } // the reducing function impl countCharacters = { dataList -> Map result = [:] ('a'..'z').each{ result[it] = 0 } dataList.each { it -> result[it]++ } return result } // put it all together! def result2 = mapReduceFunc(dictionary, startingCharacter, countCharacters) println result2 assert result1 == result2
Subscribe to:
Posts (Atom)