Functional Basic Code
Status: Beta
Brought to you by:
non_apparent
FunctionalBasic
Introduction
FunctionalBasic is a library for Visual Basic 6.0 that provides the
higher-order functions map, filter, fold(l/r), compose and bind in
addition to anonymous 'lambda' functions.
It can be used to concisely express operations on list types (arrays,
ListBoxes, ComboBoxes and Collections).
It provides an interface (IFunction) that can be used if it is difficult
to express the functionality you require in terms of lambda, compose and
bind.
Unfortunately it only supports functions with up to 9 parameters, but
that should be enough for most purposes.
Map
Map takes a list type and a function type and returns a new list where
each element corresponds to the result of applying the function to each
element in the original list.
Map can be called with a string as the list in which case it returns a
new string where the function was applied to each character in turn.
In pseudo-code:
Function Map(List() As T, Func As T(T)) As T()
For Each Element In List
NewList.Add Func(Element)
Map = NewList
End Function
Filter
Filter takes a list type and a function type and returns a new list
containing only the elements where the function returned True when
applied to them.
Filter can be called with a string as the list in which case it returns
a new string containing only the characters for which the function
returned True.
In pseudo-code:
Function Filter(List() As T, Func As Bool(T)) As T()
For Each Element In List
If Func(Element)
NewList.Add Element
Filter = NewList
End Function
Note that Filter is already used as a function name in VB6 so you must
either use HigherOrder.Filter or its alias RemoveIf.
Foldl/r
Foldl takes a list type and a function type, and optionally an initial
value and returns the value obtained by applying the function to each
pair of elements from left to right. If an initial value if specified
it is treated as the leftmost element of the list.
Foldr functions similarly but it applies the function from right to left
and the initial value is treated as the rightmost element of the list.
In pseudo-code:
Function Foldl(List() As T, Func As T(T, T), Optional Initial As T) As T
If Initial Then
Initial = Func(Initial, List(0))
Else
Initial = List(0)
For Each Element In List(1 ..)
Initial = Func(Initial, Element)
Foldl = Initial
End Function
Compose
Compose takes two function types and returns a new function which when
evaluated calls the first function with the result of the second.
In pseudo-code:
Function Compose(F As Any(T), G As T(Any...)) As Any(Any...)
Compose(Params) = F(G(Params)
End Function
Bind
Bind takes a function type and a list of parameters and returns a new
function which calls the function with the new parameters. It also
supports specifying parameters to be supplied when the new function
is called via the Param(1 - 9) syntax.
In pseudo-code:
Function Bind(F As Any(Any...), Params...)
Bind(Params) = F(Params)
End Function
Lambda
Lambda takes a string and returns a new function that evaluates the
expression in the string. The syntax of the expression is as close to
VB6 syntax as possible. (params) => expression where params is a comma
separated list of parameter names and expression is a normal VB6
expression using those parameters.
You may use ' instead of " for string literals inside the expression.
The following VB6 functions are supported inside expressions:
Abs, Asc, Atn, CBool, CDbl, CLng, Chr, CInt, Cos, CSng, CStr, Exp, Fix,
Hex, IIf, InStr, InStrRev, Int, IsArray, IsEmpty, IsNull, IsNumeric,
IsObject, LBound, LCase, Left, Len, Log, LTrim, Mid, Oct, RGB, Right,
Rnd, RTrim, Sgn, Sin, Sqr, String, Tan, Trim, TypeName, UBound, UCase,
Val
Examples
Stripping non-alphabetic characters from a string:
RemoveIf("L33t", _
Lambda("(C) => (C >= 'a' And C <= 'z') Or (C >= 'A' And C <= 'Z')"))
= "Lt"
Building a comma-separated list of names:
Foldl(Array("John", "Steve", "Bruce"), _
Lambda("(N1, N2) => N1 & ', ' & N2"))
= "John, Steve, Bruce"
Rot13 encoding a string:
Map("HELLOURYYB", _
Lambda("(C) => IIf(UCase(C) > 'M', Chr(Asc(C)-13), Chr(Asc(C)+13))"))
= "URYYBHELLO"