Click here to Skip to main content
15,886,919 members
Articles / .NET

Anonymous Delegates In COBOL for .NET

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
14 Jan 2010CC (ASA 2.5)3 min read 20.3K   1   3
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


Written By
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 Pin
dmccollim4-Jun-10 11:11
dmccollim4-Jun-10 11:11 
AnswerRe: Converting C# anonymous delegates to COBOL Pin
alex turner4-Jun-10 14:42
alex turner4-Jun-10 14:42 
No problem - but not tonight Smile | :)

I'll take a look on Monday if that is OK.

Thanks for the comment - AJ

www.nerds-central.com - welcomes all nerds Smile | :)
AnswerRe: Converting C# anonymous delegates to COBOL Pin
alex turner7-Jun-10 4:28
alex turner7-Jun-10 4:28 

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

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