Subscribe to The Madman Scribblings        RSS Feed
-----

Iterators used unconventionally.

Icon Leave Comment
Iterators used unconventionally.


I was thinking could the LINQ approach, be applied to getting inputs from the user?

In VB11 (vs2012) iterators where added to the VB.Net, so lets utilize them.

Module Public Module ConsoleEnumerables
    Public Iterator Function GeIntegers(Optional allowNegatives As Boolean = False) As IEnumerable(Of Integer)
        While True
            Yield ReadInteger(allowNegatives)
        End While
    End Function


So that's all there is to it. Get User input and then yield it.

Of course all of the heavy lifting is handled in the ReadInteger Function, it handles the keypresses to filter input to specific keys. The delete key being rather tricky.



  Public Function ReadInteger(Optional AllowNegatives As Boolean = False) As Integer
        Dim rs = ""
        Dim fn = Function(s As String) As Boolean
                     Dim v As Integer
                     Return Integer.TryParse(s, v)
                 End Function
        Do
            Dim ck = ReadKey(True)
            If ck.IsDigitKey Then
                If rs.IsValid(rs & ck.KeyChar, fn) Then Write(ck.KeyChar)
            ElseIf ck.IsDeleteKey Then
                If rs.IsValid(rs.Substring(0, rs.Length - 1), Function(s) fn(s) OrElse s = "") Then
                    Write(ck.KeyChar)
                    Write(" ")
                    Write(ck.KeyChar)
                End If
            ElseIf rs = "" AndAlso AllowNegatives AndAlso ck.IsMinusKey Then
                If rs.IsValid("-", Function(s) fn(s) OrElse s = "-") Then Write("-")
            ElseIf ck.IsEnterKey Then
                WriteLine()
                Exit Do
            End If
        Loop
        If rs = "" Then Return 0
        Return Integer.Parse(rs)
    End Function

#Region "ConsoleKeyInfo checks"
    <Extension>
    Public Function IsDigitKey(ck As ConsoleKeyInfo) As Boolean
        Select Case ck.Key
            Case ConsoleKey.D0 To ConsoleKey.D9,
                 ConsoleKey.NumPad0 To ConsoleKey.NumPad9
                Return True
            Case Else
                Return False
        End Select
    End Function
    <Extension>
    Public Function IsDeleteKey(ck As ConsoleKeyInfo) As Boolean
        Return ck.Key = ConsoleKey.Delete OrElse ck.Key = ConsoleKey.Backspace
    End Function

    <Extension>
    Public Function IsEnterKey(ck As ConsoleKeyInfo) As Boolean
        Return ck.Key = ConsoleKey.Enter
    End Function

    <Extension>
    Function IsMinusKey(ck As ConsoleKeyInfo) As Boolean
        Return ck.Key = ConsoleKey.OemMinus OrElse ck.Key = ConsoleKey.Subtract
    End Function
#End Region



The following extension method is used to ensure that result of keypress will result in a valid output.

    <Extension>
    Public Function IsValid(Of T)(ByRef current As T, nextstate As T, fn As Func(Of T, Boolean)) As Boolean
        Dim v = fn(nextstate)
        If v Then current = nextstate
        Return True
    End Function
End Module


It is used to ensure the value is valid and within the bounds of an Integer.

Example
Dim ave = GetIntegers.Take(5).Average
Console.WriteLine("Average: {0}",ave)

0 Comments On This Entry