HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Immutable Linked List in VBA

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
listimmutablelinkedvba

Problem

I made an immutable list class using the head-tail idiom. If I did this correctly, it implements persistent data structures. Unfortunately it doesn't scale well as VBA is not tail recursive. Note: I use a method called seq.Assign to handle assigning objects without using Set. I would like to copy the objects and preserve immutability but for now; if you build a List of mutable objects and mutate one of those objects it will mutate the contents of that list and any list built from that list.

Let's get some basics out of the way.

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "SList"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True ' Client code cannot use `new` Keyword
Attribute VB_Exposed = True
Option Explicit


Private Members

Private TypedName As String
Private pHead As Variant
Private pTail As SList


TypeChecking

SList is also strongly typed using the following methods and boilerplate code

''
' TypeCheck:
Friend Sub TypeCheck(ByVal element As Variant, ByVal source As String)

    If TypedName = vbNullString Then TypedName = TypeName(element)
    If (TypeName(element) <> TypedName) Then RaiseTypeError element, source

End Sub
''
' RaiseTypeError:
Private Sub RaiseTypeError(ByVal badItem As Variant, ByVal method As String)
    Err.Raise 13, method, "Element is of type " & TypeName(badItem) & _
                         ", not " & TypedName & "."
End Sub
Private Sub RaiseEmptyError(ByVal method As String)
    Err.Raise 9, TypeName(Me) & "." & method, method & " cannot be called on Empty List!"
End Sub
Private Sub RaiseOutOfRangeError(Byval method As String)
    Err.Raise 9, TypeName(Me) & "." & method, method & " Index is out of range!"
End Sub


Friend Methods (mutability)

These methods violate mutability and should only be used carefully in constructor functions.

```
Friend Property Let Head(ByVal x As Variant)
TypeCheck x, "Head"
seq.Assign

Solution

I like that you prefer to use VBA's built in runtime errors, but...

Private Sub RaiseEmptyError(ByVal method As String)
    Err.Raise 9, TypeName(Me) & "." & method, method & " cannot be called on Empty List!"
End Sub
Private Sub RaiseOutOfRangeError(Byval method As String)
    Err.Raise 9, TypeName(Me) & "." & method, method & " Index is out of range!"
End Sub


You're raising two different errors with the same error number. As someone using this list, I would probably want to handle those two errors differently, but I would need two different error numbers to do so. I encourage you to define a custom error for the list being empty. The out of range error is fine as it is.

The code is neat and clean as far as I can tell. Variables and Methods/Properties have meaningful and clear names mostly. You overshorted some of them and I'm a little confused by what the Nil Function is, but I suspect someone familiar with Python wouldn't be. (Okay, I'm not really, but I had to read the code to understand that it returns an empty list).

This could be cleared up with some documentation I suspect. A few comments explaining what each procedure does would go a long way. Perhaps even some Item.VB_Description attributes so they show up in intellisense too? That's always nice to have when you're working with an unfamiliar class or library. Of course, don't get carried away. You don't need to tell us what Contains does, but it would be nice to understand what Public Function Cons is. (Again, I know it's a constructor, but you could never tell that from it's name alone.)

Code Snippets

Private Sub RaiseEmptyError(ByVal method As String)
    Err.Raise 9, TypeName(Me) & "." & method, method & " cannot be called on Empty List!"
End Sub
Private Sub RaiseOutOfRangeError(Byval method As String)
    Err.Raise 9, TypeName(Me) & "." & method, method & " Index is out of range!"
End Sub

Context

StackExchange Code Review Q#68802, answer score: 4

Revisions (0)

No revisions yet.