I just ran into an interesting issue related to data binding. I have a custom control in a windows forms application that manages the app's configuration. I also have a configuration object. The control is the view for the configuration object.
I had bound the object properties to controls using the following idiom
private void bind() { SeeRectangle.DataBindings.Add("Checked", configuration, "ShowAnswer"); // Checkbox OrderingTypeSelection.DataBindings.Add("SelectedItem", configuration, "OrderingMode"); // ComboBox AnswerPath.DataBindings.Add("Text", configuration, "AnswerPath"); // TextBox }
When adding a data biding via the Add() method of the DataBinding specialized collection, the arguments are the property of the control that will be bound, followed by the object that we will bind with, followed by the property of the object that is binding. The checkbox and combobox worked fine. I wasn't getting expected results with the textbox binding.
I had tried to assign the value of the Text property of the textbox with the following code
var openDirectory = new FolderBrowserDialog(); var answer = openDirectory.ShowDialog(); if (answer == DialogResult.OK) { if (configuration != null) { AnswerPath.Text = openDirectory.SelectedPath; } }
And the textbox was correctly assigned. However, the binding with the configuration object kept failing. What I discovered was that there must be an event that is not triggered when assigning values via code. If I changed the values in the textbox, the assignment would happen.
So the workaround was to explicitly assign the value from the FolderBroswerDialog to the configuration object.
var openDirectory = new FolderBrowserDialog(); var answer = openDirectory.ShowDialog(); if (answer == DialogResult.OK) { if (configuration != null) { AnswerPath.Text = openDirectory.SelectedPath; configuration.AnswerPath = openDirectory.SelectedPath; // <--- the solution } }
Last week we went to the Science and Engineering festival in DC. Among the great swag that we got was a couple of circuit kits from sparkfun designed to teach one how to solder. My daughter had done the Parallax "learn how to solder" activity at the festival, so we donated some money and got two kits, one for her, and one for me.
I did mine today. It is a Simon Says game, and I was pretty pleased with how well I was soldering. I had tried it before, but I think I kept missing the right combination of soldering iron and the correct solder with for electronics. Most of my dots were pretty, except for some necessary big blobs that I needed to make to connect the battery holders; those were horrible. Admitting that fault, I was pretty happy with my job soldering the micro-controller. I had previously had problems soldering a 555 chip, so to be able to solder way more leads successfully made me happy.
Looping is a fundamental concept in computer programming. And to most programmers familiar with imperative c-syntax languages, it looks something like this:
foreach (var s in stringList) { doSomethingTo(s); }
The idiom is simple: we are going to go through each item in the list, and we will process that element in some manner. In most cases, we are either transforming each element, we are filtering the elements, or we are carrying out some sort of accumulation. To know which of these actions is being carried out we would have to read carefully what is happening in between the curly brackets.
So, looking at the code, we instantly know that we are doing something with every element. But at a glance we don\'t know what that something is.
Functional programming gives us three (3) functions to loop through lists. These are map(), filter(), and fold(). The final result between imperative looping and the functional functions is the same, but we gain semantic clues with the functional functions to what the looping id doing.
C# is a remarkable language. Although it was born as an imperative language, it has been supporting more and more functional operations through linq. Below I will briefly describe the three looping functions, and then I will show its imperative equivalent, followed by its equivalent in using linq.
map() will take a function followed by a list. Each element in the list will be transformed by the function, and the output will be a list of transformed values. In haskell it looks like this
x = map (* 5) [3,4,5,6,3]
Translated into imperative C# code it looks like this:
var result = new List<int>(); var list = new list<int> { 3,4,5,6,3}; foreach (var n in list) { result.Add(5 * n); }
In linq, to express the above function, we us the select query thingy and write
var query_result = (from n in new List<int> { 1, 2, 3, 4, 5 } select n * 5).ToList();
Sometimes we use loops to filter values out. Functional programming languages have filter(), which takes a predicate function, one with a condition, and a list, and returns a list that meets the filter condition.
x = filter (> 5) [3,4,5,6,3]
Its procedural code in C#:
var result = new List<int>(); var list = new list<int> { 3,4,5,6,3}; foreach (var n in list) { if (n > 5) result.Add( n); }
And its functional version in C# via linq. For filter, we mainly use the where clause in a linq query.
var query_result = (from n in new List<int>() { 1, 2, 3, 4, 5 } where n > 5 select n).ToList();
The final looping case that I will show is aggregating a value, such as a total from all of the numbers in a list. This operation is called fold in functional programming, since the person naming the function imagined a paper list of values being folded one at a time. foldl takes a function, a list, and an initial value.
x = foldl (+) 0 [3,4,5,6,3]
This is equivalent to procedural C# to
var result = 0; var list = new list<int>{ 3,4,5,6,3}; foreach (var n in list) { result += n; }
In functional C# via linq we write:
var query_result = (from n in new List<int>{ 1, 2, 3, 4, 5 } select n).Sum() ;
The above was shown to keep the parallelism between the examples. In actual use, one would most likely use a IEnumerable
var result = new List<int> { 1, 2, 3, 4, 5 }.Sum();
As we have seen, the functional methods map, filter, and fold have an semantic advantage over procedural looping in that they clearly tell you what the looping is doing. C# has the capabilities of doing functional statements. Although not giving the same terse syntax or its immediate semantic meaning, the linq functional-like methods approximate functional terseness and reduces, although not eliminates, the semantic ambiguity the semantic ambiguity that procedural loops have.
While working on a personal project, I ran into the following case. I wanted method load() to take a hash with values. If a key in the hash exists as an instance method, then assign the value from the input hash to it. I could have coded around it using an array with the names of instance variables and working from there, but, where is the fun in that? Besides, I knew that I could use this as a concrete meta programming exercise for myself.
1. I made sure that accessors create an instance method
I started irb and tested whether a class with an accessor would create an instance variable automatically. I tried the following:
class A attr_accessor x end y = A.new y.instance_variable_set "@x", "wow" puts y.x # => "wow"
So far, it seems like it works! So back to the text editor, and I wrote the method.
2. Something isn't right
def load(data = nil) if data.instance_of? Hash data.keys.each do |key| if self.instance_variables.include? key attr_name = "@#{key}" self.instance_variable_set attr_name , data[key] end end end end
So I write the code above. I expect that my tests would pass. But they didn't. The if clause was never true, so there was never an assignment. What? I looked back at the class description. The accessor names were there. What was going on? After a few minutes, I remembered a lunch discussion that I listened to at Ruby Nation. It was discussed that ruby starts with an empty object, and it builds members and methods as they are declared or needed. To begin with, there isn't anything in an object beyond the Object methods themselves, or so I understood. So, that means that until there is any assignment to a member accessor, the instance variable that the accessor provides the getter and setter for method doesn't exist yet.
Since the instance variable wasn't there, I decided to check for whether the object could respond to its getter/setter method.
3. Getting it to work
def load(data = nil) if data.instance_of? Hash data.keys.each do |key| if self.respond_to? key attr_name = "@#{key}" self.instance_variable_set attr_name , data[key] end end end end
the difference happens on line 4. It went from
if self.instance_variables.include? key
where I was checking for the existence of the instance variable (which doesn't exist until assignment) to
if self.respond_to? key
which checks for whether the object would respond to the method. This fix the problem.
I ran into some strange issues with exception testing in rspec when working on cygwin using rspec 2.6.4. These more more than anything else a collection of notes.
I am writing an object Room. It should have an optional hash argument. So I have two scenarios to test: that it should quietly create the Room object when no arguments were given to the initializer, and that, if there is an argument, it should only be a hash. Here are the tests that eventually worked:
describe "initialize" do it "should accept an optional argument" do expect { @r.init {} }.should_not raise_error end it "should accept only a hash" do expect { @r.init [] }.to raise_error ArgumentError end end
And the following are the steps that I took when I was getting there, and what I learned on the way.
1. I can't test object creation, Room.new, tests will consistently pass
When using this code:
expect { Room.new [] }.should raise_error
rather than getting the error that I was expecting, it would silently pass, which is not good when the whole point of testing is to convince yourself and others that the object is behaving as expected.
2. room.initialize() is invisible
I thought to myself that even though it is a bit annoying, not being able to test via object creation is not that horrible. I would just test initialize() instead.
expect { @r.initialize [] }.should raise_error
When running it, I did get those expected errors. however the error was because it couldn't find the initialize(). Not the error that I wanted. So it seems that initialize() becomes invisible when running rspec.
3. room.init works
So what I had to do was to create a init() method that would handle the code that otherwise would be found in initialize(). A bit clunky, but it works.
Now, the only reason why I spent so much time on it was because I thought it was an important logic. This logic would have been taken cared of by the compiler in a static language. Since that is not available, it would be nice to be able to be able to test the constructor. Maybe there is a way. Maybe I missed it. But for the moment, this is what I found.
This is a game that my daughter wrote. I wrote the code for the game in Small Basic. It was fun, but I could feel the limits of Small Basic when writing the code. :) The source code sharing code is KVG603
I have been thinking a lot about BASIC recently, and it seems that I have a lot to say about it, so I will break up this huge blog entry that I wrote about BASIC into smaller, more digestible ones.
Right now BASIC is mostly derided or hated. Yet since the 60s to the 90s, it is the language that most people learned how to program. John George Kemeny and Thomas Eugene Kurtz created a masterwork learning programming language. And they did this early in the history of computing. As it is, BASIC was designed to teach people the rudiments of programming. And on this goal, BASIC has been the most successful teaching language ever made.
BASIC has a series of characteristics that makes it so successful. The most important is that it is small. Very small. The core of the language can be printed out in a single sheet of paper. Because it is so small, it can teach the core ideas about programming, such as assignments, conditional, and loops. One can learn the core between in about a weekend. The lack of a greater language makes the learner focus on the concepts rather than on syntax. The small size of the language is probably the reason why it became the default language of the home computer of the 70s and 80s.
Another important feature was that it gave you quick feedback. With a few strokes, one could see something happening on the screen. The feedback loop is powerful; and especially important in programming education. Many programmers remember the feeling of power that they felt when they understood that they could control the machine. BASIC, thanks to its economy in typing strokes, gives that feeling fast.
Finally, BASIC had an environment that got out of the way. Once one learned how to run, save, and open a file, one could focus on programming. The text editor was simple, and for all practical purposes, invisible.
One can accuse me of being nostalgic about BASIC. They can point out the many faults that the language has such as the lack of consistent functions, subroutines, the GOTO command, the bad learning habits picked up by the language, etc. No, I am not ignoring them. it happens that they get mentioned too much, and the strengths of BASIC are not acknowledge enough. Furthermore, we forget to remember a curious historical incident that occurred to the language and which brings forth its shortcomings:
It was a learning language for beginners
It was not meant to be a professional language. It was not meant to be used for big programs. Most of the problems attributed to the language come from its accidental misuse as a professional programming language. The same characteristics that makes the language great as a teaching tool is what makes it horrible as a professional language. Some of the bad thinking habits grew out of necessity when writing programs around BASIC's limitations.
Eventually the shortcomings to the language were addressed with newer versions of that extended the language and gave it greater flexibility and addressed its former problems, but the reputation damage of caused by the 80s versions of the language was done.
That was history. The question today is whether there is a place for BASIC in education. This year we have seen a lot of interest in the internet about people wanted to learn how to code. I personally feel conflicted on this. How much of BASIC's success can we explain by existing at the right time? Maybe it is too old? Maybe newer languages such as python, ruby, or Scratch are better substitutes? I will explore some of these questions in future posts, where I compare different languages.
I am happy that I am having less allergic reactions this year than last year.
I have been trying to be as thrifty in coding as I can. And by thrifty I mean not introducing any technique until the code has a reason to have it. That includes objects. If the code is small enough, we should start testing single functions until there is a reason to use an object.
Rspec, and many unit testing frameworks, assume objects. Because I am trying to avoid introducing objects until I need them, I wanted to find out how you can tests functions without including them in an object. The solution follows. The code is all included in a single file:
def make_it_work true end describe "testing straight functions" do it "should work" do make_it_work.should == true end end
Now, this is really cheating. Looking at the rspec documentation, one sees that one needs an object to add an expectation. Since everything in ruby is an object, we can happily add the expectation to our function. The function is an object.
However, I still find this solution useful. Because, even though the function is an object, in our minds, it is a function, just like the number 5 is still a number when in reality is an object too.
Today it made me very happy that my son had his first programming lesson in scratch. He is now able to read well enough that he can use the environment. His hand-eye coordination is good enough that he can work correctly using a mouse. I am very proud of him.
My daughter had some trouble getting started, but then she focused and did her violin and calculus lesson.