Tuesday, 11 February 2025

Safe Type casting in Swift (Data Conversion)


When working with different types of Data in Swift, it's important to understand the best practices to convert data from one form to another. Let's take a look at this using below example: 

  1. Conversion between Int and String

When we type case an Int to a String using String(integer1), the new type is an optional type of string which can be little daunting to work with. Swift provides us with safe ways to convert Int to an String.

  • Using Optional Binding - This way, the print statement is only executed when string1 has a valid String value.
let int1 = 55
if let string1 = String(int1) {
   print(string1)  
}
  • Using nil coalescing - This method will assign a default value to the new variable when swift can not convert to a valid value:
let string2 = String(int1) ?? "N/A"

    2. Conversion between Int and Hexadecimal (Base 6 or Base 16)

let str3 = String(125, radix: 16) à This will return 7d

We can also ask swift to return the value in all UPPERCASE.

Str3 = String(125, radix: 16, uppercase: true) à This will return 7D

Swift can also help us convert Hexadecimal base 16/6 to an Integer.

let int2 = Int(“7D”, radix: 16)

Sunday, 19 January 2025

Pattern Matching in Swift

When it comes to pattern matching, Swift provides us with some great tools to validate and write clean code that is also very easy to understand. Consider below example: 

let name: String? = "Alex"

let age: Int? = 35

For matching optional data, we can use .some match with properties that hold a value (something that is not nil), and .none to match with properties without any data (== nil). Here is how a simple switch statement would look like: 

switch (name, age) {

    case let(.some(matchedName), .some(matchedAge)):

    print("Hello \(matchedName)")

    

    case let(.some(name), .none):

    print("Hello \(name), How old are you?")

    

    default:

    print("Who are you?")

}

Consider another property which is an array data that may contain some nil values:

let data: [Any?] = [1, "Hello", true, nil, "Ted"]

We can use a for loop to iterate and process data elements that have some value using .some keyword:

for case let .some(value) in data {

    print(value)

}


This will ensure we only pick and process non-nill values. 



Monday, 23 December 2024

How to Use QWVRCSTK to Retrieve the Entire Call Stack in an RPG Program

Recently, I was assigned a task at work that involved modifying a complex functionality: instead of having the actual program handle file updates, the responsibility was shifted to the main calling program. While this approach is generally not recommended due to its complexity, it makes sense in certain situations. For example, when multiple processes call a single reusable program to create or update data in a table, it’s useful to have the main program identified in the audit log. This helps provide a clearer picture of the source of the data.


Breakdown of the Call Stack:

Let’s break down the situation with an example to illustrate this better:


Program X Call Stack

Scenario: Program X Call Stack

In the example, Program X is being invoked from various sources. However, the audit table (Table 1) always shows Program X in the "Create/Update Audit" stamp, regardless of which source actually triggered the action. Ideally, it would be more informative to also record the actual source program — whether it’s Program 1, Program A, or Program A1 — alongside Program X. Without this information, it becomes challenging to determine which specific process was responsible for writing the data to the table.

Leveraging IBMi’s QWVRCSTK API

On IBMi systems, there is a helpful API called QWVRCSTK that retrieves the complete call stack, which can be used to solve this issue. This API allows us to trace the entire sequence of program calls, helping to pinpoint the exact source of the operation.

To get started, we define the procedure that will utilize this API...

 * External Procedure                                         
D QWVRCSTK        PR                  ExtPgm('QWVRCSTK')       
D ReceiverVar                 2000A                            
D ReceiverLen                   10I 0                          
D Format                         8A                            
D JobId                         56A                            
D FmtJobID                       8A                            
D ErrorCode                    256A                            

Thursday, 15 September 2016