JMPL Devlog #8
A Few Nice Additions
August 26th 2025
Tags:
C
JMPL
Programming Language
This weeks update focuses on a few small but powerful additions and changes to JMPL.
What's changed?
The first change is a nice overhaul to the iterator object. Originally called the 'SetIterator', iterators are a backend object that JMPL uses to iterate through an object. Iterators are a very useful feature in JMPL, being used in for loops, set-builder notation and quantifiers. Before this week's update, they could only be used on sets, but now they can be used on any iterable object. This means that not only can sets be iterated, but tuples and strings can too! Here are a few examples:
// Set-builder notation
println({x^2 | x ∈ {1 ... 5}}) // {1, 4, 9, 16, 25}
println({x | x ∈ "Hello"}) // {'H', 'e', 'l', 'o'}
println({2 * x | x ∈ (1 ... 5)}) // {2, 4, 6, 8, 10}
// For loops
for x ∈ {1 ... 5} | x mod 2 ≠ 0 do print(x + " ") // 1 3 5
for x ∈ "Hello" do print(x + " ") // H e l l o
// Quantifiers
∀x ∈ (1 ... 5) | x mod 2 ≠ 0 // false
∃x ∈ "Hello" | x == 'e' // true
This update makes tuples and strings a lot easier to work with. However, there are still a few features I want to change to support these objects too. This includes making a 'tuple-builder notation' and making the '∈' operator support strings and tuples too.
The next change is one to indices and the addition of slicing. When a tuple or string is indexed, a negative index can now be used to get an item relative to the end of the object.
let t = (1, 2, 3)
println(t[-1]) // 3
This works the same way with strings. The new range of the index is [-size, size) where size is the number of items in the string or tuple. This index range can also be used with slicing, a way to get a portion of an ordered object.
let u = (1, 2, 3, 4, 5)
println(t[1 ... 3]) // (2, 3, 4)
let str = "Hello"
println(t[... 2]) // "Hel"
println(t[3 ...]) // "lo"
The syntax for this is:
obj[x ... y]
Where x and y are both inclusive indices and obj is a string or a tuple. Either x and y can be omitted or replaced with 'null'. When x is omitted it means the slice starts at the first element and when y is omitted it means the slice ends at the last element. Both indices are inclusive so I may add an alternative syntax where y would be exclusive.
The final change for this update (excluding bug fixes and optimisations) is anonymous functions. Defined similar to regular functions, anonymous functions are very especially useful as parameters to higher order functions. The syntax is:
func (parameters) -> expression
This syntax can only be used where an expression is expected, so not at the start of a new line. This syntax uses the maps to symbol ('->') to distinguish it from normal function notation and to look better when directly stored as a variable.
func map(S, f) = {f(x) | x ∈ S}
println(map({1 ... 5}, func (x) -> x^2)) // {1, 4, 9, 16, 25}
What's next?
As the start of the university year approaches, there will be less regular updates to JMPL. Right now I am working on a module system to include functions from other files and new natives which will probably be the last major features for a while. Other than that I plan on lots of optimisations and bug fixes, as well as cleaning up the code so it is easier to read and make additions for!