VB.NET Versus Python
I recently signed up for CS262, Programming Languages, now being taught at the Udacity web site. Although it's too late to sign up for this particular course since it's well under way, you can sign up for others and (in spite of the fact that I have been having something of a rough time of it personally) I highly recommend the site. This course is being taught with the highest of academic standards and the people in charge are great.
In fact, it takes me back to "the good old days" when people wrote code simply because they loved it.
I had no idea what to expect when I signed up for the course. As I worked on the first unit, it took me right back to when I was an undergraduate working toward a degree in Computer Science. These people are disciplined academics, even though they're also having a lot of fun.
The end goal of the course is to write the code for a web browser, but we started with an introduction to Regular Expressions. You can find one that I wrote here on this site at: Regular Expressions in VB.NET . We'll need the knowledge later to do things like parsing the HTML code for the browser. But rather than depend on RegEx to do all that, the course immediately teaches about something I wasn't as familiar with: Finite State Machines (FSM).
Like Regular Expressions, you can't figure out what a Finite State Machine is just by hearing the name. It's a lot more complex than that. Really really briefly, a FSM is a way of describing a process that might be part of a computer program, a logic circuit ...
or a Regular Expression. One of the last assignments in the first unit of the class asks students to code one for the Regular Expression:
--------
Click Here to display the illustration
--------
A Regular Expression looks for a match in a string. In this FSM, if there is an "a" in the current position in state 1, then the "edge" (this is the terminology used in the class) goes to state 2. If there is an "a" in state 2, then the edge goes to state 2 (the first curved arrow). If there is a "1" in state 2, then the edge goes to state 3, the ending state. If there is a 1 in state 3, then the edge goes to state 3.
Once you get to state 3, the Regular Expression is said to match so that's the ending state. (That's what the double circles mean.) Strictly speaking, the "+" at the end of the Regular Expression isn't necessary. The instructor added it to make the code that you have to write easier.
But they want you to do it in the Python programming language! Arrrghhhh! I never coded a line of Python in my life before this class and I didn't know Python from a British comedy team! (Which is, actually, the origin of the name!) As you will see, this program must also be written using recursion. (I wrote an article about using recursion here: VB.NET and Recursion.)
After struggling with the Python code to do this for days, I gave up and wrote it in VB.NET in a few hours.
The instructor "made it easy for us" by coding the first part of the Python program and giving us a very broad clue about how to write the rest. Here's what we got. (Warning: Python code ahead!)
"edges" is a dictionary object in Python. "accepting" is just the value of the ending state. I have to admit that it's pretty slick - in a VB6 sort of way. (Python has weak typing like VB6. A variable can be basically anything and can change types from one statement to the next.) Basically, the two element object on the left of the colon is a key that points to the element on the right. Follow it through and you'll see that the four edges in the FSM diagram match the values in the dictionary object. In other words (starting with the first one) ...
"If there is an "a" in the current position in state 1, then the "edge" goes to state 2."
Isn't that exactly what I wrote earlier? It is!! So the dictionary object completely describes the states and edges for the FSM.
I found it a little more complex to write the same thing in VB.NET. Here's what I coded:
VB.NET has a Dictionary object too, but initializing it isn't nearly so straightforward. There is a technique for initializing in one statement like Python does it, but it this case it would require nested initialization and that's not allowed in VB.NET.
But after this point - at least in my humble opinion - VB.NET took home the roses on everything. Other than syntax (not really a problem after a little study) I had two major issues:
-> Scope of variables
-> Program flow in a recursive function
At least at this relatively elementary level, you define a Python function this way:
The indentation is critical. Functions (and any loops or If blocks) end when the indentation returns to the same margin as the "def" statement. Since Python is interpreted, the function has to be defined before it's used. So programs end up having fairly long function blocks followed by the actual statements that call those functions. And if you have a lot of For blocks and nested If blocks, it can easily happen that the function just ends when you least expect it somewhere in the middle of the function. (It took a while for my mind to adjust to this way of writing code.)
The scope of variable problem I had compounded the program flow problem. A variable is either "global" or "local" in Python. If it's defined in a function, it becomes local to that function even if it's global everywhere else. And there's no obvious way in the code to decide whether something is local or global. (Other than being a Python guru and simply "knowing".)
Since the code had to use a recursive function, I found variables returning to previous values (because the scope changed to the previously recursed function) and the program flow just going nuts. And I really missed the great Visual Studio development environment to figure it out. Python does ship with a GUI developer tool call Idle (as in Monty Python's Eric Idle - Get it?) that will step through the code, but there's no way to set a breakpoint, no Immediate window, no Watch window or QuickWatch. I found myself stepping from the top down to where I had a problem over and over and started developing carpal tunnel from clicking the mouse on the "Step" button in Idle and I eventually coded multiple "print" statements in front of every line of code to see what was going on. (Idle does report the values of variables, but it was the sequence of program flow that was most puzzling.)
VB.NET made the whole thing a lot easier. (For me at least.) Here's the complete code in VB.NET:
--------
Click Here to display the illustration
--------
But here's the kicker. As I said, I was able to work up this code in VB.NET in just a few hours. Once I got it done, the main thing that I discovered was that I was trying to write the wrong code in Python! The Python logic that I had working (but was still full of bugs) was simply doing the wrong things and I only figured that out by writing the same code in VB.NET. Then I could see what I was doing wrong in Python! I think that maybe the real problem was a poorly adjusted nut in front of the keyboard.
In fact, it takes me back to "the good old days" when people wrote code simply because they loved it.
I had no idea what to expect when I signed up for the course. As I worked on the first unit, it took me right back to when I was an undergraduate working toward a degree in Computer Science. These people are disciplined academics, even though they're also having a lot of fun.
The end goal of the course is to write the code for a web browser, but we started with an introduction to Regular Expressions. You can find one that I wrote here on this site at: Regular Expressions in VB.NET . We'll need the knowledge later to do things like parsing the HTML code for the browser. But rather than depend on RegEx to do all that, the course immediately teaches about something I wasn't as familiar with: Finite State Machines (FSM).
Like Regular Expressions, you can't figure out what a Finite State Machine is just by hearing the name. It's a lot more complex than that. Really really briefly, a FSM is a way of describing a process that might be part of a computer program, a logic circuit ...
or a Regular Expression. One of the last assignments in the first unit of the class asks students to code one for the Regular Expression:
a+1+
Here's the FSM for this Regular Expression:--------
Click Here to display the illustration
--------
A Regular Expression looks for a match in a string. In this FSM, if there is an "a" in the current position in state 1, then the "edge" (this is the terminology used in the class) goes to state 2. If there is an "a" in state 2, then the edge goes to state 2 (the first curved arrow). If there is a "1" in state 2, then the edge goes to state 3, the ending state. If there is a 1 in state 3, then the edge goes to state 3.
Once you get to state 3, the Regular Expression is said to match so that's the ending state. (That's what the double circles mean.) Strictly speaking, the "+" at the end of the Regular Expression isn't necessary. The instructor added it to make the code that you have to write easier.
But they want you to do it in the Python programming language! Arrrghhhh! I never coded a line of Python in my life before this class and I didn't know Python from a British comedy team! (Which is, actually, the origin of the name!) As you will see, this program must also be written using recursion. (I wrote an article about using recursion here: VB.NET and Recursion.)
After struggling with the Python code to do this for days, I gave up and wrote it in VB.NET in a few hours.
The instructor "made it easy for us" by coding the first part of the Python program and giving us a very broad clue about how to write the rest. Here's what we got. (Warning: Python code ahead!)
# FSM Simulationedges = {(1, 'a') : 2, (2, 'a') : 2, (2, '1') : 3, (3, '1') : 3}accepting = [3]def fsmsim(string, current, edges, accepting):if string == "":return current in acceptingelse:letter = string[0]# Is there a valid edge?# If so, take it.# If not, return False.# Hint: recursion.
"edges" is a dictionary object in Python. "accepting" is just the value of the ending state. I have to admit that it's pretty slick - in a VB6 sort of way. (Python has weak typing like VB6. A variable can be basically anything and can change types from one statement to the next.) Basically, the two element object on the left of the colon is a key that points to the element on the right. Follow it through and you'll see that the four edges in the FSM diagram match the values in the dictionary object. In other words (starting with the first one) ...
"If there is an "a" in the current position in state 1, then the "edge" goes to state 2."
Isn't that exactly what I wrote earlier? It is!! So the dictionary object completely describes the states and edges for the FSM.
I found it a little more complex to write the same thing in VB.NET. Here's what I coded:
Dim edges As New Dictionary(Of state, Integer)Dim theState(3) As stateDim accepting As Integer = 3Private Structure stateDim matchState As IntegerDim matchValue As CharSub New(p1 As Integer, p2 As Char)matchState = p1matchValue = p2End SubEnd StructuretheState(0) = New state(1, "a")theState(1) = New state(2, "a")theState(2) = New state(2, "1")theState(3) = New state(3, "1")edges.Add(theState(0), 2)edges.Add(theState(1), 2)edges.Add(theState(2), 3)edges.Add(theState(3), 3)Dim accepting As Integer = 3
VB.NET has a Dictionary object too, but initializing it isn't nearly so straightforward. There is a technique for initializing in one statement like Python does it, but it this case it would require nested initialization and that's not allowed in VB.NET.
But after this point - at least in my humble opinion - VB.NET took home the roses on everything. Other than syntax (not really a problem after a little study) I had two major issues:
-> Scope of variables
-> Program flow in a recursive function
At least at this relatively elementary level, you define a Python function this way:
def functionname(parameter1, parameter2):statementstatement
The indentation is critical. Functions (and any loops or If blocks) end when the indentation returns to the same margin as the "def" statement. Since Python is interpreted, the function has to be defined before it's used. So programs end up having fairly long function blocks followed by the actual statements that call those functions. And if you have a lot of For blocks and nested If blocks, it can easily happen that the function just ends when you least expect it somewhere in the middle of the function. (It took a while for my mind to adjust to this way of writing code.)
The scope of variable problem I had compounded the program flow problem. A variable is either "global" or "local" in Python. If it's defined in a function, it becomes local to that function even if it's global everywhere else. And there's no obvious way in the code to decide whether something is local or global. (Other than being a Python guru and simply "knowing".)
Since the code had to use a recursive function, I found variables returning to previous values (because the scope changed to the previously recursed function) and the program flow just going nuts. And I really missed the great Visual Studio development environment to figure it out. Python does ship with a GUI developer tool call Idle (as in Monty Python's Eric Idle - Get it?) that will step through the code, but there's no way to set a breakpoint, no Immediate window, no Watch window or QuickWatch. I found myself stepping from the top down to where I had a problem over and over and started developing carpal tunnel from clicking the mouse on the "Step" button in Idle and I eventually coded multiple "print" statements in front of every line of code to see what was going on. (Idle does report the values of variables, but it was the sequence of program flow that was most puzzling.)
VB.NET made the whole thing a lot easier. (For me at least.) Here's the complete code in VB.NET:
Private Sub btnCheck_Click(sender As System.Object, e As System.EventArgs) Handles btnCheck.ClickDim theString As String = txtString.TextDim theStringIndex As Integer = 0CheckState(txtString.Text, 1)End SubPrivate Sub CheckState( theString As String, current As Integer)' The "approved" Python solution:' def(fsmsim(String, current, edges, accepting)):' if string == "":' return current in accepting' else:' letter = string[0]' if (current, letter) in edges:' destination = edges[(current, letter)]' remaining_string = string[1:]' return fsmsim(remaining_string, 'destination, edges, accepting)' else:' return False' print (fsmsim("aaa111",1,edges,accepting))' The VB.NET versionIf theString = "" ThenIf current = accepting ThenlblMatch.Text = "True"ElselblMatch.Text = "False"End IfExit SubElseDim letter As Char = Strings.Left(theString, 1)Dim checkKey As New state(current, letter)If edges.ContainsKey(checkKey) ThenDim destination As Integer = edges(checkKey)Dim remaining_string =Strings.Right(theString, Len(theString) - 1)CheckState(remaining_string, destination)ElselblMatch.Text = "False"Exit SubEnd IfEnd IfEnd Sub
--------
Click Here to display the illustration
--------
But here's the kicker. As I said, I was able to work up this code in VB.NET in just a few hours. Once I got it done, the main thing that I discovered was that I was trying to write the wrong code in Python! The Python logic that I had working (but was still full of bugs) was simply doing the wrong things and I only figured that out by writing the same code in VB.NET. Then I could see what I was doing wrong in Python! I think that maybe the real problem was a poorly adjusted nut in front of the keyboard.
Source...