The Occasional Occurence
My Take on Multiple Constructors
March 17, 2010 at 05:38 PM | categories: Python, Software, computing, GeneralI noticed the same question on c.l.p that Steve Ferg responded to on his blog. I was feeling too lazy to respond to the thread earlier but I thought I'd throw my idea up on the ol' blog before wrapping up for the day.
I think this is a classic use-case for class methods. Here is my implementation.
class Vector(object): def __init__(self, x, y, z): self.x = x self.y = y self.z = z @classmethod def from_sequence(cls, sequence): return cls(*sequence) @classmethod def from_vector(cls, vec): return cls(vec.x, vec.y, vec.z) def __repr__(self): return "Vector(%s, %s, %s)" % (self.x, self.y, self.z) if __name__ == '__main__': print Vector(1,2,3) print Vector.from_sequence([4,5,6]) print Vector.from_sequence((7,8,9)) v = Vector(10, 11, 12) print Vector.from_vector(v);
Here is the output from running the script:
Vector(1, 2, 3) Vector(4, 5, 6) Vector(7, 8, 9) Vector(10, 11, 12)
I like the classmethod route because it is obvious what the code is doing, it makes it easy to add new from_\* methods and keeps the general __init__ method clean.
cw
That Sucks
March 17, 2010 at 12:25 AM | categories: stories, Family, GeneralSpent the morning working from a coffee shop. I was feeling hip and fresh.
I came home and was going to whip up a sammich for lunch and then get back to work.
Opened the bread to make the sammich and then had to go and bring the puppy back in the house. Eli had "accidentally" let him out. Oh well. I bring the dog in and return to the kitchen.
I got the ham and swiss laid out on the bread. Then I get called back out because Eli let the dog out again. Bring the dog and Eli in this time.
Back to making the sammich. It was taking longer than planned (something like 8 minutes had elapsed) but it was gonna be gooooood. I proceeded to drop some succulent bean sprouts onto my delicious lunch creation.
Panicked shouts from the living room.
"Curtis and Eli are peeing in the front yard!"
This just won't do.
I go and bring the boys in and deliver a fatherly lecture on the right and wrong times and places to pee outside. I send them to their room to clean it up. Super dad.
Super hungry dad.
I get back to the kitchen to finish making the sammich.
The dog ate the sammich.
That Sucks.
cw
Tagged Revision Log Messages in Mercurial
March 12, 2010 at 01:49 PM | categories: work, Software, computing, GeneralI work at YouGov and we use the Mercurial for revision control.
We tag every release in a MAJOR.MINOR.BUGFIX format. 2.32.2 for example.
Recently I wanted to get a summary of the commit log messages for each of the tagged revisions. Here is the magic command that got me the output that I wanted:
# get all log entries for releases tagged with a 2.31 MAJOR.MINOR hg tags | grep 2\.31 | cut -c33-36 | xargs -L1 hg log -r
cw
Evolution of a Haskell Function
March 11, 2010 at 01:23 PM | categories: Python, Software, computing, GeneralI'm going through Real World Haskell trying to get a handle on the Haskell programming language. Python is my current language of choice, but I like to learn new programming languages too.
So last night I was going over the chapter that introduces 'let', 'where', 'case' and guards and I wanted to try them out. I contrived a simple situation where I thought I could use them.
I made some Contestants and wanted to see if they were "valid" for some definition of the word. I chose that they had to have a real value for age (not Missing) and be 30 years old or older (I'm pretty sure the game is called "Who Wants to Be a 30-year-old Computer Nerd?").
Here is my implementation.
-- my parameterized type data Perhaps a = Is a | Missing deriving (Show) -- definition of a Contestant data Contestant = Contestant { name :: String, age :: Perhaps Int } deriving (Show) -- some contestants contestant1 = Contestant "Christian" (Is 31) contestant2 = Contestant "Sarah" Missing contestant3 = Contestant "Curtis" (Is 6) -- the validation logic contestantValid :: Contestant -> Bool contestantValid c = case age c of Missing -> False Is true_age -> oldenough true_age where oldenough a | a >= 30 = True | a < 30 = False -- some code to print the results of running the validation against contestants main = do print $ (contestant1, contestantValid contestant1) print $ (contestant2, contestantValid contestant2) print $ (contestant3, contestantValid contestant3)
I was pretty proud of myself. I used 'case', 'where' and guards (not to mention parameterized types - I reimplemented Maybe/Just/Nothing as Perhaps/Is/Missing).
But man, it seemed like a lot of code to do something simple.
As I was falling asleep I realized how I could simplify it. I could use pattern matching to easily handle the Missing case. It would also let me pull the age out of a Contestant with ease too.
Here is the contestantValid function updated to reflect that.
contestantValid :: Contestant -> Bool contestantValid (Contestant _ Missing) = False contestantValid (Contestant _ (Is age)) | age >= 30 = True | age < 30 = False
Quite a bit simpler. I patted myself on the back. It was less fancy than the first version, but at least I had some guards in there.
Then it hit me. I didn't need the guards.
contestantValid :: Contestant -> Bool contestantValid (Contestant _ Missing) = False contestantValid (Contestant _ (Is age)) = age >= 30
Well, so much for 'where', 'case' and guards. It sure is a boring function now, but I think the process of how I got there is interesting.
cw
Link: PiCloud Overview
March 11, 2010 at 10:50 AM | categories: Python, Software, computing, GeneralHere's a great overview of using PiCloud that goes beyond "hello world" type stuff.
For those of you who don't know, PiCloud is a cloud computing platform for Python that aims to simplify the task of running code in "the cloud."
cw