I'm starting a new project based on some concepts I learned in the flashcard program.
That program is still in beta testing. The basic feature set is ready, but I'm trying to decide if I should delay the 1.0 release to move everything into a database (rather than files).
Anyway, this one will be a memorization tool for Bible verses. I'm terrible at memorizing Scripture, and I really want to improve. Therefore, I'm working on a new utility which will help with my ability to remember.
Instead of randomization and probabilistic weighting for short-term learning (like the previous flashcard system), this one will feature a long-term memorization technique, much closer to the original Leitner algorithm. A GUI (web-based Flex, or desktop AIR, or desktop QT) will be used to select and display verses in a list, associated with a user. The verses being displayed will be weighted according to the user's ability to remember and repeat them. As users are better able to remember, they'll see them less often every day. I have some investigation to do regarding how to do the time calculations (e.g. I guessed a verse right, when should I be asked again), but that's another post altogether.
Anyway, it will be interesting to see how it goes.
Thoughts on theology, books, life, the universe, and everything.
Sunday, March 15, 2009
Sunday, March 8, 2009
Flex and RIA development
I had a project at work to complete. Our automated testing infrastructure has aged beyond the point of usability, and no money has existed for upgrading to a more recent version, or investing in a different system for automated and manual test deployment, tracking, and maintaining.
One of my coworkers began (several years ago) piecing together a web-based automation utility which would allow us to quickly configure and execute test servers with automated tests. The solution was, conceptually, a combination of Javascript, CSS, and Ajax, in which users could add machines to a table, drag&drop test configurations to each machine, edit the test configurations (e.g. modify the command-line parameters passed to each test), and execute the overall config by sending it to the test automation system as a single CSV string.
His work lasted about 3 months, and resulted in the drag&drop interface.
Shortly after this, another coworker extended upon this work by adding the test config storage and retrieval via Ajax. Users could [in theory] add tests to each machine, edit their respective parameters, and execute said tests. They could also quickly create test configurations which would map directly to their respective automated tests in the version control repository.
The result was pretty good, but fell short in several ways: Ajax calls only worked 70% of the time, resulting in failures to execute tests, save configurations, and retrieve various pieces of information. Each test config was stored as a Javascript file on the web server, which required users to understand Javascript syntax if they wanted to manually add or edit existing configs. It also refused to work in IE.
His work lasted several months as well before he moved on to bigger and better things. I inherited it and took on the work to make it work more consistently with our test infrastructure. This lasted for about 3 months on the system before I decided to investigate other solutions.
Enter Flex.
The original interface put together was quite sound: dragging and dropping test configs to various machines is a great idea, though difficult to implement. I wanted to keep the use model of the system, but move away from pure Javascript.
After hearing some buzz regarding Flex around the office, I decided to take a look and see if it could offer a better solution.
Frankly, I was amazed. Within 3 weeks of starting, and without any prior exposure to Flex and ActionScript, I had completely reproduced all interface functionality, and even added several extensions. Rather than relying on Javascript for test configurations, I was able to introduce XML (a more logical choice, in my opinion) for configuration storage and retrieval. Relying on the Flash player resolved the issues between IE and Firefox (and other browsers which support the issues with storing and retrieving information from the web server.
In short, Flex is a fantastic solution for developing "Rich Internet Applications." The presence of a standardized API (*cough -- javascript!*) and a full-fledged object-oriented language quickly and easily resolved all issues I had with prior implementations.
In essence, though I'm impressed with the usability and functionality of Javascript and CSS, for web apps I'm likely going to stick with Flex and potentially Cappuccino if it's as cool as it looks.
One of my coworkers began (several years ago) piecing together a web-based automation utility which would allow us to quickly configure and execute test servers with automated tests. The solution was, conceptually, a combination of Javascript, CSS, and Ajax, in which users could add machines to a table, drag&drop test configurations to each machine, edit the test configurations (e.g. modify the command-line parameters passed to each test), and execute the overall config by sending it to the test automation system as a single CSV string.
His work lasted about 3 months, and resulted in the drag&drop interface.
Shortly after this, another coworker extended upon this work by adding the test config storage and retrieval via Ajax. Users could [in theory] add tests to each machine, edit their respective parameters, and execute said tests. They could also quickly create test configurations which would map directly to their respective automated tests in the version control repository.
The result was pretty good, but fell short in several ways: Ajax calls only worked 70% of the time, resulting in failures to execute tests, save configurations, and retrieve various pieces of information. Each test config was stored as a Javascript file on the web server, which required users to understand Javascript syntax if they wanted to manually add or edit existing configs. It also refused to work in IE.
His work lasted several months as well before he moved on to bigger and better things. I inherited it and took on the work to make it work more consistently with our test infrastructure. This lasted for about 3 months on the system before I decided to investigate other solutions.
Enter Flex.
The original interface put together was quite sound: dragging and dropping test configs to various machines is a great idea, though difficult to implement. I wanted to keep the use model of the system, but move away from pure Javascript.
After hearing some buzz regarding Flex around the office, I decided to take a look and see if it could offer a better solution.
Frankly, I was amazed. Within 3 weeks of starting, and without any prior exposure to Flex and ActionScript, I had completely reproduced all interface functionality, and even added several extensions. Rather than relying on Javascript for test configurations, I was able to introduce XML (a more logical choice, in my opinion) for configuration storage and retrieval. Relying on the Flash player resolved the issues between IE and Firefox (and other browsers which support the issues with storing and retrieving information from the web server.
In short, Flex is a fantastic solution for developing "Rich Internet Applications." The presence of a standardized API (*cough -- javascript!*) and a full-fledged object-oriented language quickly and easily resolved all issues I had with prior implementations.
In essence, though I'm impressed with the usability and functionality of Javascript and CSS, for web apps I'm likely going to stick with Flex and potentially Cappuccino if it's as cool as it looks.
Sunday, January 11, 2009
Flashcards Project Status
For those of you who don't know, I've been working on a new project for the past several months. My initial desire was to create a simple little app which would help me learn Python, and would also facilitate my learning of Classical Greek endings. Verb and noun endings in Greek are vitally important to understand, and there's so bloody many, I felt a learning application would be a fun project.
The last 4 months of coding have been some of the most fun I've had.
Though the project is still in its infancy, and though I'm struggling with massive amounts of scope creep, I have an "alpha" which is almost ready to be released.
Here are the initial requirements/specifications:
1. The system will provide "questions" and allow users to provide "answers"
2. The system will check the user's response and either accept it as a match, or reject it
3. The "questions" posted by the system will initially be in the form of Classical Greek verbs, nouns, or prepositions. Answers will be posted in English.
4. Verbs and Nouns can be put together by the system as a "cross product" of two sets: roots and endings. In other words, the system should be able to take a list of roots and apply endings to each one.
4a. In addition to this, the system should be able to discern the correct answer
5. The system will use Leitner's System (or a modified version) for "learning" which words the user knows and which ones they don't.
5a. The system will provide "questions" for those less-known words more often than those of well-known words
5bi. The system should have a means for accessing less-known words more often than well-known words (see point 8b)
6. The system will provide a means of "hinting" at the answer
6a. The hint system should be configurable
7. The system will provide statistics for the learner to gauge their progress
7b. The system should output information regarding the number of successes, failures, and hints posted or requested by the user
8. The system will allow the user to modify the underlying details of the Leitner Algorithm while currently engaged with the application
8a. The user should be able to modify the number of "piles" (called "buckets") in which the cards are distributed, within the range of '1' or '10' buckets
8b. The user should be able to modify the means in which the buckets are distributed (e.g. 30% of the time, the system will pull cards from the least-known bucket, 5% of the time it will pull from the well-known bucket)
9. The system should use a QT-based GUI for viewing
10. The system should be able to preserve the current state of user-execution
10a. The system should allow the user to save/restore the current state whenever they desire
11. The system should be configurable via XML configuration files, allowing users to "hot-swap" different card-input algorithms
12. The system will provide detailed documentation for use, administration, and flashcard development.
13. The system will host 'hotkeys' for easier navigation
These are the basic requirements. All but 10 and 11 are pretty much finished, though there are a number of defects and design issues which need to be addressed.
One requirement I'd really like to investigate and get working is #11. My buddy Bump suggested this: apparently, the current Flashcard systems don't have very well abstracted algorithms which can be swapped out. I'm not sure what this will mean, but it sounds interesting and fun.
In the meantime, here are some screenshots of the GUI in action. In order they are:
I. The main GUI and dialog for choosing the card "set"
II. The main flashcard GUI -- note the Unicode characters for the Greek words and the statistics in the lower left corner
III. Main flashcard GUI -- posted failure when user guess is incorrect
IV. Main flashcard GUI -- posted hint when user requests
V. Main flashcard GUI -- posted success when user guess is correct
VI. Main Algorithm Admin GUI -- note the Leitner and Hint system administration options





The last 4 months of coding have been some of the most fun I've had.
Though the project is still in its infancy, and though I'm struggling with massive amounts of scope creep, I have an "alpha" which is almost ready to be released.
Here are the initial requirements/specifications:
1. The system will provide "questions" and allow users to provide "answers"
2. The system will check the user's response and either accept it as a match, or reject it
3. The "questions" posted by the system will initially be in the form of Classical Greek verbs, nouns, or prepositions. Answers will be posted in English.
4. Verbs and Nouns can be put together by the system as a "cross product" of two sets: roots and endings. In other words, the system should be able to take a list of roots and apply endings to each one.
4a. In addition to this, the system should be able to discern the correct answer
5. The system will use Leitner's System (or a modified version) for "learning" which words the user knows and which ones they don't.
5a. The system will provide "questions" for those less-known words more often than those of well-known words
5bi. The system should have a means for accessing less-known words more often than well-known words (see point 8b)
6. The system will provide a means of "hinting" at the answer
6a. The hint system should be configurable
7. The system will provide statistics for the learner to gauge their progress
7b. The system should output information regarding the number of successes, failures, and hints posted or requested by the user
8. The system will allow the user to modify the underlying details of the Leitner Algorithm while currently engaged with the application
8a. The user should be able to modify the number of "piles" (called "buckets") in which the cards are distributed, within the range of '1' or '10' buckets
8b. The user should be able to modify the means in which the buckets are distributed (e.g. 30% of the time, the system will pull cards from the least-known bucket, 5% of the time it will pull from the well-known bucket)
9. The system should use a QT-based GUI for viewing
10. The system should be able to preserve the current state of user-execution
10a. The system should allow the user to save/restore the current state whenever they desire
11. The system should be configurable via XML configuration files, allowing users to "hot-swap" different card-input algorithms
12. The system will provide detailed documentation for use, administration, and flashcard development.
13. The system will host 'hotkeys' for easier navigation
These are the basic requirements. All but 10 and 11 are pretty much finished, though there are a number of defects and design issues which need to be addressed.
One requirement I'd really like to investigate and get working is #11. My buddy Bump suggested this: apparently, the current Flashcard systems don't have very well abstracted algorithms which can be swapped out. I'm not sure what this will mean, but it sounds interesting and fun.
In the meantime, here are some screenshots of the GUI in action. In order they are:
I. The main GUI and dialog for choosing the card "set"
II. The main flashcard GUI -- note the Unicode characters for the Greek words and the statistics in the lower left corner
III. Main flashcard GUI -- posted failure when user guess is incorrect
IV. Main flashcard GUI -- posted hint when user requests
V. Main flashcard GUI -- posted success when user guess is correct
VI. Main Algorithm Admin GUI -- note the Leitner and Hint system administration options






Saturday, January 3, 2009
Brief Update
We just returned from SD yesterday. It was a great trip, albeit pretty short. We flew out from Denver on Tuesday morning and arrived in Sioux Falls (about 45 miles northeast of Freeman) around 1 in the afternoon. All in all, the flight was ok. Our departure was an hour late; apparently, the plane was falling apart and they needed to piece it back together. Such things do not instill massive amounts of reassurance in those of us who are a bit trepidatious when it comes to flying.
We stayed with Jenn's family over the duration. Her family on both sides visited over lunch on the 31st and 1st. I didn't spend much time with her mother's side: it was only the women, and I had the opportunity to have lunch with her younger brother and father. It was a worthy trade off.
We left yesterday morning at 11 and arrived here at 12:30pm. Ofelia did very well throughout the entire trip. The first time she fussed during travel since Tuesday was yesterday as the plane was descending. Other than that, we could tell she enjoyed the adventure immensely. She made friends with people all over the airport and in the plane, her smiles inspiring others everywhere she went. I'm amazed at how much happiness she seems to bring to those around her. She's very friendly, and has a way of endearing herself to everyone. While we were sitting on the plane waiting to take off, she kept peering through the gaps in between our seats, giggling, squeaking, and smiling at the elderly couple behind us. She did the same for several people behind and next to us as well. It was cute, and very fun to watch.
Of course, I was primarily focusing on not freaking out over being 30,000 feet in the air, but that's another tale for another time.
She was also baptized a week ago tomorrow. The ceremony was held in a local Confessional Lutheran Church (Missouri Synod) and we've established a nice relationship with the lead pastor. I don't think the liturgical service is for us, per se, and we have disagreements with Lutheran doctrine, but it was an interesting exposure to a historical side of the Christian church which we hadn't seen prior.
That's all for now.
We stayed with Jenn's family over the duration. Her family on both sides visited over lunch on the 31st and 1st. I didn't spend much time with her mother's side: it was only the women, and I had the opportunity to have lunch with her younger brother and father. It was a worthy trade off.
We left yesterday morning at 11 and arrived here at 12:30pm. Ofelia did very well throughout the entire trip. The first time she fussed during travel since Tuesday was yesterday as the plane was descending. Other than that, we could tell she enjoyed the adventure immensely. She made friends with people all over the airport and in the plane, her smiles inspiring others everywhere she went. I'm amazed at how much happiness she seems to bring to those around her. She's very friendly, and has a way of endearing herself to everyone. While we were sitting on the plane waiting to take off, she kept peering through the gaps in between our seats, giggling, squeaking, and smiling at the elderly couple behind us. She did the same for several people behind and next to us as well. It was cute, and very fun to watch.
Of course, I was primarily focusing on not freaking out over being 30,000 feet in the air, but that's another tale for another time.
She was also baptized a week ago tomorrow. The ceremony was held in a local Confessional Lutheran Church (Missouri Synod) and we've established a nice relationship with the lead pastor. I don't think the liturgical service is for us, per se, and we have disagreements with Lutheran doctrine, but it was an interesting exposure to a historical side of the Christian church which we hadn't seen prior.
That's all for now.
Saturday, November 8, 2008
Some Post-Election Thoughts
I wrote this to my sister a few days ago. I won't paste the mail in its entirety, but it pretty much sums up my thoughts regarding the debacle that was our 2008 Presidential election:
Last night was an utter abomination for those of us who are conservative in our politics. It seems like our country is giving so-called "right-wingers" an ultimatum (or perhaps, just the finger) regarding our views. The amendment in Colorado which would have made the definition of "human" as starting at fertilization was TROUNCED (27% support), and the other governmental reforms were overturned. It was pretty sad. In addition, we now have a socialist-controlled government. We'll see what happen over the next few months/years. It's likely to get harder.
We Christians (the right-wing voters, including myself) have always assumed we have a "safety net" in our life here. Let's face it: this is the land of the free. We have First Amendment rights, don't we? We have freedom to worship as we please, and to tell people the truth without any consequences. This is America--we are a Constitution-led federal republic. But these words (the Bill of Rights and Constitution) are only words, unless they are truly believed by those who enforce them. The new government doesn't (and I'm not convinced the Republicans do either). We often hear about the Constitution as the be-all and end-all for our life, liberty, and pursuit of happiness. It's an amazing document, but...it's still just a document. The Constitution gives us no more rights than the government is willing to provide. Unfortunately, the new government will likely revoke what liberties we have.
For Christians, however, the Constitution, though a wonderful example of what God-fearing men can do with a government in a depraved world, is of middling importance. Will we face higher taxes over the next few years? Yep. Will we face increasing energy costs? Yep. Will we see our "free speech" rights restricted? Yep. But what does this mean for us as God's children? Well, it means life is going to be harder...no doubts about that. But our calling from the Lord remains: "'...make disciples of all the nations, baptizing them in the name of the Father, Son, and the Holy Spirit.'"
But let's face it, we have no guarantee in life which says we will get the majority of our earnings, or have access to cheap energy, or have local grocery stores filled with food. Our prosperity in this country has given Christians (and believe me, I'm 100% included in this) a false sense of security regarding our life and comfort here. Yeah, we might have some opposition when talking to people about Jesus, but this is America. We can still attend the church of our choice without penalty. We can still talk to people on the street without getting arrested. We can still shop at the local store and buy what we need for our existence. We can work and take home the fruits of our labor. We live in America--we can say we trust the Lord to provide, but...we don't necessarily need to back it up with real faith because...this is America.
Please don't misunderstand, I'm not knocking America. I don't want to live anywhere else, and I think the Founding Fathers had insight into the nature of power-based corruption and did what they could to minimize it. Unfortunately, their dream of America is flawed and unsustainable. Depraved mankind will not allow it.
I think American Christians have viewed their lives here as a form of "heaven on earth," where "live and let live" has been the norm. There's nothing wrong with prosperity and wealth--America has done more for helping raise the standard of living worldwide than any other country. America has also sent out more missionaries than any other nation. We have a rich heritage to be thankful for. But...this isn't heaven and we can't assume it will always be this way. And when life takes a turn for the worse, we should respond with faith and trust in the Lord's ultimate provision for our families and for the time when He will finally put to death all evil and sin. This is our hope and our
There's a law in physics which says, "everything is moving toward decay." Entropy is built into our reality--the heat given off by the sun for the growth of our crops (and for boiling Las Vegas ;) reveals the reality of its terminal state. Our world is dying and will continually move toward chaos and evil. The only real force in place stemming the tide is the Lord--not lower taxes, First Amendment rights, or limited government.
This is something which has slapped me hard in the face over the last 24 hours; the verse in Psalm 20:7 says, "Some boast in chariots, some in horses, but we boast in the name of the Lord our God." This has really challenged me to abandon my preconceived disposition to a comfortable life here. I don't think it's wrong to desire a peaceful life, but the Lord is ultimately in control...not our government.
Anyway, don't be troubled. The Lord is OUR shepherd and He will provide for our needs. The government will tear away every pound of flesh it can, but we have a future HOPE which cannot be taken from us.
Friday, October 17, 2008
Everlasting Lovingkindness
Reading Psalm 136 (ESV), I see this:
Give thanks to the LORD, for he is good, for his steadfast love endures forever.
Give thanks to the God of gods, for his steadfast love endures forever.
Give thanks to the Lord of lords, for his steadfast love endures forever;
to him who alone does great wonders, for his steadfast love endures forever;
to him who by understanding made the heavens, for his steadfast love endures forever;
to him who spread out the earth above the waters, for his steadfast love endures forever;
to him who made the great lights, for his steadfast love endures forever;
the sun to rule over the day, for his steadfast love endures forever;
the moon and stars to rule over the night, for his steadfast love endures forever;
to him who struck down the firstborn of Egypt, for his steadfast love endures forever;
and brought Israel out from among them, for his steadfast love endures forever;
with a strong hand and an outstretched arm, for his steadfast love endures forever;
to him who divided the Red Sea in two, for his steadfast love endures forever;
and made Israel pass through the midst of it, for his steadfast love endures forever;
but overthrew Pharaoh and his host in the Red Sea, for his steadfast love endures forever;
to him who led his people through the wilderness, for his steadfast love endures forever;
to him who struck down great kings, for his steadfast love endures forever;
and killed mighty kings, for his steadfast love endures forever;
Sihon, king of the Amorites, for his steadfast love endures forever;
and Og, king of Bashan, for his steadfast love endures forever;
and gave their land as a heritage, for his steadfast love endures forever;
a heritage to Israel his servant, for his steadfast love endures forever.
It is he who remembered us in our low estate, for his steadfast love endures forever;
and rescued us from our foes, for his steadfast love endures forever;
he who gives food to all flesh, for his steadfast love endures forever.
Give thanks to the God of heaven, for his steadfast love endures forever
Think about these statements for a second: ...to him who struck down the firstborn of Egypt, for his steadfast love endures forever...
This doesn't sound like our definition of love, does it? Here we see God enacting judgment against the Egyptians, by striking down their firstborn. Here's how Webster defines love (the first of several): strong affection for another arising out of kinship or personal ties
Do you ever wonder if our definition of love falls dramatically short of reality?
Give thanks to the LORD, for he is good, for his steadfast love endures forever.
Give thanks to the God of gods, for his steadfast love endures forever.
Give thanks to the Lord of lords, for his steadfast love endures forever;
to him who alone does great wonders, for his steadfast love endures forever;
to him who by understanding made the heavens, for his steadfast love endures forever;
to him who spread out the earth above the waters, for his steadfast love endures forever;
to him who made the great lights, for his steadfast love endures forever;
the sun to rule over the day, for his steadfast love endures forever;
the moon and stars to rule over the night, for his steadfast love endures forever;
to him who struck down the firstborn of Egypt, for his steadfast love endures forever;
and brought Israel out from among them, for his steadfast love endures forever;
with a strong hand and an outstretched arm, for his steadfast love endures forever;
to him who divided the Red Sea in two, for his steadfast love endures forever;
and made Israel pass through the midst of it, for his steadfast love endures forever;
but overthrew Pharaoh and his host in the Red Sea, for his steadfast love endures forever;
to him who led his people through the wilderness, for his steadfast love endures forever;
to him who struck down great kings, for his steadfast love endures forever;
and killed mighty kings, for his steadfast love endures forever;
Sihon, king of the Amorites, for his steadfast love endures forever;
and Og, king of Bashan, for his steadfast love endures forever;
and gave their land as a heritage, for his steadfast love endures forever;
a heritage to Israel his servant, for his steadfast love endures forever.
It is he who remembered us in our low estate, for his steadfast love endures forever;
and rescued us from our foes, for his steadfast love endures forever;
he who gives food to all flesh, for his steadfast love endures forever.
Give thanks to the God of heaven, for his steadfast love endures forever
Think about these statements for a second: ...to him who struck down the firstborn of Egypt, for his steadfast love endures forever...
This doesn't sound like our definition of love, does it? Here we see God enacting judgment against the Egyptians, by striking down their firstborn. Here's how Webster defines love (the first of several): strong affection for another arising out of kinship or personal ties
Do you ever wonder if our definition of love falls dramatically short of reality?
Saturday, October 11, 2008
Dynamic Inheritance in Perl
Ok, I discovered this little tidbit while working on a relatively extensive project in Perl. I came across an issue where I had several OS-based "abstract" classes written in Perl (yeah, I know -- OOP in Perl is nothing but trouble), and I needed to inherit from one of them. The trick, however, was to do it dynamically, depending on the OS I was currently working on.
Casting scalars to functions and even classes is a pretty simple thing.
Consider the following example in foo.pl:
The result of executing this code is fairly simple:
It's also possible to cast a scalar to a package/class type, allowing more flexibility on which objects or modules are called at run time.
Consider the following two files, foo.pl, bar.pm, baz.pm:
foo.pl:
bar.pm:
and baz.pm:
Now, execution looks like this:
Of course, there are some severe consequences of doing such practices. But, in my opinion, none of them compare to what else you can do with Perl's "cast-ability."
Consider the following hiearchy: Class linuxFoo is a class, specific to the Linux OS. Class solarisFoo is also a class, specific to the Solaris OS. Class Foo wants to inherit from either, but only does so in accordance to the OS it's currently running from. Here's the code:
linuxFoo.pm:
solarisFoo.pm:
Foo.pm:
and test.pl:
The result of running this script on two different operating systems (linux and solaris) is as follows:
Now, why is this a bad idea??
Creating function references on the fly via string values is always iffy. It requires a full-knowledge of the underlying code in order to correctly identify which methods are required. Though it's possible to abstract this out to some extent (forcing function/method names to use a value which is immutable for the system--e.g. the OS type), it still creates a brittle interface in which to work.
Dynamically creating and using modules is likewise a bit iffy as well. Should a module need to be refactored in the future (or is replaced with a different one), this forces the programmer to update the string which is used to create it.
Either way, the ability to use a string value to execute a function or use a module is tenuous at best. Dynamic inheritance, however, is downright dangerous. Users can take objects and randomly redefine their hierarchical structure however and whenever they want. Languages such as Java and C++ (to name a few) prevent this by statically typing their classes at compile-time. This forces the contracts imposed by inheritance and interfaces (e.g. interface methods are always implemented, inherited methods are always present via the parent, etc.).
Dynamic inheritance throws it all out the window. If you have a Dog object, it can randomly inherit from a Wheel object. Not only this, it can inherit from a Wheel after it's already inherited from a Fire Hydrant. Ok, the rule of odd and bizarre inheritance structures is present in all languages. But redefining the structure at any point in the code, without compile-time checks, makes Perl a fun, but screwy and dangerous language to program in.
...of course...some would say not to do OOP in Perl, which is why I'm transitioning to Python...
Casting scalars to functions and even classes is a pretty simple thing.
Consider the following example in foo.pl:
#!/usr/bin/perl
my $func = shift;
my $result = &$func(@ARGV);
print "$result\n";
sub add {
my ($x, $y) = @_;
return $x + $y;
}
sub subtract {
my ($x, $y) = @_;
return $x - $y;
}
The result of executing this code is fairly simple:
# perl foo.pl add 1 2
3
# perl foo.pl subtract 2 1
1
It's also possible to cast a scalar to a package/class type, allowing more flexibility on which objects or modules are called at run time.
Consider the following two files, foo.pl, bar.pm, baz.pm:
foo.pl:
#!/usr/bin/perl
my $pkg = shift @ARGV;
require "$pkg.pm"; # only load the package specified on the command line
my $class_ref = $pkg->new();
$class_ref->to_string();
bar.pm:
#!/usr/bin/perl
package bar;
sub new {
my $proto = shift;
my $class = ref $proto || $proto;
my $self = {};
bless ($self, $class);
return $self;
}
sub to_string {
my $self = shift;
return "bar says hello!\n";
}
1;
and baz.pm:
#!/usr/bin/perl
package bar;
sub new {
my $proto = shift;
my $class = ref $proto || $proto;
my $self = {};
bless ($self, $class);
return $self;
}
sub to_string {
my $self = shift;
return "baz says hello!\n";
}
1;
Now, execution looks like this:
# perl foo.pl bar
bar says hello!
# perl foo.pl baz
baz says hello!
Of course, there are some severe consequences of doing such practices. But, in my opinion, none of them compare to what else you can do with Perl's "cast-ability."
Consider the following hiearchy: Class linuxFoo is a class, specific to the Linux OS. Class solarisFoo is also a class, specific to the Solaris OS. Class Foo wants to inherit from either, but only does so in accordance to the OS it's currently running from. Here's the code:
linuxFoo.pm:
#!/usr/bin/perl
package linuxFoo;
sub new {
my $proto = shift;
my $class = ref $proto || $proto;
my $self = {};
bless ($self, $class);
return $self;
}
sub to_string {
return "This is Linux-based functionality!\n";
}
1;
solarisFoo.pm:
#!/usr/bin/perl
package solarisFoo;
sub new {
my $proto = shift;
my $class = ref $proto || $proto;
my $self = {};
bless ($self, $class);
return $self;
}
sub to_string {
return "This is Solaris-based functionality!\n";
}
1;
Foo.pm:
#!/usr/bin/perl
package Foo;
sub new {
my $class = shift;
my $os = $^O; # this gets the OS, in case you don't know
# require the correct module, and use it as the parent
my $pkg = $os . "Foo";
require "$pkg.pm";
our @ISA = $pkg;
my $self = $class->SUPER::new();
bless ($self, $class);
return $self;
}
sub to_string {
my $self = shift;
return $self->SUPER::to_string();
}
1;
and test.pl:
#!/usr/bin/perl
use Foo;
my $class_ref = Foo->new();
print $class_ref->to_string();
The result of running this script on two different operating systems (linux and solaris) is as follows:
# perl test.pl # on linux
This is Linux-based functionality!
# perl test.pl # on solaris
This is Solaris-based functionality!
Now, why is this a bad idea??
Creating function references on the fly via string values is always iffy. It requires a full-knowledge of the underlying code in order to correctly identify which methods are required. Though it's possible to abstract this out to some extent (forcing function/method names to use a value which is immutable for the system--e.g. the OS type), it still creates a brittle interface in which to work.
Dynamically creating and using modules is likewise a bit iffy as well. Should a module need to be refactored in the future (or is replaced with a different one), this forces the programmer to update the string which is used to create it.
Either way, the ability to use a string value to execute a function or use a module is tenuous at best. Dynamic inheritance, however, is downright dangerous. Users can take objects and randomly redefine their hierarchical structure however and whenever they want. Languages such as Java and C++ (to name a few) prevent this by statically typing their classes at compile-time. This forces the contracts imposed by inheritance and interfaces (e.g. interface methods are always implemented, inherited methods are always present via the parent, etc.).
Dynamic inheritance throws it all out the window. If you have a Dog object, it can randomly inherit from a Wheel object. Not only this, it can inherit from a Wheel after it's already inherited from a Fire Hydrant. Ok, the rule of odd and bizarre inheritance structures is present in all languages. But redefining the structure at any point in the code, without compile-time checks, makes Perl a fun, but screwy and dangerous language to program in.
...of course...some would say not to do OOP in Perl, which is why I'm transitioning to Python...
Subscribe to:
Posts (Atom)