patternModerate
Higher Order Functions in VBA, the dirty way
Viewed 0 times
orderthewayhighervbafunctionsdirty
Problem
I have been building a small library of VBA functions. I have a small section with higher order functions that I'd like to share. It uses strings as delegates/function pointers and
This isn't by any means a true implementation; just a quick and dirty implementation without connecting external libraries or creating objects for every function. I haven't found real drawbacks yet.
Application.Run to actually call the functions.This isn't by any means a true implementation; just a quick and dirty implementation without connecting external libraries or creating objects for every function. I haven't found real drawbacks yet.
Application.Run always passes arguments by value, which would be a draw back, but is desirable in all of these implementations. Also not being able to declare lambdas is a buzz-kill.Public Sub Map(ByVal delegate As String, ByRef sequence As Variant)
Dim i As Long
For i = LBound(sequence) To UBound(sequence)
sequence(i) = Application.Run(delegate, sequence(i))
Next i
End Sub
Public Function Mapped(ByVal delegate As String, ByVal sequence As Variant) As Variant
Mapped = sequence
Map delegate, Mapped
End Function
Public Function Fold(ByVal delegate As String, ByVal sequence As Variant, _
ByVal initial_value As Variant) As Variant
Fold = initial_value
Dim el As Variant
For Each el In sequence
Fold = Application.Run(delegate, Fold, el)
Next el
End Function
Public Function Reduce(ByVal delegate As String, ByVal sequence As Variant) As Variant
' Head and Tail return the first element and the rest, respectively.
Reduce = Fold(delegate, Tail(sequence), Head(sequence))
End Function
Public Function Compose(ByVal delegates As Variant, ByVal initial_value As Variant) As Variant
Compose = initial_value
Dim delegate As Variant
For Each delegate In delegates
Compose = Application.Run(delegate, Compose)
Next delegate
End FunctionSolution
Things I like
Things to watch out for
Nitpicks
- This idea.
- You've explicitly declared
ByValandByRef.
- All methods are short, clear, and concise.
Things to watch out for
- All of these functions take variants in as parameters, by necessity. Client code runs the risk of passing in a
sequencethat isn't enumerable. These really need a comment and maybe aVB_Descriptionattribute describing what kind of arguments the functions expect.
- You also may want to consider handling runtime error 438 "Object doesn't support Method" for the functions that use
For Eachloops. There's not much you can do other than return a more meaningful error message though.
- If you change the loop in
Mapto aFor Eachand manually incrementi, all of the functions will be compatible with collections as well as arrays.
Nitpicks
- Underscores have a special meaning. They indicate event procedures. So I would change
initial_valuetoinitialValue.
- While I quickly understood that
elstood forelement, there's no reason not to just spell it out.
Context
StackExchange Code Review Q#60083, answer score: 12
Revisions (0)
No revisions yet.