Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Introduction
Currently AHK is missing a simple way to start iterating from a number other than 1, or to iterate backwards. This pull request adds a function similar to Python's range function.
Range
returns an enumerator that enumerates fromstart
tostop
with optionalstep
, and also supports (semi-)infinite enumerating.Syntax
Range(stop)
=> enumerates from 1...stop withstop
included.Range([start := 1 , stop?, step := 1]
=> enumerates fromstart
tostop
withstep
,stop
is included.Arguments must be of numeric type or omitted, otherwise an error is thrown.
Omitting
stop
but providingstep
(or omitting all parameters) will create a semi-infinite enumerator by settingstop
to MAXLONGLONG when step > 0, or MINLONGLONG when step < 0.RangeEnumerator can be converted into an array with pre-existing syntax:
Array(Range(5)*)
=>[1, 2, 3, 4, 5]
Design choices
Closed interval
Unlike in Python, this implementation of
Range
uses closed interval forstop
. This is because AHK is 1-based, which meansArray(Range(n)*).Length == n
and this makes more intuitive sense. In Pythonrange(0, n)
is more commonly used and also results in length n.INT64 instead of int
This was chosen to be consistent with AHK Integer type sizes and to provide maximal range for
Range
(because the enumerating can start at an arbitrary point). ForRangeEnumerator::mStep
type int would probably suffice, but since it would cause type-casting to INT64 anyway I decided to keep it INT64 also.Tests
Unit tests
Performance tests
Outputs the following in my setup:
The user-defined enumerator that has a more limited functionality is already ~6x slower. Otherwise it's comparable to a simple Loop, with a small win over it when starting with an offset.
Memory tests
Running this for a while doesn't cause increasing memory use in Visual Studio debugger.
Final notes
This implementation chose not to support character enumeration such as
Range('A', 'Z')
, but such functionality may be added later on.Feel free to make any kinds of modifications to this code.