Leveling Up: RPG and JavaScript Functions

Part - 2:Comparing Functions in JavaScript with Subprocedures in RPGLE

Welcome back to our enlightening series where we draw parallels between RPGLE and JavaScript. In our previous entry, we delved deep into a comparison of data types between the two languages. In this edition, we'll be exploring how JavaScript functions can be juxtaposed with RPGLE subprocedures. Let's embark on this interesting journey and see how the two match and differ!

Introduction:

JavaScript and RPGLE operate on different paradigms but share similarities that can help RPG developers adapt swiftly to JavaScript. Today, we’ll scrutinize JavaScript functions and RPGLE subprocedures.

JavaScript functions, like RPGLE subprocedures, are reusable blocks of code that perform a specific task and can be called multiple times within a program, allowing for modular and organized code. Let’s journey through the key aspects of each.

Definition:

JavaScript Functions: In JavaScript, a function is defined using the function keyword, followed by a name, parameters within parentheses (), and the code block within curly braces {}.

function greet(name) {
    console.log("Hello, " + name + "!");
}

RPGLE Subprocedures: In RPGLE, subprocedures are defined using the DCL-PROC and END-PROC keywords, with parameters declared within the procedure.

dcl-proc greet;
    dcl-pi *n;
        name varchar(50);
    end-pi;
    dsply ('Hello, ' + name + '!');
end-proc;

Calling:

JavaScript: Functions are invoked by using their name followed by parentheses, containing any arguments.

greet('John'); // Outputs: Hello, John!

RPGLE: Subprocedures are called by their name with parameters, if any, passed within parentheses.

greet('John'); // Displays: Hello, John!

Parameters and Return Types:

JavaScript: Functions can have parameters, and the return type can be any valid JavaScript data type, including undefined.

function add(a, b) {
    return a + b;
}

RPGLE: Parameters in subprocedures are declared using the DCL-PI and END-PI keywords. The return type is explicitly declared.

dcl-proc add;
    dcl-pi *n packed(10);
        a packed(10);
        b packed(10);
    end-pi;
    return a + b;
end-proc;

Scope:

JavaScript: JavaScript functions have access to the variables in their scope, their parent (outer) scope, and any global variables.

let globalVar = 'Global';

function showScope() {
    let localVar = 'Local';
    console.log(globalVar); // Accessible
    console.log(localVar);  // Accessible
}

RPGLE: In RPGLE, variables in the main procedure can be accessed by subprocedures, but local variables within subprocedures are not accessible outside them.

dcl-s globalVar varchar(50) inz('Global');

dcl-proc showScope;
    dcl-s localVar varchar(50) inz('Local');
    dsply globalVar; // Accessible
    dsply localVar;  // Accessible within subprocedure
end-proc;

First-Class Functions in JavaScript:

JavaScript functions are first-class citizens, meaning they can be:

  1. Passed as an Argument to other functions:

    Here greet fucntion is passed as an argument to the runFunction . runFunction returns the passed function, greet in this case with value = 'John' .

function runFunction(fn, value) {
    return fn(value);
}

function greet(name) {
    return "Hello, " + name + "!";
}

console.log(runFunction(greet, 'John')); // Outputs: Hello, John!
  1. Returned from other functions:
function multiplier(factor) {
    return function (number) {
        return number * factor;
    }
}

let twice = multiplier(2);
console.log(twice(5)); // Outputs: 10
  1. Assigned as a Value to a Variable:
const greet = function(name) {
    return "Hello, " + name + "!";
}
console.log(greet('John')); // Outputs: Hello, John!

Closure:

JavaScript: JavaScript functions form closures, allowing them to capture and remember their surrounding scope and access variables from that scope even after it has finished executing. In the below code the innerFunction is returned to the caller and still the innerFunction is aware of its parent functions variable.
MDN Doc - Closure

function outerFunction() {
    let outerVar = 'I am from outer!';
    function innerFunction() {
        console.log(outerVar); // Accessible due to closure
    }
    return innerFunction;
}

const innerFunc = outerFunction();
innerFunc(); // Outputs: I am from outer!

Below is a sample JavaScript module that includes the various types of functions we discussed:

Let’s create a module named myModule.js:

// Regular Function Definition
function greet(name) {
    console.log("Hello, " + name + "!");
}

// Function that can be Passed as an Argument
function runFunction(fn, value) {
    return fn(value);
}

// Function that Returns another Function
function multiplier(factor) {
    return function (number) {
        return number * factor;
    }
}

// Function Assigned as a Value to a Variable
const farewell = function(name) {
    console.log("Goodbye, " + name + "!");
}

// Function Stored in Data Structure
const operations = {
    add: function(a, b) {
        return a + b;
    },
    subtract: function(a, b) {
        return a - b;
    }
}

// Exporting the functions to be accessible in other modules
export {
    greet,
    runFunction,
    multiplier,
    farewell,
    operations
}

Usage in Another File

Now, let's see how we can import and use this module in another JavaScript file, say app.js:

// Importing functions from myModule
import { greet, runFunction, multiplier, farewell, operations } from './myModule.js';

// Using the Imported Functions
greet('John'); // Outputs: Hello, John!

// Pass a Function as an Argument
const greeting = runFunction(greet, 'Jane'); // Outputs: Hello, Jane!

// Function that Returns another Function
const double = multiplier(2);
console.log(double(5)); // Outputs: 10

// Function Assigned as a Value to a Variable
farewell('John'); // Outputs: Goodbye, John!

// Function Stored in Data Structure
console.log(operations.add(2, 3)); // Outputs: 5
console.log(operations.subtract(5, 2)); // Outputs: 3

In this example, myModule.js encompasses various function types, including regular functions, first-class functions, and functions stored in a data structure. They are then exported for usage in other modules, showcasing modularity and reusability in JavaScript.

To run these JavaScript files from the local system one should first download Nodejs and then use Nodejs to execute app.js. Alternatively, the console of a browser is a great tool for executing js functionality.

Conclusion:

JavaScript functions and RPGLE subprocedures are pivotal elements in their respective programming paradigms, playing a crucial role in structuring the code base in a modular and reusable way. While they stem from different programming paradigms and syntax structures, understanding the similarities and differences enables RPG developers to transition seamlessly into the world of JavaScript.

Stay tuned for the next part of our series, where we’ll explore more intricate concepts and bridge the conceptual gaps between RPGLE and JavaScript, making your leveling-up journey enjoyable and insightful!

Did you find this article valuable?

Support Gajender Tyagi by becoming a sponsor. Any amount is appreciated!