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:
    pass

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.)