Groovy - Understand Closure in More Detail and Distinguish Each Lexical Scope in Closure

in #utopian-io6 years ago (edited)

Groovy.png

<h4>Repository <p dir="auto"><br /><br /><span><a href="https://github.com/JetBrains/intellij-community" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://github.com/JetBrains/intellij-community<span> <a href="https://github.com/gradle/gradle" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://github.com/gradle/gradle<span> <a href="https://github.com/apache/groovy" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://github.com/apache/groovy <h4>What Will I Learn? <ul> <li>You will learn more about Closure <li>Deal with functional programming in Groovy <li>All about lexical scope upon Closure in Groovy <h4>Requirements <ul> <li>The latest version of <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Java™ SE Development Kit 8 <li>The latest version of <a href="https://gradle.org/install/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Gradle Build Tool <li>The latest stable version of <a href="http://groovy-lang.org/download.html" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Apache Groovy <li><a href="https://www.jetbrains.com/idea/download/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">IntelliJ IDEA Community Edition <li>Understanding of my <a href="https://steemit.com/utopian-io/@murez-nst/mureztutorial013" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">previous tutorial <li>Clone my current project <code>https://github.com/murez-nst/JVM-Based.git and then execute the <code>gradlew build command on your local directory. Finally, create a new Groovy script, <code>Test. <p dir="auto"><br /> <blockquote> <p dir="auto">I will not discuss the installation and creation steps anymore in this tutorial. For more details, please visit my previous one. <p dir="auto"><br /> <h4>Difficulty <ul> <li>Beginner<br /> <br /> <hr /> <p dir="auto">In my previous tutorial, I've already discussed about Groovy DSL can be more flexible and powerful to build such a custom syntax, so anyone can easily interpret the codes even to who doesn't understand the programming at all. <p dir="auto">But, I think DSL comes prematurely to the beginners. Because to get closer, they have to understand <strong>Closure extensively in advance. And now, this tutorial will explain it in detail. Initially, I will use the term of <strong>block to simply refer to the block of statements or algorithm to solve a particular case, i.e. <em>function, <em>method or <em>closure. Because in Groovy, they have the same major characteristic as performing a particular process depends on the parameter(s) (as input), has the type which is a type of the returned value (as output) and <strong>always produce any output, at least <code>null or even you somehow define it which does not intend to return any value at all. <p dir="auto">The main goal of a block is to prevent redundant definitions. So, if Java SE has provided a solution raising a number to the power of the second one, <code>Math.pow(double, double), then we don't need to create the same new definition. Just use the existing one. <p dir="auto">Now, they can be distinguished from each other very easily as follows <h2>Function <p dir="auto">The base form of a block that only depends on parameter(s) and the other same level members. The term of <em>function in the world of programming is general and comprehensive meaning, sometimes in a particular language it has a specific meaning. Java was originally intended for object-oriented programming, although it has finally adopted functional programming. So, I think the right definition for a function in the context of Java is the static one which is defined using the <code>static keyword. <pre><code>class A { private final NON_STATIC_RESOURCE = 'will never be touched' static void sayHello(def yourName) { // (1) new Inner() // (2) new Callable() { // (3) @Override void to(String name) { } } println "Hello ${ yourName }!" // (4) } class Inner { } interface Callable { void to(String name) } } def result = A.sayHello('World') println result // (5) <p dir="auto"><img src="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmZZzxGYo8J7o3PxKommj8sguANLXgkSWuWEKkjTrYyVN7" alt="Untitled 14.png" srcset="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmZZzxGYo8J7o3PxKommj8sguANLXgkSWuWEKkjTrYyVN7 1x, https://images.hive.blog/1536x0/https://ipfs.busy.org/ipfs/QmZZzxGYo8J7o3PxKommj8sguANLXgkSWuWEKkjTrYyVN7 2x" /><br /> <br /> <ol> <li>A function which is defined using <code>static keyword. <li>An error occurs, because this function attempts to access non-static members. This is the meaning of my statement about "<em>a block that only depends on parameter(s) and the other same level members". <li>But, why this one can be accessed?<br /> Because as a member <strong><em>inner-interface is always static implicitly.<br /> Because of this rule, we can perform functional programming easily as follows, <pre><code>class A { ... static def greeting(String salaam) { new Callable() { @Override void to(String name) { println "$salaam $name!" } } } } def sayHello = A.greeting('Hello') def sayHi = A.greeting('Hi') sayHello.to 'World' sayHello.to 'Groovy' sayHi.to 'Murez' <img src="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmacwpezGzSC9AdnP8zUPVq6ygbwv1YRRyNPYq2EWMqzsi" alt="Untitled 15.png" srcset="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmacwpezGzSC9AdnP8zUPVq6ygbwv1YRRyNPYq2EWMqzsi 1x, https://images.hive.blog/1536x0/https://ipfs.busy.org/ipfs/QmacwpezGzSC9AdnP8zUPVq6ygbwv1YRRyNPYq2EWMqzsi 2x" /><br /> <br /> <li>As I explained, a function depends on parameter(s) and the other static members only. If you try to do the following,<br /> <code>println "Hello ${ NON_STATIC_RESOURCE }!"<br /> an error will occur. <li>The result is <code>null, why?<br /> Again, this is the meaning of my statement about "<em>a block <strong>always produce any output, at least null or even you somehow define it which does not intend to return any value at all".<br /> Here the <code>sayHello method with a <code>void type is executed, then a <code>null value will be given. <h2>Method <p dir="auto">It is the same as a function but can access non-static members. This is why a method is always represented as a behavior on an object. <p dir="auto">In the JVM-based context, a function will never access a <em>field (or sometimes as an attribute or property) which is a non-static member. So, it is ridiculous to create an object first and then execute a function. This is why we only have to do <code>A.sayHello('World') in order to execute a function as in the previous example. <p dir="auto">While in the object-oriented programming context, a method in any class always depends on the fields to perform such a particular process. So in order to execute a method, we must create the object first. <pre><code>class B { private String salaam void say(String name) { println "$salaam $name!" // (1) } } def withHello = new B(salaam: 'Hello') def withHi = new B(salaam: 'Hi') withHello.say 'World' // (2) withHi.say 'Murez' <p dir="auto"><img src="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmXaMDkpy8zHLUbMqh5VKpniwGWsT5GQ1u564bhaL7GuD6" alt="Untitled 16.png" srcset="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmXaMDkpy8zHLUbMqh5VKpniwGWsT5GQ1u564bhaL7GuD6 1x, https://images.hive.blog/1536x0/https://ipfs.busy.org/ipfs/QmXaMDkpy8zHLUbMqh5VKpniwGWsT5GQ1u564bhaL7GuD6 2x" /><br /> <br /> <ol> <li>Now a method can access any non-static member, of course by eliminating the <code>static keyword. <li>The <code>say method must be invoked by first creating an object of enclosing class.<br /> <br /> <p dir="auto">Eventually why do you have to define a method while there are no dependencies with any property? Then you have to redefine it into a function. <p dir="auto">Sometimes, if referring to any name is ambiguous, we can use <code>this keyword explicitly that corresponds to the enclosing class where it is used. <pre><code>class Outer { class Inner { private String desc void set(String desc) { this.desc = desc // (1) } } void get() { this.desc } // (2) } <ol> <li>The name of <code>desc is ambiguous between field or argument. So, <code>this used here corresponds to the <code>Inner class and then <code>this.desc is a property. <li>The <code>this used here corresponds to the <code>Outer class while the field of <code>desc never exists in the <code>Outer class finally this statement will cause an error<br /> <br /> <p dir="auto">Of course <code>this cannot be used in a static context, because <code>this only refers to any non-static member. <h2>Closure <p dir="auto">This is the most powerful one, in addition to parameter(s) it also depends on the undefined members which can be easily resolved using delegation, as long as the delegated object defines the missing members correctly. <p dir="auto">In Java, any interface that has only <strong>one abstract method can be applied as a lambda expression which is an anonymous method, while <a href="http://docs.groovy-lang.org/latest/html/api/groovy/lang/Closure.html" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">closure is a lambda expression plus delegate capability. <p dir="auto">Closure is an abstract class, but we can create it in the same way as easy as lambda expression. This is the simplest closure, <code>{ } that returns a <code>null. Delegation can be done by simply invoking the <code>setDelegate method as follows, <pre><code>class Any { private myName String getName() { myName } // (1) } def say = { println "$it ${ name }!" // (2) } say.delegate = new Any(myName: 'World') // (3) say 'Hello' // (4) say.delegate = new Any(myName: 'Murez') say 'Hi' <p dir="auto"><img src="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmYThjscfo3qoPmembVvGsed15tHQU3Y1q4eWsNh4AV9UJ" alt="Untitled 17.png" srcset="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmYThjscfo3qoPmembVvGsed15tHQU3Y1q4eWsNh4AV9UJ 1x, https://images.hive.blog/1536x0/https://ipfs.busy.org/ipfs/QmYThjscfo3qoPmembVvGsed15tHQU3Y1q4eWsNh4AV9UJ 2x" /><br /> <br /> <ol> <li><p dir="auto">This class defines a member which is a method named <code>getName. <li><p dir="auto">Create a closure that will print an argument as <code>it and then join with the other undefined member. If we immediately execute this closure, then an error will occur because the <code>name is completely undefined. <li><p dir="auto">We delegate an object to this closure by passing it a new instance of the <code>Any class and then give a string to the constructor. This technique is called <em>Named argument constructor one of the features provided by Groovy and we'll not discuss it in this tutorial. <li><p dir="auto">There is no error. Because we have delegated an object that has defined a <code>name() method. <p dir="auto">But instead of defining the <code>getName() method, should it define the <code>name() one? <p dir="auto">Here <code>myName is a property of <code>Any and its getter is <code>getName. Then in Groovy, the getter can be invoked in two ways, as <code>.getName() or just <code>.name. <p dir="auto">Even so about the setter, such as a property of the delegate at the closure which can be invoked as <code>.setDelegate(object) or <code>.delegate = object as well.<br /> <br /> <p dir="auto">Closure has a generic which is an abstract type of a value that will be returned by executing a closure. It can be executed like a function in general, but actually the <code>call method is implicitly invoked. Sometimes we have to call him explicitly to avoid ambiguity, like the following example <pre><code>class C { static def isPositive = { it > 0 } static def isPositive(def number) { throw new UnsupportedOperationException() } static def test(def value) { isPositive(value) // (1) } } println C.test(1) <ol> <li>We will get an exceptions with statement like this. But by changing it to <code>isPositive.call(value), then it is considered as a closure rather than a function.<br /> <br /> <h2>Lexical Scope <code>this and <code>owner <p dir="auto">If a function can't refer to any class member (except the static ones) or we can define it as does not have a lexical scope, then a method has a lexical scope of <code>this which references to an enclosing class. Then closures other than having <code>this also have a lexical scope of <code>owner and <code>delegate. <p dir="auto">If <code>this corresponds to an enclosing class, then <code>owner corresponds to the enclosing of either a class or a closure where it is defined. While <code>delegate as we know, it corresponds to the delegated object, so we don't need to discuss about it in more detail. <p dir="auto">How could it be?<br /> Yes, Exactly! Because a closure can be defined in another closure while a function or method cannot. <pre><code>class Outer { class Inner { def takeOwner() { ({ getOwner() }) // (1) } Closure 'Take a Nested closure'() { ({ // (2) ({ owner })() // (3) }) } } void test() { def inner = new Inner() // (4) assert inner.takeOwner()() == inner // (5) Closure nested = inner.'Take a Nested closure'() // (6) assert nested() == nested // (7) assert ({ owner })() == this // (8) println 'Successful!' // (9) } } new Outer().test() <p dir="auto"><img src="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmPNWqWFG98URTBfGGABbpVBA9RRr7pXFkV21YdqmGdpJ3" alt="Untitled 18.png" srcset="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmPNWqWFG98URTBfGGABbpVBA9RRr7pXFkV21YdqmGdpJ3 1x, https://images.hive.blog/1536x0/https://ipfs.busy.org/ipfs/QmPNWqWFG98URTBfGGABbpVBA9RRr7pXFkV21YdqmGdpJ3 2x" /><br /> <br /> <ol> <li>The method <code>takeOwner returns a closure which returns an object of the <code>owner.<br /> This equivalent to: <pre><code>def takeOwner() { return { getOwner() } } So, if you pass a closure as a return value without first storing it to a variable then you have to surround it with parentheses. <li>The <em>outer closure. <li>The <em>inner closure and immediately execute it. Here we can clearly see that a closure can be defined within another one like the top-level container, such as class or interface.<br /> This equivalent to: <pre><code>Closure 'Take a Nested closure'() { return { def innerClosure = { owner } return innerClosure.call() } } <li>The instance of <code>Inner class <li>As we can see, the <em>stand-alone closure or in other words a closure that is not inside another one, the <code>owner's characteristic will be the same as <code>this, which is returning an instance of enclosing class, i.e. <code>Inner.<br /> This equivalent to: <pre><code>def closure = inner.takeOwner() assert closure() == inner <li>Execute the string named method and an instance of the outer closure. <li>Execute the outer closure which will immediately execute the inner one which finally returns an object of the <code>owner. Because <code>owner is executed in the context of an inner closure then it returns an instance of enclosing closure which is the outer one. <li>This closure stands alone in the <code>Outer class context, it will automatically become <code>this and return an instance of <code>Outer class. <li>Because all assertions in each condition are correct, "<strong>Successful!" will be printed.<br /> <br /> <h2>Finally <p dir="auto">I will express my gratitude in a different way,<br /> <img src="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmSBh7LP197oJRV6XFBGRt6W5mKhTRJ9gNViRU3Rr5bsjM" alt="Untitled 19.png" srcset="https://images.hive.blog/768x0/https://ipfs.busy.org/ipfs/QmSBh7LP197oJRV6XFBGRt6W5mKhTRJ9gNViRU3Rr5bsjM 1x, https://images.hive.blog/1536x0/https://ipfs.busy.org/ipfs/QmSBh7LP197oJRV6XFBGRt6W5mKhTRJ9gNViRU3Rr5bsjM 2x" /> <p dir="auto"><br /> <h4>Curriculum <ul> <li><a href="https://steemit.com/utopian-io/@murez-nst/mureztutorial013" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Groovy - Build Custom Syntax Using Groovy Domain-Specific Language and Perform Delegation <h4>Proof of Work Done <p dir="auto"><span><a href="https://github.com/murez-nst/JVM-Based/tree/master/Groovy/Lombok" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://github.com/murez-nst/JVM-Based/tree/master/Groovy/Lombok <h5>Reference <ul> <li>Groovy logo — <a href="https://upload.wikimedia.org/wikipedia/commons/3/36/Groovy-logo.svg" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://upload.wikimedia.org/wikipedia/commons/3/36/Groovy-logo.svg
Sort:  

Thank you for your contribution.

  • The name of the classes isn't perceptible. Class A or B doesn't look good.

Looking forward to your upcoming tutorials.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.



Chat with us on Discord.
[utopian-moderator]Need help? Write a ticket on https://support.utopian.io/.

Thank you for your review, @portugalcoin!

So far this week you've reviewed 8 contributions. Keep up the good work!


Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!Hey @murez-nst

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Hi @murez-nst! We are @steem-ua, a new Steem dApp, computing UserAuthority for all accounts on Steem. We are currently in test modus upvoting quality Utopian-io contributions! Nice work!

Congratulations @murez-nst! You received a personal award!

1 Year on Steemit

Click here to view your Board of Honor

Support SteemitBoard's project! Vote for its witness and get one more award!

Congratulations @murez-nst! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!