Order-independent function/constant declarations?
Posted: 12 Mar 2023, 18:03
I've been loving v2 since it went mainstream (thanks @lexikos)! As I've been converting code, I've been thinking a lot about AHK and comparisons with other languages in which I regularly write, especially with regard to first-class functions and definitions. It seems to me that a weakness of a lot of languages is the inability to declare a derived (but otherwise constant) function without being dependent on order of execution.
For example, in AHK, the following global scope lines could be declared in any order:
But as soon as one starts employing derived functions, things quickly become order-dependent:
If there were a way for these definitions to be labeled constants (maybe signified by const or def or val or some other keyword?) it seems like the interpreter could make sense of them in any order. With formal function definitions (like my first example), aren't these definitions all located during a first pass? I don't know the interpreter workings well, so I could be wrong in this impression. Anyhow, could some constant keyword prefix allow these types of immutable definitions to be identified in a first pass?
It seems like this might also be generalizable to non-functional constants, especially helpful for those that cross-reference but are declared in an otherwise alphabetic order (admittedly trivial example, but this ordering wouldn't work for obvious reasons):
Could some prefix allow these to be located in the first pass and therefore not order-dependent?
I know these examples are trivial. In my real libraries it's a little more complicated, but I've tried to use .Bind and function wrapping/currying wherever possible in terse/DRY functional style. However, this often makes editing the code a pain, since (1) derived functions can't generally be listed in alphabetical order, (2) inserting new functions often involves repositioning definitions in the right place, so all dependencies are physically above their descendants.
There are definitely places where I use partial/bound functions or variables that are indeed temporary or mutable and *should* be order dependent. It's just there are a whole lot of cases where it's about cross-referenced global constants or functions that do not change within a library.
Is this something you have considered or would consider? Many thanks for all the hard work! No matter what, AHK is still my favorite language for automation and quick prototyping.
For example, in AHK, the following global scope lines could be declared in any order:
Code: Select all
isDiv(x,y) => Mod(x,y) == 0 ;is divisible by
isEven(x) =>isDiv(x,2) ;is even number
isOdd(x) => !isEven(x) ;is odd number
Code: Select all
isDiv(x,y) => Mod(x,y) == 0 ;is divisible by
neg(f) => p* => !f(p*) ;negates truthiness of f result
;the following must be defined in this order, and before they are used
isEven := isDiv.Bind(,2)
isOdd := neg(isEven)
It seems like this might also be generalizable to non-functional constants, especially helpful for those that cross-reference but are declared in an otherwise alphabetic order (admittedly trivial example, but this ordering wouldn't work for obvious reasons):
Code: Select all
;alphabetic list of global constants
lb := [rl, lf, rt] ;list of possible line breaks (out of order)
lf := "`n" ;linefeed
pi := 3.14159 ; :)
rl := rt lf ;return-linefeed (out of order)
rt := "`r" ;return
I know these examples are trivial. In my real libraries it's a little more complicated, but I've tried to use .Bind and function wrapping/currying wherever possible in terse/DRY functional style. However, this often makes editing the code a pain, since (1) derived functions can't generally be listed in alphabetical order, (2) inserting new functions often involves repositioning definitions in the right place, so all dependencies are physically above their descendants.
There are definitely places where I use partial/bound functions or variables that are indeed temporary or mutable and *should* be order dependent. It's just there are a whole lot of cases where it's about cross-referenced global constants or functions that do not change within a library.
Is this something you have considered or would consider? Many thanks for all the hard work! No matter what, AHK is still my favorite language for automation and quick prototyping.