Archive for September, 2007

JavaScript: Functions are Constructors are Functions

2007-09-13

Some people seem to be a bit confused about the return value of a JavaScript function when used as a constructor. So what does «new Foo(some args)» evaluate to?

If the constructor returns an object then that is used; otherwise the return value is irrelevant and the newly constructed object is used.

The immediate and practical upshot this is that for a constructor it doesn’t matter whether you use «return» or «return this». I would say that a constructor’s normal job is to make objects so if you must return explicitly from a constructor then just use the simple «return» form.

The amusing and alarming upshot is that the behaviour of a function can be radically different according to whether it is invoked as a function or a constructor. Imagine you have a subtraction function:

function Sub(x, y) {
  return x-y
}

Invoke it like «Sub(9,5)» and it returns 4. What does it do when used in «new Sub(9,5)»? Well, technically the function still returns 4, but because 4 is not an object that value is ignored and the newly constructed object is returned instead. A new expression is guaranteed to evaluate to an object (or raise an exception).

Consider (at an interactive JavaScript prompt):

js> function Sub(x, y) {
  result = x-y
  return result
}
js> Sub.prototype.toString = function() { return 'I am a walrus' }
js> Sub(9,5)
4
js> result
4
js> new Sub(100,1)
I am a walrus
js> result
99

When invoked as a constructor we get a new object that prints as «I am a walrus» because of the toString method in its prototype. I have deliberately changed Sub so that it writes to a global variable so that you can convince yourself that it is being called in the constructor case even though its return value is not being used.

Do not do this at home!

I am not recommending the above, I just find it an amusing way to illustrate an obscure feature of JavaScript.

I recommend that you make it crystal clear which of your functions are constructors and never encourage anyone to call them as a normal function. The fact that all functions can be used as constructors (and vice versa, any constructor can be invoked as a function) is an attractive nuisance. Sure, you can avoid it by being careful, but it’s too easy to do accidentally. Douglas Crockford has an article about the attractive nuisance of fallthrough in switch, which is where I got the term.

The usual convention, which seems very sensible to me, is to start constructors with a capital letter. That’s makes them look a bit more like classes too.

To some extent you can protect yourself against accidentially calling a constructor as a function. You can test whether this is the global object (which it should be in a function) or not the global object (which it should be in a constructor). But only if you first remember what the global object is:

js> g=this
[object global]
js> function Foo() {
  if(this === g) {
    throw 'I am a constructor, not a function'
  }
}
js> new Foo()
[object Object]
js> Foo()
uncaught exception: I am a constructor, not a function

Because the first OO language I learnt was Dylan I find that the artificial separation of constructors and ordinary functions (which may or may not return fresh objects) is also attractive nuisance. It’s an attractive nuisance that has worked its way (like fallthrough in switch) into many programming languages: C++, Java, JavaScript. Even Common Lisp has it, though I suspect that unwrapped uses of make-instance are actively discouraged. In the other languages I mention, the idea that you might use something other than a constructor to get a fresh object is so unusual that there’s a name for this idea: factory method pattern!

Appendix: Standard References

All in ECMA 262 3rd edition.

Section 11.2.2 defines the semantics of the new operator. Which when used like this:

new Foo()

The semantics are to grab the Foo object and call its [[Construct]] method. When Foo is a constructor that you defined yourself, that is a JavaScript function, the [[Construct]] method is described in section 13.2.2 and has roughly the behavious I describe above: construct a «new Object()» (and let it be this); call the function; if it yields an object then use it, otherwise use this.

Python: Documenting Higher-Order Artefacts

2007-09-11

This is something that I would’ve touched on in my Introduction to Functional Programming in Python talk had it been about 4 hours long.

Suppose I make a nice healthy currying function:

def curry(f, l) : return lambda *r : f(l, *r)

and then use it to define a max function like this:

max=curry(reduce, lambda x,y : [x,y][x<y])

(in Python 2.5 instead of defining curry you can go «curry = functools.partial»)

(Aside: I really don’t know what to think of that code on the right hand side of the lambda. It’s more or less forced on me by the fact that that body of a lambda is an expression so I can’t use if. It’s also a compelling reason why Python will probably continue to use Iverson’s Convention for some while.)

I’m not saying that it’s necessarily good idea to define max like this, it’s a bit of a contrived example, but when you get used to higher order functions you end up defining a lot of really useful functions like this instead of using def statements. Sometimes such a function will be sufficiently useful that it will form part of a public interface, in which case it needs documenting.

The documentation for max is rubbish:

>>> help(max)
Help on function <lambda> in module __main__:

<lambda> lambda *r

The way to fix that is to give max an explicit docstring via its secret __doc__ attribute and a proper name via its __name__ attribute:

max.__doc__="""Return largest element of sequence."""
max.__name__='max'

Now the help looks like this:

>>> help(max)
Help on function max in module __main__:

max(*r)
    Return largest element of sequence.

The __name__ attribute means that max’s name correctly appears after «help on function» and in the function prototype. The __doc__ attribute appears as max’s description.

The way the argument list appears is slightly misleading, but I’ll leave it at that for now. Maybe there’s also a sneaky way to fix the argument list?

It occurs to me that curry could produce some sort of docstring automatically:

def okname(x) :
  """Return some okay name for any object."""
  def isnum(x) :
    """Return true if x is a number."""
    try :
      return complex(x) == x
    except Exception :
      return False
  def isstr(x) :
    """Return true if x is a string."""
    try :
      return str(x) == x
    except Exception :
      return False
  if isnum(x) or isstr(x) :
    return repr(x)
  try :
    if x.__name__ == '<lambda>' :
      return 'some anonymous lambda'
    else :
      return x.__name__
  except Exception :
    return 'some nameless object'

def curry(f, l) :
  r = lambda *r : f(l, *r)

  r.__doc__ = ('Curried application of ' +
               okname(f) + ' to ' +
               okname(l))
  return r

The documentation is not great, but it is slightly better than nothing:

>>> help(curry(reduce, operator.add))
Help on function <lambda> in module __main__:

<lambda> lambda *r
    Curried application of reduce to add

>>> help(curry(operator.add, 1))
Help on function <lambda> in module __main__:

<lambda> lambda *r
    Curried application of add to 1

>>> map=curry(reduce, lambda x,y : [x,y][x<y])
>>> help(map)
Help on function <lambda> in module __main__:

<lambda> lambda *r
    Curried application of reduce to some anonymous lambda

Along with the compiler module, the possibilities are endless.

Code Monk recalls PyCon UK

2007-09-10

Personal:

I should have definitely attended both days. Felt there wasn’t enough time to just meet people and chat, so the evening social events would have definitely helped. I also enjoy chatting at breakfast so maybe I should hotel it next year (or scam myself into the hotel’s breakfast room). Next year: attend as many days as possible!

Nobody else (that I saw) use a laser pointer and I think a couple of people could’ve done with one.

I should’ve investigated my bag more thoroughly to discover the conference schedule. Durr.

Conference:

Venue excellent once I’d found it. Given how awesome John Pinner and the rest of the committee were I feel that it would be reasonable to ask for a big 10 metre wide pink laser descending from the skies above and pointing at the building next year. When I was lost I asked several people if they knew where the conservatoire was and it was quite a while before I found someone who did. All the time I couldn’t have been more than 200 m from it!

Excellent organisation. John Pinner and the PyCon UK crew rule!

The talks I attended:

My «Introduction to Functional Programming in Python». I was very surprised by the high attendance and that makes me feel a bit guilty about slapping something together the day before. This was my first conference talk, I think it went quite well for all that. The room, the projector, Simon as chair, and the attendees were all excellent. I think I gave Simon and John Pinner a bit of a fright by not showing on the radar until 10 minutes before I was due to start. Sorry about that.

Julius Welby‘s «A Pythonista’s Year at Kew». I would have dearly loved to have seen more Python code, but on the other hand it was also really interesting to see what other people were doing with Python. Some excellent text processing war stories. This talk made me remember one of the things I like best about Python: it’s so easy to get real work done using it.

Jonathan Fine’s «From MathTran to PyTeX». (Has Latex 3 really been in development since 1992? Even a day after I’m still a bit shocked, and I still think my “that’s longer than perl 6!” heckle is amusing.) Anyway, MathTran looks already cool and PyTex looks like it should be cool. It’s an approach to the problem of how to make TeX sane that I hadn’t thought of. The approach is: treat TeX as a two-way piped coroutine, squirt TeX input in, get boxes out. Now TeX is a callable function. I remember having to submit batch jobs to run TeX, and now I can do it from a web page in a few milliseconds. Very cool. It’s been a while since I’ve used TeX in anger and I found the nostalgia simultaneously pleasant and a bit stomach churning. (aside: people use TeX to typeset Hieroglyphics, how cool is that?)

The break: At last I get to taste some of the coffee that I sponsored. It was okay. Good opportunity to chat to some Python dudes, which is always good.

Nick Efford and Tony Jenkins, «Python in Higher Education». Yay! I think we’ve all been appalled and depressed by the way that Java has taken over CS departments everywhere (even Cambridge has a Java course). Now Python is fighting back. I liked their mountain analogy. Also the power of just being able to whip out an interpreter in a lecture to answer questions. Great war stories, students saying “I felt restricted by C++”, 1st year students making stuff out of Python that is good enough to demo at PyCon UK!

Russel Winder‘s «Python is the Future of Build Systems». Seems like a guy on my wavelength. Clearly just wants to solve problems by making software and seems very hacked off by the current state of build systems. Everybody likes to bash autotools. A much more thorough investigation of various approaches to the build problem than I was expecting, using make, CMake, autotools, ANT, Maven, Rake, and Scons (and, does he mention Gant too?). CMake and Scons come out on top but only one of those has a real programming language behind it. I will definitely have to give Scons a second look (I abandoned it after brief flirtation a couple of years ago). The highlight was definitely when Russel switched the microphone off.

Lunch. Not bad at all.

Laura Creighton’s keynote. I’ve never heard of her and she seemed to assume that I (not me personally, but the audience in general) should have. Her talk was quite interesting, it turned out to be on software patents, the artificial opposition between Science and Engineering and the opposition between Arts and Engineering. It had nothing to do with Python. That’s not necessarily a bad thing; one thing Python programmers probably should be doing is talking to politicians about how they created all this stuff using these Open Source tools and they did it without a single patent. It was a bit scary when Laura directly addressed me in a kind of how-could-you-possibly-come-to-pycon-without-knowing-what-a-sprint-was-way to explain what a Sprint was.

Lightning Talks. Well these varied from the very entertaining and slick to the deserving and interesting but unprepared. Fun all round though. Any cool graphics went down well, even if they were presented to an audience of 200 on a laptop held at an awkward angle. Might be interesting to do one next year. For me Johnnie Stovall’s talk about the direct value of education via sprints was particularly compelling.

Python: where is your colon?

2007-09-10

I’ve just got back from the most excellent PyCon UK 2007.

One trivial observation that occurred to me is that I seem to be the only Python programmer that puts a space before the colon. Like this:

def double(x) : 
  return x * 2

I think the reason that I do that is that I think of the colon as being equivalent to the opening brace, «{», in a language like C, and of course I would never omit the space between the «)» and the «{» in «if(x) {».

Introduction to Functional Programming in Python

2007-09-10

I recently gave a talk «Introduction to Functional Programming in Python» at PyCon UK.

Slides (2.2e6 octet PDF)

Accompanying notes, including homework (49e3 octet PDF)

In another post I give my ramblings on PyCon as a whole.

It was my first talk and it was a very interesting experience. Thanks to all who attended (it was much more popular than I was expecting). It’s definitely something I should do more of.

[2008-05-06: I gave a talk with the same title but about 50% different content at the spring UKUUG]

A judgement on DNA

2007-09-06

The BBC reports that someone suggests that everyone in the UK, resident or visitor, be recorded on a DNA database. The issue is not that someone thinks this, says it, or has it reported by the BBC, but…

How did this man come to be a judge?

Stupid keyboard, stupid shift; a proposal for better key sensing

2007-09-04

On my Apple keyboard (the white wired one, circa 2003, with an ergonomic curve to it) if I press both Shift keys down then it disables most of the QWERTY row. I guess this is some sort of ghosting or masking. Is it useful to be able to separately detect the two Shift keys? Why aren’t they wired on the same row/column intersection? That would eliminate this sort of masking. This makes me think far too hard about keyboard wiring designs and microcontroller pin minimisation. Observation: pin minimisation is the root of all keyboard misdesigns (well except for problems with the actual shape, action, and layout of the keys).

The Matrix

Electrically, keyboards are arranged in a matrix of rows and columns with a switch (corresponding to an actual key) at the intersection of each row/column pair. Depressing a key closes the switches and forms an electrical connexion between the row and the column. A microcontroller uses a scanning algorithm to detect key presses: it regularly scans the rows and columns by driving each row bus in turn and sensing each column bus to detect which keys are depressed. Warning: this description is made up by me based on my ancient knowledge of the ZX81 hardware design. I have no idea how modern keyboards work, but it’s probably something very similar. Probably you can get a single chip for USD 1 that does all this driving and sensing of the matrix, has a register and some LED drivers for the Caps Lock light, and a USB interface all in one. I suspect Apple have very little choice in how the electrical wiring of their keyboard is made.

The number of microcontroller pins I need for a keyboard of N keys is p+q where p×q ≥ N. If we assume that the cost of a microcontroller is proportional to the number of pins it has, then we would do well to minimise the number of pins we require for the keyboard matrix. For a 40 key keyboard (the ZX81) an arrangement of 8 rows and 5 columns is optimal. This comes about because we can only place one key at the intersection of each row and column. If we try and place two or more keys at the same intersection then the scan algorithm can’t differentiate between them.

However if we can somehow differentiate between two or more keys at the same intersection then we could put more keys per intersection and thereby reduce the number of pins we require.

Capacitance is Key

Suppose we put a capacitor inline with each switch. Now when a key is depressed instead of a closed circuit between a row and a column we get a resonant CR circuit. We can still use the scanning algorithm, but instead of driving the row bus with a constant voltage we drive it with a periodic signal. Obviously we should choose the period so that the CR circuit passes it. A 1.5 MHz square wave might be a good choice for a keyboard because we can get this from the clock used for the USB interface (12 MHz divided by 8). If we put different value capacitors on different key switches and drive the row with two different frequencies (1.5 MHz and 0.75 MHz say) then we can now detect two different keys at the same row/column intersection. We scan once at 1.5 MHz to detect one set of keys and scan again at 0.75 MHz to detect another set of keys.

For our ZX81 example with 40 keys we would need only 20 intersections which we can do with 4 rows and 5 columns, reducing our pin requirements from 13 to 9 pins. Awesome!

In general we save about 30% going from 1 key per intersection to 2 keys per intersection: we go from about 2×sqrt(N) pins to about 2×sqrt(N÷2) or sqrt(2)×sqrt(N). sqrt(2)÷2 is of course about 0.7.

More keys per intersection means greater savings, but also requires more frequencies, slower scanning (because each frequency requires an extra pass), and more stringent rejection requirements in the CR circuits.

For a really cheap and nasty keyboard, instead of having an open/closed switch inline with a capacitor simply make the keybaard so that two metal plates are brought close together when the key is depressed. The two metal plates form a capacitor whose value can be controlled by changing the area of the metal plates. (In fact, don’t really cheap and nasty keyboards use this principal already?) The challenge would be to reliably detect keys with different capacitance.

Javascript: switch

2007-09-03

The switch statement in JavaScript is more or less borrowed from C. But unlike C where the case labels have to be constant expressions the case labels in JavaScript can be any expression.

I expect that they did this is so that, despite the fact that JavaScript has no notion of constant, you can go:

switch(node.type) {
  case Node.ELEMENT_NODE: blah blah
  case Node.ATTRIBUTE_NODE: blah blah
  case Node.TEXT_NODE: blah blah
}

rather than the less clear:

switch(node.type) {
  case 1: blah blah
  case 2: blah blah
  case 3: blah blah
}

(Though strangely, you see a lot of people referring to DOM enumeration values (like Node.ELEMENT_NODE) by their numeric value.)

Of course in C you’d use enumeration members because they’re constants and it would look much the same.

The fact that the case labels are general expressions is reminiscent of CASE/WHEN from BBC BASIC V (on the Archimedes) and I am reminded of a hackish abuse I was once told about: you put some constant expression in the switch, true say, and a bunch of variable expressions, a bunch of conditionals, in the case statements. Like this:

switch(true) {
  case a>b : blah blah
  case foo(bar)=='spong' : blah blah
  case isNaN(x) : blah blah
}

All day I’ve been trying to think of some reason why this might be remotely useful.

Follow

Get every new post delivered to your Inbox.