Hold my beer, I can do that in one line of code

AL is not an object-oriented language, but we do have pieces that behave like objects. In this video, I show how we can use that to make great one-liners. Check out the video:

https://youtu.be/bSjh_B1ibRo

In this video, Erik demonstrates how AL’s evolving syntax allows you to chain method calls on text variables, enabling you to accomplish in a single line what traditionally required multiple lines of classic AL (or C/AL) code. He walks through the progression from old-school string manipulation to a clean, object-oriented one-liner using .Split() and .Get() method chaining.

The Problem: Extracting a Value from a String

Erik’s starting point is a common text manipulation task. Given a string like 'Text[250]', the goal is to extract the number 250 from between the square brackets. This is the kind of string you’d encounter when working with field type definitions in Business Central — where a field’s type and length are expressed in a format like Text[250] or Code[20].

The Classic Approach: StrPos and CopyStr

If you’ve been working with NAV or Business Central for a long time, the traditional approach looks completely normal. You find the positions of the opening and closing brackets, then use CopyStr to extract the substring between them:

T := 'Text[250]';
P1 := StrPos(T, '[');
P2 := StrPos(T, ']');
Output := CopyStr(T, P1 + 1, P2 - P1 - 1);
Message('Result %1', Output);

This works perfectly well and has some advantages — it’s step-by-step, so you can check whether P1 is zero (meaning the bracket wasn’t found) before continuing. You won’t accidentally pass a negative value to CopyStr. It’s reliable and clear.

Erik also mentions regex as another option but notes it might be overkill for a simple extraction like this. (He has a separate video on regex in AL if you’re interested.)

AL’s Text Type as an Object

Here’s where things get interesting. AL is not an object-oriented language — its foundation is Pascal, as Erik has discussed many times. But over the years, the language has evolved significantly. One of the more recent additions is that the Text type has become an object. This means you can call methods on text variables using dot notation.

When you have a Text variable T, you can type T. and see available methods like Split(), Contains(), Replace(), and more. However, Erik points out an important limitation: this only works on text variables, not on string literals. You can’t write 'Text[250]'.Split('[') directly — the AL compiler doesn’t support that kind of inline type casting.

The Step-by-Step Object-Oriented Approach

Before jumping to the one-liner, Erik builds up to it methodically. Using the Split() method on the text variable, you can break the string into a list:

T := 'Text[250]';
L1 := T.Split('[');
X1 := L1.Get(2);
L2 := X1.Split(']');
Output := L2.Get(1);
Message('Result %1', Output);

Here’s what’s happening at each step:

  1. T.Split('[') splits 'Text[250]' on the opening bracket, producing a list with two elements: 'Text' and '250]'.
  2. L1.Get(2) retrieves the second element: '250]'.
  3. X1.Split(']') splits '250]' on the closing bracket, producing a list with '250' and an empty string.
  4. L2.Get(1) retrieves the first element: '250'.

Erik walks through this with the debugger, confirming the intermediate values at each step — L1 contains the expected split results, X1 holds '250]', and the final output is '250'.

The One-Liner: Method Chaining in AL

The key insight is that all of these intermediate types — Text, List of [Text] — are objects with their own methods. Since Split() returns a List of [Text] (which is also an object), and Get() returns a Text (which is also an object), you can chain them all together:

Output := T.Split('[').Get(2).Split(']').Get(1);
Message('Result %1', Output);

Split, get, split, get — and you have your 250 in one line of code. For anyone coming from C#, JavaScript, Java, or similar languages, this feels completely natural. But for those from the old NAV world, this is new and perhaps a bit exotic.

The Complete Source Code

Here’s the full page extension showing both approaches (with the classic approach commented out):

pageextension 50100 CustomerListExt extends "Customer List"
{
    trigger OnOpenPage()
    var
        T: Text;
        P1: Integer;
        P2: Integer;
        Output: Text;
        X1, X2, X3 : Text;
        L1, L2 : List of [Text];
    begin
        T := 'Text[250]';
        // Classic approach:
        // P1 := StrPos(T, '[');
        // P2 := StrPos(T, ']');
        // Output := CopyStr(T, P1 + 1, P2 - P1 - 1);

        // Step-by-step object approach:
        // L1 := T.Split('[');
        // X1 := L1.Get(2);
        // L2 := X1.Split(']');
        // Output := L2.Get(1);

        // One-liner:
        Output := T.Split('[').Get(2).Split(']').Get(1);
        Message('Result %1', Output);
    end;
}

A Word of Caution

Erik is careful to point out that this one-liner will only work when you know the brackets are present in the text. If the opening bracket isn’t found, the Split() won’t produce a second element, and Get(2) will throw an error — “invalid index was passed to a list.” The classic approach with StrPos gives you the opportunity to check for zero return values and handle the error gracefully. With the one-liner, you’re trading error handling for elegance.

Which Types Support Dot Notation?

Erik demonstrates that this object-oriented dot notation doesn’t work on all AL data types. He tries it on several:

  • Text — ✅ supports dot notation with methods like Split(), Contains(), etc.
  • Decimal — ❌ no methods available
  • Code — ❌ no methods available
  • Date — ❌ no methods available
  • List — ✅ supports dot notation (newer data type)
  • Dictionary — ✅ supports dot notation (newer data type)

Of the classic data types, Text is the only one that has been “upgraded” to support object-oriented syntax. The newer data types like List and Dictionary were designed with this syntax from the start.

AL Is Not Pascal

Erik makes an important point about AL’s identity. While AL’s roots are in Pascal — the if statement syntax, procedure declarations, case statements, and so on are all Pascal-ish — AL has evolved into its own language. When someone says “you can’t do that in Pascal,” Erik’s response is simple: “I’m not programming in Pascal. I’m programming in AL.” The language continues to evolve, and features like method chaining on text variables are part of that evolution.

Conclusion

This video showcases a small but powerful evolution in AL’s syntax. The ability to chain .Split() and .Get() calls on text variables brings a more modern, fluent programming style to Business Central development. While the classic StrPos/CopyStr approach remains valid and offers better error handling, the one-liner approach is elegant and efficient when you’re confident about your data’s format. As AL continues to evolve beyond its Pascal roots, expect to see more object-oriented capabilities like this making their way into the language.