First stab at Functional Map, Reduce, and Filter in B4J
Lost of testing and error checking to do, but I think this is a decent starting draft:
Lost of testing and error checking to do, but I think this is a decent starting draft:
B4X:
'// ******************* In Main *******************
Sub AppStart (Form1 As Form, Args() As String)
Private n_Count = 0
Private lst_Items As List
Private lst_Results As List
lst_Results.Initialize
'// Map Test
Private lst_Mapped As List
lst_Mapped.Initialize
Private lst_OriginalValues As List
lst_OriginalValues.Initialize
lst_OriginalValues.AddAll( Array As Int( 6, 8, 14, 20, 202, 194 ) )
Private s_Function As String
Private n_Result As Int
s_Function = "PlusOne"
lst_Mapped = mod_Functional.List_Map( "mod_Functional", "PlusOne", lst_OriginalValues )
'// Reduce Tests
lst_Items.Initialize
lst_Items.AddAll( Array As String( "one", "two", "three", "four", "five" ) )
Private s_Items As String
s_Items = ""
n_Count = 0
s_Items = mod_Functional.List_Reduce( "mod_Functional", "Concatdat", lst_Items )
lst_Items.Initialize
lst_Items.AddAll( Array As Int( 1, 2, 3, 4, 5 ) )
Private n_Items As Int
n_Items = mod_Functional.List_Reduce( "mod_Functional", "Plus", lst_Items )
lst_Items.Initialize
lst_Items.AddAll( Array As Int( 1, 7 ) )
Private n_Items As Int
n_Items = mod_Functional.List_Reduce( "mod_Functional", "Plus", lst_Items )
'// Filter Test
lst_Items.Initialize
lst_Items.AddAll( Array As Int( 1, 2, 3, 4, 5 ) )
lst_Results.Initialize
lst_Results = mod_Functional.List_Filter( "mod_Functional", "IsEven", lst_Items )
'...
'...
'...
End sub
Sub PlusOne( n_Int As Int ) As Int
Return n_Int + 1
End Sub
'// ******************* In mod_Functional.bas *******************
Sub List_Map( s_Component As String, s_Function As String, lst As List ) As Object
'// Contains implied assignments, because of the automatic initialization
'// , but the variables mutate only once
Private n_Count As Int
Private lst_Results As List
lst_Results.Initialize
Return List_Map_with_InitialValues( s_Component, s_Function, lst, n_Count, lst_Results )
End Sub
Sub List_Map_with_InitialValues( s_Component As String, s_Function As String, lst As List, n_Count As Int, lst_Results As List ) As List
If lst_Results.IsInitialized == False Then
lst_Results.Initialize
End If
'// If function doesn't exist, return an empty list.
If SubExists( s_Component, s_Function ) == False Then
Return lst_Results
End If
'// If the count is up to the length of the list, then return final result
If n_Count == lst.Size Then
Return lst_Results
Else
Return List_Map_with_InitialValues( s_Component, s_Function, lst, n_Count + 1, AddItemToList( lst_Results, CallSub2( s_Component, s_Function, lst.Get( n_Count ) ) ) )
End If
End Sub
'// There has to be an assignment, so we're isolating it here.
Sub AddItemToList( lst As List, x_Item As Object ) As List
lst.Add( x_Item )
Return lst
End Sub
Sub List_Reduce( s_Component As String, s_Function As String, lst As List ) As Object
'// Contains implied assignments, because of the automatic initialization
'// , but the variables mutate only once
Private n_Count As Int
Private x_Reduced As Object
Return List_Reduce_with_InitialValues( s_Component, s_Function, lst, n_Count, x_Reduced )
End Sub
Sub List_Reduce_with_InitialValues( s_Component As String, s_Function As String, lst As List, n_Count As Int, x_Reduced As Object ) As Object
'// If function doesn't exist, return the original object
If SubExists( s_Component, s_Function ) == False Then
Return x_Reduced
End If
'// If there's only one element in the source list, then just return its single value
If lst.Size == 1 Then
Return lst.Get( 0 )
End If
'// If there are only 2 elements in the source list, then combine those two, and return the result
If lst.Size = 2 Then
Return CallSub3( s_Component, s_Function, lst.Get( 0 ), lst.Get( 1 ) )
End If
If n_Count = 0 Then
x_Reduced = lst.Get( 0 )
End If
If n_Count+1 == lst.Size Then
Return x_Reduced
Else
Return List_Reduce_with_InitialValues( s_Component, s_Function, lst, n_Count+1, CallSub3( s_Component, s_Function, x_Reduced, lst.Get( n_Count+1 ) ) )
End If
End Sub
Sub List_Filter( s_Component As String, s_Filter As String, lst As List ) As List
'// Contains implied assignments, because of the automatic initialization
'// , but the variables mutate only once
Private n_Count As Int
Private lst_Results As List
lst_Results.Initialize
Return List_Filter_with_InitialValues( s_Component, s_Filter, lst, n_Count, lst_Results )
End Sub
Sub List_Filter_with_InitialValues( s_Component As String, s_Filter As String, lst As List, n_Count As Int, lst_Results As List ) As List
If lst_Results.IsInitialized == False Then
lst_Results.Initialize
End If
'// If function doesn't exist, return an empty list.
If SubExists( s_Component, s_Filter ) == False Then
Return lst_Results
End If
'// If the count is up to the length of the list, then return final result
If n_Count == lst.Size Then
Return lst_Results
Else
'// If Filter Predicate returns true, then include the original item in the Result list
If CallSub2( s_Component, s_Filter, lst.Get( n_Count ) ) == True Then
Return List_Filter_with_InitialValues( s_Component, s_Filter, lst, n_Count + 1, AddItemToList( lst_Results, lst.Get( n_Count ) ) )
Else
Return List_Filter_with_InitialValues( s_Component, s_Filter, lst, n_Count + 1, lst_Results )
End If
End If
End Sub
' Callable functions for testing
Sub IsEven( n As Int ) As Boolean
Return n Mod 2 == 0
End Sub
Sub PlusOne( n_Int As Int ) As Int
Return n_Int + 1
End Sub
Sub Plus( n_Int1 As Int, n_Int2 As Int ) As Int
Return n_Int1 + n_Int2
End Sub
Sub Concatdat( s1 As String, s2 As String ) As String
Return s1 & s2
End Sub
'...
'...
'...
End Sub