Tuesday, January 4, 2011

Cartesian

I see your hacky method overloading ...

Luckily with Python you can implement your own hacky little overloads.


from itertools import product

def argslist(args):
return [ tuple(t) for t in product(*[a.split('|') for a in args]) ]

class Signatures(defaultdict):
def __init__(self):
self.seen = defaultdict(set)
defaultdict.__init__(self, list)

def __setitem__(self, key, item):
if isinstance(key, tuple):
m, args = key
for k in argslist(args):self.seen[m].add(k)
self[m].append(item)
else:
defaultdict.__setitem__(self, key, item)

def __contains__(self, (m, args)):
for k in argslist(args):
if k in self.seen[m]:
return True


def parse_sigs():
api = PyQuery(filename='api.xml')
sigs = Signatures()

for sig in api('entries entry[type=method] signature'):
entry = sig.getparent()
name = entry.get('name')

for args in arg_combinations(PyQuery(sig)('argument')):
k, v = parse_sig(name, args)
v.update({'sig': PyQuery(sig)})

if k:
key = (k, tuple(v['types']))

if key not in sigs:
sigs[key] = v

return dict(sigs)

'toggle': [{'args': ['handler(eventObject)', 'handler(eventObject)'],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle(handler(eventObject), handler(eventObject))',
'types': ['Function', 'Function']},
{'args': ['handler(eventObject)',
'handler(eventObject)',
'handler(eventObject)'],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle(handler(eventObject), handler(eventObject), handler(eventObject))',
'types': ['Function', 'Function', 'Function']},
{'args': [],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle()',
'types': []},
{'args': ['duration'],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle(duration)',
'types': ['String']},
{'args': ['callback'],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle(callback)',
'types': ['Callback']},
{'args': ['duration', 'callback'],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle(duration, callback)',
'types': ['String', 'Callback']},
{'args': ['duration', 'easing'],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle(duration, easing)',
'types': ['String', 'String']},
{'args': ['duration', 'easing', 'callback'],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle(duration, easing, callback)',
'types': ['String', 'String', 'Callback']},
{'args': ['showOrHide'],
'name': 'toggle',
'sig': [<signature>],
'sig_str': 'toggle(showOrHide)',
'types': ['Boolean']}],

I haven't written tests (in javascript) but those sigs look fairly legit

Method (Overload) Madness

    _toggle: jQuery.fn.toggle,

toggle: function( fn, fn2, callback ) {
var bool = typeof fn === "boolean";

if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
this._toggle.apply( this, arguments );

} else if ( fn == null || bool ) {
this.each(function() {
var state = bool ? fn : jQuery(this).is(":hidden");
jQuery(this)[ state ? "show" : "hide" ]();
});

} else {
this.animate(genFx("toggle", 3), fn, fn2, callback);
}

return this;
},


....

animate: function( prop, speed, easing, callback ) {
var optall = jQuery.speed(speed, easing, callback);

if ( jQuery.isEmptyObject( prop ) ) {
return this.each( optall.complete );
}


....

jQuery.extend({
speed: function( speed, easing, fn ) {
var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
complete: fn || !fn && easing ||
jQuery.isFunction( speed ) && speed,
duration: speed,
easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
};

opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;

// Queueing
opt.old = opt.complete;
opt.complete = function() {
if ( opt.queue !== false ) {
jQuery(this).dequeue();
}
if ( jQuery.isFunction( opt.old ) ) {
opt.old.call( this );
}
};

return opt;
},





It's interesting. I thought they would have a more sophisticated and abstract dispatch method. Something declarative and usable by plugins.

I was hoping to be able enumerate the different valid signature types but I have a feeling there isn't going to be some 'easily' exploitable pattern. The args aren't optional in a left to right manner such that for all optional args all args to the left have been optioned. You can call toggle with a callback function as the sole argument. Complicating things somewhat more is the fact that some arguments are described as accepting multiple types. Duration can be a number or string.

fadeTo Shenanigans


Yet the following works perfectly


$(this).fadeTo(function(){ console.log('weird')}, Math.random());

Not that it would be a good idea to rely upon implementation quirks


I'm just interested in automatically computing the different valid combinations of working signatures. Should be doable. Working left to right, taking the first combination of each signature. Cheating for a second and altering my routines to swap out things like "String|Number" to "String" I can see I'm on the right path



'toggle()': {'args': [], 'name': 'toggle', 'sig': [], 'types': []},

'toggle(Boolean)': {'args': ['showOrHide'],
'name': 'toggle',
'sig': [],
'types': ['Boolean']},
'toggle(Callback)': {'args': ['callback'],
'name': 'toggle',
'sig': [],
'types': ['Callback']},
'toggle(Function, Function)': {'args': ['handler(eventObject)',
'handler(eventObject)'],
'name': 'toggle',
'sig': [],
'types': ['Function', 'Function']},
'toggle(Function, Function, Function)': {'args': ['handler(eventObject)',
'handler(eventObject)',
'handler(eventObject)'],
'name': 'toggle',
'sig': [],
'types': ['Function',
'Function',
'Function']},
'toggle(String)': {'args': ['duration'],
'name': 'toggle',
'sig': [],
'types': ['String']},
'toggle(String, Callback)': {'args': ['duration', 'callback'],
'name': 'toggle',
'sig': [],
'types': ['String', 'Callback']},
'toggle(String, String)': {'args': ['duration', 'easing'],
'name': 'toggle',
'sig': [],
'types': ['String', 'String']},
'toggle(String, String, Callback)': {'args': ['duration',
'easing',
'callback'],
'name': 'toggle',
'sig': [],
'types': ['String',
'String',
'Callback']},

I could make a special class for the the types currently represented by a string sourced directly from the xml. This could compare "String|Number" == "Number" as true. Then tuples could be compared ('String|Number', 'Callback') == ('Number', 'Callback')

5 minutes of fame

Don't really know how much you can really read into an online test, but seeing I did well I'll not criticize it too much :) Not bad after such a big break.


The pay on oDesk is pretty lousy but it's all relative. If you earned 10 dollars an hour and lived in Cambodia? You can live in a resort on the beach for 500 a month there and it gets a lot cheaper than that ...

Brushing Up

Some eBooks I have been, am currently, and plan to be, reading

  • jQuery in Action
  • JavaScript - The Definitive Guide - 5th Edition
  • PacktPub.Firebug.1.5.Apr.2010
  • Rapid GUI Programming with Python and Qt - The Definitive Guide to PyQt Programming
  • OReilly.CSS.The.Missing.Manual.2nd.Edition.Sep.2009
  • Selenium 1.0 Testing Tools Beginner’s Guide
  • JavaScript Testing Beginner's Guide 2010 Packt
  • SQL Pocket Guide, Third Edition
  • Pro JavaScript with MooTools - Learning Advanced JavaScript Programming

SRS, jQuery

Back

My dear readers will be glad to know that I'm back. Where the hell have I been I imagine them asking ( I must have a great imagination, considering noone reads this blog! )

For the last year or so I've been studying music, one of the great unrequited loves in my life. I realised, or shall I say, I came to an even deeper understanding of, how profoundly untalented a musician I am. This is not to say that I don't believe I have potential but I'm positive it will take a Bruce Lee like zeal to unleash and heretofore unseen training methods. I haven't given up. I'm just taking a timeout to develop more programming skills to apply to the problem.

Throughout the year struggling away at ear training, using the available software I found myself yearning for something better. Being one of those arrogant "I could do this better" programmer types cursed also with a low pain threshold ("I have to use a mouse?? kill me!") ideas started to form in my mind. I didn't have the time or inclination to work on any of them however as I was busy studying and pretty much burned out on anything IT related.

But that's never here nor there. The central topic of this blogpost is 'scheduled repetition software'. Why lead in with your mediocre musicians lament?

Well, if you ever *completely stopped* something for any length of time you'll know the danger of gaining rust and losing insights. In the Skydiving world they call this state 'uncurrent' and you are considered a danger to yourself and others if you go for longer than a few months without jumping. We've all heard the "Use it or lose it" maxim.

Having finished up the year of study, I realised I needed some work and decided I should brush up on some of my old programming skills. Ouch! I've been somewhat blessed with a pretty good long term memory and retention. However, there's so much I just plain forgot.

Little details that before were readily available were now lost leaving me no recourse but to use references. "Where do I import that module from again?" "How do you get hg to automatically update server side?" "What was the keybinding for that command?" "The trigger for that snippet?" "What was the difference between left outer joins and ... "

And so on.

At one point during the year, I actually memorized 72 ascending musical intervals over four or five days. You think I could recall them a month later? No. Cramming doesn't work. You need to review. I can recall the intervals in the key of C and some in G/D/E but most I've forgotten.

Now I was considering studying this year also. It occured to me that it would be hard to maintain a decent skill/knowledge level to be able to work efficiently enough that I wouldn't be better off just digging ditches.

I knew it would be futile to try and cram in a heap of study over the holidays.


  
TODO:
Brushup on WebDev

jQuery in action.
CSS, The Missing Manual.
Firebug, Beginners Guide
SQLAlchemy tutorial
Genshi templating

I've done cramming in the past with things like Django (for an ill fated project ...), and you invariably forget it unless you use it day to day until it's burned into your long term memory.

How to bypass the need for a long period of 'day to day'? How to get something burned into your memory 'unnaturally'?

One thing you learn as a musician, is that you really need to apply 'deliberate practice' to get better. I'm not sure it's something many programmers do. At least I know I never did. In fact even when 'current' there were somethings I routinely used a reference for, even as little as a week between, just because my mind was habitually forgetful.

I left school at 12 years of age, obviously never attending university. Needless to say my study skills aren't very sophisticated. I actually find this thought rather encouraging as I know I'm miles from having plateued. There's lots of "low hanging fruit" ready to be picked.

So I had 6 weeks until school started again (at this point I planned on returning to study). I realised I should probably read into some study tips.

I downloaded a bootleg copy of the Memletics manual, which goes into quite some depth about the most efficent methods for learning.


  • Nutrition.
  • Exercise.
  • Attitude.
  • SRS.

I've still yet to apply most of what I read in there. If you think turning short term memory into long term memory is hard try developing new habits!

The biggest change in my learning habits is the use of SRS software. In fact I even got in some daily revisions on XMAS day.


Enter Anki


Anki is an implementation ( PyQt ) of software based flashcards. What makes this different to normal flashcards is that it intelligently schedules your cards for repetition at a time when it thinks you'll forget. I guess by now you have gleaned that SRS is an acronym for Scheduled Repetition Software.

The cards are html with all that entails: you can embed sounds/images and hyperlink. It has some other cool features like 'download shared deck'.

In fact, I found that someone had created a jQuery deck with roughly 180 cards.

Now, as I've learned there's something of an art to creating flashcards. You really need to reduce the amount of information to one or two discrete chunks.

This of course violates your prejudices against redundancy. IIRC, and I'm pretty sure I do (at least I remember this!), there was a meme floating about by the name of DRY, "Don't repeat yourself". With flashcards, scheduled REPETITION ones at that, the whole point is for repetition so that's OK.

As Anki is implemented in Python/PyQt and is extensible via plugins, one of the first things I did was to create a PYRO based bridge between it and my python extensible editor.

I'd copy/paste text from pdfs websites into a text buffer, manipulating the information into Q/A form then push 10 - 20 cards at a time using the multiple selection capabilites of my editor.

This information reorganizing process itself is invaluable as it really forces you to go beyond habitual skimming.

This requires some time and discipline and feels like a lot of work so I'd imagine it's not something everyone will have the stomach for. However, 'slow is fast'. What's the alternative? If you spend a few hours skimming and within a few weeks can recall nothing of value you've wasted your time. You have to think long term.

If it's something you think you'll eventually want/need to know then it's a good idea to spend the time upfront. How many times have you wasted countless hours fucking about blind, cause of artificial deadline pressures? I know people who have been developing for ages who always 'too busy' to RTFM.

Software development is complex. How can what is basically glorified rote memorisation really help?

How can you make critical implementation decisions if you don't know the frameworks you are using? How many times have you reinvented the wheel, because of lack of knowing your options? How much more creative can you be if you really know your 'material' and can think clearly about possibilities? It's what makes an expert and expert.

I applied Anki to brushing up on CSS, jQuery, Firebug and am learning the PyQt framework. At the rate I crammed some of it in, I doubt I'd have retained much without Anki.


jQuery Examples


One of my projects I've been tinkering on lately is a flash card export of the jQuery API raw xml dump. I wish to create flash cards going from {short_description : method_name} and its inverse {method_name, short_description}

Not only that but I want each html card to contain links which open up the example code in my editor. Luckily my editor can run commands argumented via the command line. I created a custom sblm:// protocol which allows commands to be sent in the query string.

I created a routine to determine all valid combinations of arguments so I can memorise the signatures of routines and create snippets. ( I'll have to make it a little smarter to filter the conflicting variations somehow. There's only so many ways a function can interpret a single boolean for instance )


    def arg_combinations(args):
args_n = (int(bool(e.get('optional', False))) for e in args)

for n in xrange(2 ** sum(args_n)):
opt_args = []
n_optional = -1

for arg in args:
optional = arg.get('optional')
if optional: n_optional += 1

if not optional or optional and n & (2 ** n_optional):
opt_args.append(arg)

yield opt_args

 'toggle()': {'args': [], 'name': 'toggle', 'sig': [<signature>], 'types': []},

'toggle(callback)': {'args': ['callback'],
'name': 'toggle',
'sig': [<signature>],
'types': ['Callback']},
'toggle(duration)': {'args': ['duration'],
'name': 'toggle',
'sig': [<signature>],
'types': ['String|Number']},
'toggle(duration, callback)': {'args': ['duration', 'callback'],
'name': 'toggle',
'sig': [<signature>],
'types': ['String|Number', 'Callback']},
'toggle(duration, easing)': {'args': ['duration', 'easing'],
'name': 'toggle',
'sig': [<signature>],
'types': ['String|Number', 'String']},
'toggle(duration, easing, callback)': {'args': ['duration',
'easing',
'callback'],
'name': 'toggle',
'sig': [<signature>],
'types': ['String|Number',
'String',
'Callback']},
'toggle(easing)': {'args': ['easing'],
'name': 'toggle',
'sig': [<signature>],
'types': ['String']},
'toggle(easing, callback)': {'args': ['easing', 'callback'],
'name': 'toggle',
'sig': [<signature>],
'types': ['String', 'Callback']},

I wonder if you really can pass a single string as an arg and have the toggle function determine whether you meant duration or easing? I'll have to try it our or better yet, look at the jQuery soruce

For purposes of automatically creating snippets I guess you really only want to look at the different signature types. jQuery uses anonymous functions a lot and literal string based arguments so creating snippets with placeholder args already quoted and function(){} inline seems like a decent idea


Web Snippets


There's a reason iterative development is usurping upfront design methodologies. We are fallible and mostly lacking detailed imagination. Our most glaring and atypically ungrudging admission: the fact we are so obsessed with testing.

I'm a great believer in efficient text editing. This shortens your feedback loop. If you can input text twice as fast you get through, I dunno, probably not twice as many, but a lot more 'fuckups'. Iterations!

The thing about snippets I've found is that unless I can recall instantly the abbreviation, I'll tend to just type in the whole words.

Now this really ties back to what I was saying before about 'deliberate practice'

In theory, if you practiced enough you could use completely arbitrary 2 letter combinations to compress an API worth of words down. However, memorising, even with SRS, is easier with some mnemonics so...

I've actually written some routines which will take a list of words and attempt to create ideal abbreviations and ensure unique.

One of the routines uses the Carnegie Mellon University Pronouncing Dictionary, cmudict for short, found in the nltk toolkit.


    def rank_letters(wd):
if not wd in CMU: return []

cmu = ''.join(['_' if ch[-1].isdigit() else ch for ch in CMU[wd][0]])
cmus = defaultdict(int)

mapping = '^(\\w)_|_(\\w)_|(\\w)_|_(\\w)$|_(\\w)'

for i, w in enumerate(mapping.split('|')):
for m in re.finditer(w, cmu):
ch = m.group(1).lower()
if ch in wd: cmus[ch] = max(i+1, cmus[ch])

return sorted(cmus.keys(), key=lambda k: (cmus[k]))

Intuitively I sensed that words surrounded by vowel sounds are the 'strongest' letters in a word, followed by those adjacent to only one. It seems to work reasonably well for such a crude method.


eg
document - DocuMeNt - dm
border - BorDer - bd

I also used the words corpus to create routines to decompose composite words.


mouseup - mouse, up - mu
mousedown - mouse, down - md

I'm going to create desc/entity flashcards and snippets also for html elements/attributes and css property/values.

With my editor at least, the bindings are smart enough to know when the cursor is inside a tag. eg. <|div> Why the hell type in annoying long character sequences when the set of identifiers compresses down to one, two, maybe three (ouch) character ids?

Over a course of weeks, you could, with SRS, systematically memorise the entire html set of elements and their attributes along with related snippet abbreviations. Shld I sy abrv instd?

It would be analogous to touchtyping. A lifetime of benefit for a short period of practice.

On second thought ... A lifetime of entering html/css? There's a horrid thought...


Statistics


Ideally I'd like to give the most frequently used entities the most suitable and short abbreviations, one character ones at times.

Google apparently did a massive study looking at web authoring statistics. They have the data as to which elements should receive the honorary 1 keyers.


Namespaces


You mean there's other javascript snippet candidates other than jQuery? Poses some problems. Where there's a problem, there's a solution.

Tuesday, July 28, 2009

Consolation: It's not you, it's the other guy.

I have been doing some freelancing work but it hasn't really been buttering the bread on a consistent basis. I avoid PHP which doesn't really leave much else job wise. Normally I value my time and flexible working hours far more than dollars so a full time job isn't something I'd really look for. Once you have been poor long enough however you start resorting to desperate measures and thinking of all sorts of crazy ideas. Boredom sets in and you even do things like offer your services practically free. Fail with consolation:
it is also clear to me that you possess attributes that would make an excellent employee - talent, enthusiasm and dedication. I would have no issues with offering you work if I were able to get XXXX to that stage... I am more than happy for you to put me down as a reference for any job opportunities, as I would highly recommend you to any employer.
Now whether the guy was just politely fobbing me off or he actually meant that I'm not entirely sure half the time. I've never particularly thought of myself as `talented` when it comes to code. `Persistent` like a retarded dog who doesn't know when to stop, sure.

When you can't practically give yourself away and you again decide you really want stable cash what do you then? 'I know! I'll look for a *well paying* job. What a shrewd and cunning plan!'

As I'm starting to get reasonably fluent with python, not needing references every 10 seconds, I naturally looked for jobs using that. There were however none available that didn't require `3 years experience` and `knowledge of finance` etc. The `python` keyword did however turn up another interesting advertisement.

We're a Richmond-based software development studio specialising in web technologies such as Flex and Ruby on Rails. We are looking for a passionate and energetic developer to join our team of three.

We're more interested in what you can do than what you say you can do. So prove yourself with your attitude and with your code.

We're looking for someone who's spent their evenings and weekends working on their own projects, and has something to show for it. We have a particular love of open source collaboration, and you should too. Tell us about the projects you watch, and the projects you contribute to: do you have accounts with Github, SourceForge, or RubyForge?

We want to be floored by your enthusiasm to work with new products, programs, and languages. Dynamic or functional languages like Python, Ruby, Actionscript, Erlang, and Haskell are looked upon favorably. We're not interested in your academic transcript, your 2-day ScrumMaster black-belt, or your Microsoft certificates, but we are interested in real talent, sharp skills, and unmatched motivation.

You must send through a cover letter describing your pet projects or open source projects, example source code from the project, and your resume to recruitment@silverpond.com.au. We won't consider any applications which don't have all three.

Normally I wouldn't have even bothered applying for something like that but I thought, if that guy will give me a reference then I may as well try it. I didn't really have much time to create an application or research the position all that much as I was away on a trip helping my father with a building project. Being an unfit person who would normally spend way too much time on a computer, after a days work I was quite tired in my poor fitness. I mostly reused an old application for another Job at a game development firm.

I was somewhat suprised when I got a positive sounding response from the recruiter/director of the company "I'm free to chat late this week or early next week, so I'm looking forward to hearing from you"

We eventually had a chat a few days later, which I wasn't exactly well prepared for. There was some initial awkardness with some nerves causing to me blurt out "good thanks and yourself" completely out of phase. It then smoothened out somewhat and I was happy to find the team was a group of 20 somethings and that it wasn't an issue I didn't have any experience with the technologies they used. I didn't really have many decent questions prepared ( it was actually my first job interview! ) but regardless at the end I was left with the impression it went well enough. The recruiter wanted me to come in a few days later for some facetime with the rest of the team.

As it turns out I never got that opportunity. Someone else had done their homework and really impressed them so well with their phone interview they got the job solely on that. I found this out as after as I asked the recruiter for any particular reasons the other candidate was chosen (over me). I was very appreciative with the email he replied with:

1) The candidate we chose asked questions about the projects we're doing and suggested improvements to them

2) The candidate also outlined what he could contribute to the team, and offered a timeframe to do them in.

Of the 80 of so applicants it was between the candidate, one other person and yourself. Your energy and enthusiasm is highly commendable. I'll touch base with you later in the year, say November, and see where you're at.
Overall, I have mixed feelings. I'm somewhat disappointed that I didn't have greater time to research the company more and also that I didn't make better use of the time I did have. The biggest disappointment is the fact that I missed out on a job where they didn't care that I lacked a degree or even any real experience with their tools of choice. "I don't really know ruby.." I had said. "It won't be an issue" was the reply. Similar conversations re: git / rails / flex. However it's somewhat encouraging to have made the short list from 80 candidates. That I feel pretty good about.

Will I continue investigating ruby / rails? My only concern is that it seems somewhat wasteful to walk away from my python experience ( It's the libraries stupid ) for a language so similiar. My `next language` to learn has always been planned to be C then possibly assembly.

I wonder if I would learn much from ruby about programming in general coming from python. Perhaps the similarities would be actually a boon to recognizing core concepts and distilling an understanding, compared to something radically different where you have no reference? I'm not really sure and I doubt I could really know for myself unless I tried. However, at the end of the day; there *does* seem to be a lot more work available for ruby/rails as opposed to python.

I can't shake the nagging suspicion I have just been "It's not you it's XXXX"d twice.

I posted on facebook, "didn't get the job and wonders why he marginalizes himself learning obscure tool-sets". A friend commented:
And don't focus on tool-sets - focus on your general problem solving abilities, There are a million different ways to solve any programming problem these days. Key thing is to be adaptable.
I agree with the notion that general problem solving ability is more important than any particular toolset. However, if you had said ability *and* a proficiency with a particular toolset it would make sense to use them where possible. Using the `right tool for the job` is part of solving problems.

Python isn't exactly an `obscure` toolset, however if you are unwilling to work with PHP you definitely are marginalized. I have a very low pain threshold in general. PHP is painful. I don't like pain. Nuff said.

Of interest to me was that the recruiter during his `wish you all the best` phonecall mentioned that the ruby community met once a month (in my home city) Perhaps learning some ruby/rails and getting involved would at the least yield some freelancing contracts. Never really been to any geek meetups. Surely beer is involved?

Monday, July 27, 2009

Ruby Tuesday

IPython is a huge part of my workflow. How to replace it?

(1:24:57 PM) akalias: Does ruby have an equivalent to python's IPython ? ie a hugely enhanced shell with better completion / syntax coloring etc?
(1:25:32 PM) dominikh: irb with auto_indent and the "wirble" gem

I have sourced a few ruby/git ebooks