lunes, 29 de marzo de 2010

Scheme and home-made objects

Scheme is functional. Functional and minimalist.

But its power to build higher abstractions with the basic toolset it provides, allows us to build a pseudo Object oriented system by ourselves.

That's what SICP 3.1 - 3.4 exercices are about:

Using the closure property we have learnt about in chapter 2, and the just revealed set! function, we can build objects with private state to the world.

We'll use the classical bank account exercice. We create it with a initial amount of money and we can deposit money and withdraw money (iif we have enough money there).

At the end of the 4 exercices we should have a way to generate password protected bank accounts, which remember not only the password but how many wrong passwords you have entered in a row. If you fail thrice, it'll call the cops.

To solve this little problem (that, on the other hand I love because of its well defined objectives and dose of reality) we'll first have a make-monitored function, that counts how many times it's been called. make-monitored procedure gets a procedure as a parameter, and outputs a prodecure that is like the one entered, but with the counter stuff added. we could say it makes wrapped functions (decorated if you come from python).

The password protected account uses just an extra local variable to the closure that has the password.

the usage is like

(define pw-acc (make-protected-account 'secretp4ss 100))
((pw-acc 'secretp4ss 'deposit) 10) => ok
((pw-acc 'wr0ngpass 'deposit) 10) => fail
((pw-acc 'wr0ngpass 'deposit) 10) => fail
((pw-acc 'wr0ngpass 'deposit) 10) => call-the-police

I don't like that when a wrong pass is passed as an argument, the output is applied to the argument (10 in this case), and scheme doesn't know how to apply it.

I've worked partial solutions but none convinced me one being flattening the way to call the functions (pw-acc 'pass 'deposit 10) but this way, the password protected account had to know about how many parameters received each function. The other solution is returning a dummy functions that accepts one parameter in case of wrong password. Unfortunately, here we just accept 1 parameter, so we are limited too.

Any suggestions are very welcome