Tuesday, May 13, 2014
Python tutorial for beginners.
The first draft of my Python tutorial for beginners is now live. The previous link is for the tutorials; the actual code needs to be entered in Reeborg's World. There is also a Javascript version of the tutorial.
Tuesday, April 29, 2014
Collaborate on Reeborg's World using Mozilla's TogetherJS
If you go to http://reeborg.ca/world.html and click on "Start TogetherJS" at the top, you can get a URL to share with others. This hopefully will be found useful by teachers who can help their students remotely.
Note that the exact location of the Start TogetherJS button may change in the near future. Thanks to Ian Bicking and others at Mozilla for creating this amazing tool.
Feedback is welcome! ;-)
Reeborg's world: more options to share
RUR-PLE's primary goal was to create a very easy path for people that wanted to learn programming. The original version still had a significant hurdle to jump over for absolute beginners. They had to 1) download and install Python; 2) download and install wxPython; 3) download and unzip the files for RUR-PLE's distribution. This is probably considered to be trivial by the reader of this blog ... but it was not so for the users (some of whom were young children ... or their parents!) So, it really required to have someone nearby with some computer savyy and, since it required to install programs, some teachers could not use it without jumping through additional hoops to have it installed on the school computers.
As more users joined in, some volunteered to create "one-click" install files (.exe, .dmg, etc) for various systems. These were made available on Google code; however, since new downloads can not be added (due, I understand, to how this service was abused by some other "projects"), this means that yet a new home (after the original sourceforge site) would have to be found for updates. Furthermore, this does not solve the issue of installing software on school's computers.
These various facts were the main impetus behind my desire to create a web version as something with the absolute lowest barrier to entry. To my mind, this means no creation of user accounts. With no user accounts, there is nothing saved on the server. Still, it is useful for people learning to program to be able to save their results. So, I implemented:
As more users joined in, some volunteered to create "one-click" install files (.exe, .dmg, etc) for various systems. These were made available on Google code; however, since new downloads can not be added (due, I understand, to how this service was abused by some other "projects"), this means that yet a new home (after the original sourceforge site) would have to be found for updates. Furthermore, this does not solve the issue of installing software on school's computers.
These various facts were the main impetus behind my desire to create a web version as something with the absolute lowest barrier to entry. To my mind, this means no creation of user accounts. With no user accounts, there is nothing saved on the server. Still, it is useful for people learning to program to be able to save their results. So, I implemented:
- An automatic save of a program state when it's run successfully. This includes the code in the "library". It also saves the "world" that was selected, as well as the programming language (Python, Javascript of CoffeeScript). This way, when a user returns to the page, it restarts from where it was left off. However, this uses localStorage which is appropriate only when everything is done from a single browser.
- For students that may want to work on the school computer and at home, I implemented a way to save to files (hello USB keys...); this can be either the world selected (which the student can edit) or the program or the content of the library, each saved separately.
I thought this was going to be enough until I got an email from the Samsung folks behind the Junior Software Academy initiative. As I mentioned in a previous blog, they created a book based on rur-ple. They now would like students to take part in a mini programming contest and wanted to be able to have the students show their results. This works fine if rur-ple is installed on the computer they have ... but a web based solution was thought to be more interesting. So, I implemented a permalink utility which enables one to save the complete state (programming language, world definition, code in editor and library) and share this as a url. Here is a silly example.
One more thing I would like to do is to implement a collaborative mode using Mozilla's TogetherJS. However, this will require quite a bit more coding, based on what I saw in an earlier attempt, just after TogetherJS was announced.
Monday, April 14, 2014
Reeborg knows multiple programming languages
I wish I were in Montreal to visit my daughter, eat some delicious Saint-Sauveur bagels for breakfast, a good La Banquise poutine and some Montreal Smoked Meat for lunch... and, of course, attend Pycon. Alas....
In the meantime, a quick update: Reeborg now knows Python, Javascript and CoffeeScript. The old tutorials are gone as Reeborg's World has seen too many changes. I now am in the process of writing the following tutorials, all using Reeborg's world as the test environment
In the meantime, a quick update: Reeborg now knows Python, Javascript and CoffeeScript. The old tutorials are gone as Reeborg's World has seen too many changes. I now am in the process of writing the following tutorials, all using Reeborg's world as the test environment
- A quick introduction to Python (for people that know programming in another language)
- A quick introduction to Javascript (same as above)
- A quick introduction to CoffeeScript (same as above)
- An introduction to programming using Python, for absolute beginners
- An introduction to programming using Javascript, for absolute beginners
- An introduction to Object-Oriented Programming concepts using Python
- An introduction to Object-Oriented Programming concepts using Javascript
Note that I have two "versions" of Javascript, one that uses JSHint to enforce good programming practices (and runs the code with "use strict"; option) and one that is the normal permissive Javascript.
If anyone knows of any other transpilers written in Javascript that can convert code client-side from language X into Javascript (like Brython does for Python, or CoffeeScript does naturally), I would be interested in adding them as additional options.
Thursday, March 13, 2014
Reeborg news
People reading this blog may be familiar with rur-ple (https://code.google.com/p/ rur-ple/), a Karel-the-robot clone using Python that I wrote. The robot's name in my version is Reeborg, hence the title of this post.
Since the last version was produced in 2009, rur-ple had been downloaded more than 11,000 times. Since people that download it do not need to contact me to do so, it is only through serependity that I find out where it is used. By doing some searches on the web, including videos on youtube, I found out that it has been used by elementary school children in Austria, high school children in the U.S. and by university students in the U.S. and Latin America as a tool to introduce Python.
Recently, Samsung contacted me and asked my permission (!) to produce a book based on rur-ple. They distributed free copies of this book yesterday to approximately 1000 Korean students.
So what you say?....
I am happy to announce that a test-version of "Reeborg's world" is now available online as a tool to learn Python. Like the desktop version (rur-ple) I wrote, it is free to use and does not require registration.
The first version of Reeborg's world was produced to teach Javascript; it is the default version available from http://reeborg.ca. It includes some 98 lessons (available in both English and French); the English version can be found directly at http://reeborg.ca/learn_js. html
I'm working on an "improved" version which can be found at http://reeborg.ca/learn_js_ dev.html
Following some comments by early adopters, the UI of this version is improved slightly and more changes are planned, including a graphical world builder, new images for the robot, the option to import from file and save to file programs and worlds, etc. I am also thinking of adding a collaborative option using https://togetherjs.com/.
This time, I will probably include a page on the site where I will ask teachers that use it to communicate with me to let me know in what context they use it, and keep track of it on a "wall of fame".
The proof-of-concept Python version, which is probably of greater interest for readers of this blog, can be found at http://reeborg.ca/learn_py_ test.html It is based on the "improved" version and uses Brython to translate the Python code into Javascript, which can then be executed using eval(), like the Javascript version does. I do not plan to do more work on it (including adapting the lessons to teach Python instead of Javascript) until I have nailed down the "improved" Javascript version.
If you want to quickly try the Python version to see what it can do, after dismissing the "contents window", I suggest you select (from the drop down menu showing "Alone" by default) the world "Tokens 1" and run the following program:
move()
take()
move()
put()
move()
I welcome any comments & suggestions about Reeborg's world; please feel free to email me directly.
Thursday, February 13, 2014
Importing modules in RUR-PLE
When I first started working on RUR-PLE some 10 years ago, I wanted to create a "safe" environment so that beginners using it could not be "tricked" by others into running malicious programs. So, before running a user program, I would parse it and prevent the use of keywords such as "chr", "exec", "eval", "input" and "import". However, I still wanted to teach the idea of "importing a module", so I created a "fake" module allowed the user to have the line
or
into their program, and this would import various "useful" definitions so that they would not have to retype them. I added a note to teachers at the bottom of the relevant lesson, telling them that they could get in touch with me if they wanted to remove the "import" restriction, and I would tell them how to modify the code.
Somewhere along the way, prompted by a discussion with a user, discussion whose details I have long forgotten, I removed the so-called useful module and enabled the import statement to be used. However, the lesson about the "import useful" module remained (and has been translated into other languages) as I just noticed, much to my embarassment.
Today, five years after I last modified the code, I was contacted by a teacher had read what I wrote and who wanted their students to be able to save their own functions and import them. Here's a way to do it. Note however it involves a bit of "magic" (at least from the point of view of the student).
First, just to demonstrate that import works, one can type the following:
import useful
or
from useful import turn_right
into their program, and this would import various "useful" definitions so that they would not have to retype them. I added a note to teachers at the bottom of the relevant lesson, telling them that they could get in touch with me if they wanted to remove the "import" restriction, and I would tell them how to modify the code.
Somewhere along the way, prompted by a discussion with a user, discussion whose details I have long forgotten, I removed the so-called useful module and enabled the import statement to be used. However, the lesson about the "import useful" module remained (and has been translated into other languages) as I just noticed, much to my embarassment.
Today, five years after I last modified the code, I was contacted by a teacher had read what I wrote and who wanted their students to be able to save their own functions and import them. Here's a way to do it. Note however it involves a bit of "magic" (at least from the point of view of the student).
First, just to demonstrate that import works, one can type the following:
import sys
print sys.path # python 2 syntaxturn_off()
Here is the output from the window below the robot world (I used the version installed by the .exe file)
['C:\\Program Files (x86)\\RUR-PLE', 'C:\\Program Files (x86)\\RUR-PLE\\library.zip']
I used a usb key (recognized as drive d: on my computer) to save the file my_def.py and containing the following:
from rur_py.cpu import rur_program
robot = rur_program()
def turn_around():
robot.turn_left()
robot.turn_left()
The first two lines contained the required "magic" so that our user-defined module can use all the same robot instruction that a "normal" program can. However, these instructions, such as turn_left(), must be preceded by "robot." [or any other name given to rur_program()].
Note that I could have used just about any name instead of "my_def".
Once we have saved this module, we can now use it. First, we need to make rur-ple aware of where our definitions exist. To this end, we first run the following program once within RUR-PLE:
import sys
sys.path.append("D:\\")
turn_off()
Next, if we want to use our definitions found in module my_def.py, we do as follows:
import my_def
my_def.turn_around()
turn_off()
Of course, one could use the "from my_def import turn_around" syntax instead so as not to have to write
"my_def." in front of every instruction I define.
"my_def." in front of every instruction I define.
Note that, if my_def is modified, RUR-PLE will have to be restarted and the entire procedure above will have to be repeated.
===
Note added after the original post. I wrote RUR-PLE when I was just relearning computer programming and I did not really understand a lot of things very well. rur_program() referred to above is not a function, but a class (I was learning!...). And, having learned a bit of Java some years before and having come accross some sample code about singletons in Python, I wrote rur_program() to be a singleton, thinking I was never going to need more than one user program at a time. I don't think most Python programmers would have done that. Yet, through sheer luck, this is needed for the above to work, otherwise "turn_left" in the imported module, defined as a method of rur_program, would have referred to a different instance than that used in the user's program, and it would not have been possible to import user definitions as done above.
===
Edit #2
I know that some teachers that use rur-ple are not familiar with advanced Python features; so here's another equivalent way (sent to me by a reader) to import and use modules with rur-ple; the path uses the syntax one may have on a Mac. (For people familiar with Python, I do realize that both ways will look essentially the same - but they do not for beginners.)
===
Note added after the original post. I wrote RUR-PLE when I was just relearning computer programming and I did not really understand a lot of things very well. rur_program() referred to above is not a function, but a class (I was learning!...). And, having learned a bit of Java some years before and having come accross some sample code about singletons in Python, I wrote rur_program() to be a singleton, thinking I was never going to need more than one user program at a time. I don't think most Python programmers would have done that. Yet, through sheer luck, this is needed for the above to work, otherwise "turn_left" in the imported module, defined as a method of rur_program, would have referred to a different instance than that used in the user's program, and it would not have been possible to import user definitions as done above.
===
Edit #2
I know that some teachers that use rur-ple are not familiar with advanced Python features; so here's another equivalent way (sent to me by a reader) to import and use modules with rur-ple; the path uses the syntax one may have on a Mac. (For people familiar with Python, I do realize that both ways will look essentially the same - but they do not for beginners.)
from rur_py.cpu import rur_program
robot = rur_program()
def left():
robot.turn_left()
def turn_around():
left()
left()
def right():
turn_around()
left()
======== and within rur-ple
import sys
my_py_dir = "/Users/andre/rurple_files"
if my_py_dir no in sys.path:
sys.path.append(my_py_dir)
from my_module import *
# main program
right()
turn_off()
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
===
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
====
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
Subscribe to:
Posts (Atom)
