Click here to Skip to main content
Click here to Skip to main content

Tagged as

Anonymous Delegates In COBOL for .NET

, 14 Jan 2010 CC (ASA 2.5)
Rate this:
Please Sign up or sign in to vote.
Working with modern technologies like WPF is made a whole lot easier if you have nice features like anonymous deletegates, here is how use them in COBOL.

Introduction

This is just a quick article showing how to implement anonymous delegates in Micro Focus COBOL for .NET.

Guy Lewis Steele, Jr.. "Debunking the 'Expensive Procedure Call' Myth, or, Procedure Call Implementations Considered Harmful, or, Lambda: The Ultimate GOTO". MIT AI Lab. AI Lab Memo AIM-443. October 1977

The above paper discusses how anonymous functions can provide a very flexible and powerful way of manipulating control flow in a program without the ugly and dangerous imperative notion of GOTO. COBOL has its own notion of GOTO, the PERFORM verb. However, PERFORM in modern COBOL can be very 'nice' and not have any GOTO like behaviour; for example:

                perform varying counter from 1 by 1 until counter > 100
                    set str to String::"Format"("Hello World {0}" counter)
                    set anAction to new type "System.Action"
                    (
                       delegate
                           add 1 to delCounter
                           invoke type
 "System.Console"::"WriteLine"(String::"Format"("{0} -> {1}," 
 type "System.Threading.Thread"::"CurrentThread"::"ManagedThreadId" delCounter))
                       end-delegate
                    )
                    invoke actions::"Add"(anAction)
                end-perform  

Nevertheless, it would also be very cool indeed to have lambda functions (from Lambda calculus) in COBOL. The above example is a bit of a cheat, because it gives a hint on how to do exactly that in Micro Focus managed COBOL. A delegate is a way of referencing a method dynamically, i.e., the method it references is chosen at runtime, not compile time. This makes a delegate somewhat like a lambda. However, when a delegate is anonymous it has no method name associated with it, only code. An anonymous delegate is a lambda. The above block of COBOL is creating lambda functions.

Moving From Lambda To Closure

In reality, the anonymous delegates in MF COBOL are actually closures. It is a common misconception that all lambdas are closures. For a lambda to be a closure it must enclose state from where it is created. Anonymous delegates in MF COBOL enclose the local storage of the method in which they are created.

COBOL And Generics

MF managed COBOL works out the box with generics. Generics are just like templates in C++ and represent a compile time polymorphism mechanism. Thus, collections can be strongly typed (for example). This has the benefit of more secure coding practices and potentially faster runtimes:

01 actions       type "System.Collections.Generic.List"[type "System.Action"]. 

The above local storage declaration (variable definition) shows MF COBOL.net generics syntax. The square bracketed type at the end of the declaration causes the compiler to define the List collection as being a list of System.Action objects. I am using System.Action as it is a general purpose delegate class the constructor of which acts as a very good way of creating general purpose anonymous delegates in COBOL.net.

Iterating over Collections

        perform varying anAction through actions
            set aWorker to new "AdvancedFeatures.Worker"(anAction)
            set thread-start to new "System.Threading.ThreadStart"(aWorker::"Work"())
            set aThread to new Type "System.Threading.Thread"(thread-start)
            invoke aThread::"Start"()
        end-perform         

This piece of code uses perform to iterate over the generic list we created earlier. It does this using the 'though' keyword. This perform looping construct also launches new threads. Those threads will then use the delegates which we created earlier.

Putting It All Together

So here is a throw away example program which uses anonymous delegates as closures and multi-threading (the .NET way) and generics with iterators. Please note that there is a full threading syntax build into MF COBOL as well; so if you do not want to use the .NET class library, you can use the MF COBOL syntax. I might blog on that another time.

      $Set SourceFormat "FREE".
       program-id. Program1 as "AdvancedFeatures.Program1".

       environment division.
       configuration section.
       repository.
       
       data division.
       working-storage section.
        01 manager type "AdvancedFeatures.Manager".
       procedure division.
            set manager to new type "AdvancedFeatures.Manager"
            invoke manager::"RunWorkflow"()
            goback.
            
       end program Program1.

       class-id. Manager as "AdvancedFeatures.Manager".
        object.
        method-id "RunWorkflow" public.
            local-storage section.
            01 thread-start  type "System.Threading.ThreadStart".
            01 aThread       type "System.Threading.Thread".
            01 anAction      type "System.Action".
            01 aWorker       type "AdvancedFeatures.Worker".
            01 actions       type "System.Collections.Generic.List"[type "System.Action"].
            01 str           string.
            01 counter       binary-long.
            01 delCounter    binary-long.
            procedure division.
                move 0 to delCounter
                set actions to 
                    new "System.Collections.Generic.List"[type "System.Action"]
                perform varying counter from 1 by 1 until counter > 100
                    set str to String::"Format"("Hello World {0}" counter)
                    set anAction to new type "System.Action"
                    (
                       delegate
                           add 1 to delCounter
                           invoke type
                             "System.Console"::"WriteLine"
 (
 String::"Format"
  (
    "{0} -> {1}," type "System.Threading.Thread"::
		"CurrentThread"::"ManagedThreadId" delCounter
  )
 )
                       end-delegate
                    )
                    invoke actions::"Add"(anAction)
                end-perform
            
                perform varying anAction through actions
                    set aWorker to new "AdvancedFeatures.Worker"(anAction)
                    set thread-start to 
                        new "System.Threading.ThreadStart"(aWorker::"Work"())
                    set aThread to 
                        new Type "System.Threading.Thread"(thread-start)
                    invoke aThread::"Start"()
                end-perform
                goback.
        end method "RunWorkflow".
        end object.
       end class Manager.

       class-id. Worker as "AdvancedFeatures.Worker".

        object.
        working-storage section.
            77 aDelegate type "System.Delegate".        
        
        method-id new public.
            procedure division using by value toCall as type "System.Action".
            set aDelegate to toCall.
        end method new.
        
        method-id "Work" public.               
            procedure division.
          
                invoke aDelegate::"DynamicInvoke"(null)

        end method "Work".
        
        end object.
       end class Worker.  

History

  • 14th January, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License

Share

About the Author

alex turner
Web Developer
United Kingdom United Kingdom
I am now a Software Systems Developer - Senior Principal at Micro Focus Plc. I am honoured to work in a team developing new compiler and runtime technology for Micro Focus.

My past includes a Ph.D. in computational quantum mechanics, software consultancy and several/various software development and architecture positions.

For more - see

blog: http://nerds-central.blogspot.com

twitter: http://twitter.com/alexturner

Comments and Discussions

 
QuestionConverting C# anonymous delegates to COBOL Pinmemberdmccollim4-Jun-10 12:11 
AnswerRe: Converting C# anonymous delegates to COBOL Pinmemberalex turner4-Jun-10 15:42 
AnswerRe: Converting C# anonymous delegates to COBOL Pinmemberalex turner7-Jun-10 5:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150414.1 | Last Updated 14 Jan 2010
Article Copyright 2010 by alex turner
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid