Friday, March 01, 2013

Correction: Javascript NOT more dynamic than Python

EDITED: Adam showed me that I had missed a way to do something similar in Python as I added below.

After a very long hiatus, I'm finally back and working on a web version of rur-ple, my "Karel the Robot in Python" program.  Since it's going to be on the web, I have decided to have both a Javascript version and a Python version (using Brython).  As I was exploring javascript prototype-based "inheritance" pattern, I found  what I think is a neat way to illustrate how dynamic the method lookup can be in Javascript, in a way that has (to my knowledge) no parallel in Python.

As in rur-ple, I have a robot "class" called UsedRobot which is broken (i.e. like the original Karel it can only turn left, etc.).  For completely separate reasons, I had decided that I would actually implement a PrivateRobot "class" within the RUR  namespace, which would not be directly exposed to the user, and have UsedRobot "inherit" from it.

Here's what one can can do

var r = new UsedRobot();      // does not have a turn() method
RUR.PrivateRobot.prototype.turn = RUR.PrivateRobot.prototype.turn_left;   // give such a method to the "parent"
r.turn();  // turns left using the new parent's method.
UsedRobot.prototype.turn = RUR.PrivateRobot.prototype.__turn_right;  //give different method to "child"
r.turn();  //  turns right - look up stops at "child"
delete UsedRobot.prototype.turn;
r.turn(); // turns left again  - look up goes up to parent since method no longer exists in child.

I still prefer Python to Javascript ... but I find that one can do neat things in Javascript which (to my knowledge) can not be done in Python.   Caveat: the fact that something like the above can be done in Javascript does not mean that it should be done.

Adam, in the comments, pointed out that something similar can be done with Python, using instance.__class__ to modify the behaviour of a class.  For example:

class A:

class B(A):
    def turn(self):
        print("turn left")

def right(self):
    print("turn right")

b1 = B()
b2 = B()
a1 = A()
b1.turn()  # prints turn left
a1.__class__.turn = right
a1.turn() # prints turn right
b1.turn() # prints turn left
del b1.__class__.turn
b1.turn()  # prints turn right

Friday, February 08, 2013

Is there any merit to stepping back through the code?

After a long hiatus, I have gone back to work on a new version of my very first project - essentially a clone of Karel the Robot - this time delivered entirely via the web (not yet available though).  Like rur-ple, and Guido van Robot, and many others I am sure, the user will have the option of executing all the code without interruptions, or stepping through, one instruction at a time.  Since Javascript does not have  a "sleep()" function, the way I implemented the program was to create a series of frames (like a movie) which can be then played back at a given frame rate, or stepped through one frame at a time, etc.  This makes is easy to include the possibility of stepping back from a given frame instead of being restricted to only moving forward.  However, since I use the browser to evaluate the code (rather than creating my own interpreter), I do not have the information regarding the code line whose execution corresponds to a given frame.

I know that Greg WilsonBrad Miller,  and many others I am sure, have expressed opinions about this being a desirable feature in a teaching environment.  However, I don't want to implement things that are not needed (and will needlessly complicate the user interface) and, given the non-availability of the line of code which corresponds to a given frame, I am not sure that a really good case can be made for the possibility of going backwards.  (Note that I have implemented a "pause" instruction which would enable a user to effectively set a breakpoint and, knowing where they inserted this instruction in the code, be able to follow step-by-step
the result.)  The fact that *I* do not have a good use case for it right now does not mean that such a good use case exist.  So, dear reader, can you think of a situation where such a feature would be useful?  (in this type of programming environment.)