This weekend, I finally sat down and did something that I promised myself I would do for around a year now: I started working with F#. The experience was really quite interesting. For the first time in more than a decade, I was not able to just sit down and grok a language by staring at some sample code for a few minutes. The experience highlighted the current miserable state of affairs in the world of general programming languages. Sure, I have railed about the mediocrity of VB.NET, C#, Java, and so forth in this space many times in the past. But it fascinated me to see how the way I think has been so heavily influenced by what I do.
I first encountered a functional programming language in 11th grade working with EdScheme. While the syntax of F# is rather different from EdScheme (EdScheme is a version of Scheme, which is a dialect of Lisp; F# is based upon OCaml), many of the principles are the same, especially with regards to the concept of "labels" as opposed to "values." In the functional programming world, there tends to be an avoidance (or outright banning) of the concept of a "value"; instead, every identifier actually acts as a label to refer to a particular function. For example, "let x = 5 + y" does not actually set the value of x to be the value of y plus the number 5. Instead, x is a function that when called, calculates 5 + y and returns it. As you can imagine, thinking in this way is a radical departure from the hallowed halls of the procedural code that most of us spend most of our time working with.
As a side note, I include object-oriented (OO) code in the "procedural code universe," simply because at the rawest, lowest level, every OO program ends up in a very traditional, procedural thought process. In other words, the OO is simply a very pretty and well-organized hook to access and write procedural code.
Putting that aside, I found my mind struggling so hard with certain concepts. What was truly frustrating is that I used to know this. It is not just that I was a bit rusty or out of practice, I found myself actively struggling to think like F# was asking me to. Imagine if you tried to ride a bike, and your foot reached for the gas pedal just because you have been driving for 15 years, and you will get the idea.
It reminded me very much of a conversation that I had a few months ago. The person I was speaking with was a programmer visiting the U.S. from India. This gentleman and I had gotten to know each other fairly well, and he has been programming for quite some time, probably around as long as I have. He and I got onto the topic of education. It is a well-known fact that India, China, and a number of other countries are beating the U.S. in math scores. So I asked him how they teach math in India. He was almost baffled by the question, as if there was more than one way to learn math and this was the first time someone had let him know. "From a book, with examples on the blackboard, how else?" I queried him about the use of calculators and computers, two tools quite common in U.S. math education. He explained to me that calculators are forbidden in their version of high school and that, in colleges, the calculators allowed are basic models (think add, subtract, multiply, divide, exponents, square root, log 10, and natural log), and their usage even then is frowned upon to the point where using a calculator will be the cause of ridicule and humiliation. This sure sounded like a far cry from the educational environment in the U.S., where 7th grade students are now being required to own TI-85's, a calculator that's probably more powerful than the guidance system on a cruise missile.
Where this all comes together is the idea of fundamental methods of thought. Writing code (and writing it well) requires the ability to think a certain way. As my experience has taught me repeatedly, once a way of thinking is set, it is hard to think differently. In the case of F#, a way of thinking that was easy when I was an extremely inexperienced user is tough now that I am at the experienced level. The solid foundation of thought which was laid by an excellent early education has had a ramshackle house built upon it, which must be cleared away if I want to build a nice new home. But at least if/when I demolish that rat trap, I will still have a solid foundation, a clean well, and good plumbing to build upon. The hard work is done and I just need to rebuild the house itself. For someone who is trying to build a ramshackle house on a bare ground foundation, there is going to be a real problem. This is why the issue of general education so concerns me.
I know I can learn F#. While the curve was higher for me to get even rudimentary levels of understanding than usual, it is imminently possible. I just need to keep reminding myself how functional languages work, and I am fine. But for the person without those experiences, without that fundamental basis of thought, how can they learn this? I have no idea. Is understanding a functional programming language a requirement to be a programmer? Of course not. Many excellent programmers have never touched one and that is fine. Nevertheless, the methods of thinking taught by such an experience is invaluable. I know that my encounter with EdScheme taught me a lot about being a good programmer, even if I have become stuck in a "general purpose OO language" rut for some time now.
This is why the conversation with my Indian friend has me so worried. It seems to me that the schools in India, China, and many other countries are laying extremely high quality general education foundations for their students. I look at the "math" that my brother and sister learned (I am much older than they are), and I do not want to subject my child to the same kind of disastrous "education" (I am officially not a parent yet, but he is on his way in a few more days or weeks!). I love to see the best brought out in people. A mathematical foundation built upon computers and advanced calculators simply does not provide the basis to build a good programmer on.
I think that once I get through this F# experience (I want to learn more about it to evaluate its suitability for real-world programming), it is time to get back to the basics. A reader a few weeks ago recommended some books by ER Tufte, so I think that I will start there. In my current role, hands-on programming is minimized. I need to get my principles polished up again to be the best that I can possibly be.
Justin James is the Lead Architect for Conigent.