Teaching Children Programming
Posted: 2011/01/22 Filed under: Lisp, Musing, Programming, SBCL | Tags: Programming 2 Comments »Some parents want to teach their kids programming. Good on them, I say. I started programming with qbasic (which may still be on Windows machines), I started in grade 5 (age 10), I know I was using C to make RPG’s by grade 8 (age 13).
This article (List of educational programming languages — wikipedia) shows many bad ways to learn. Ways that are held in high regard by many programmers who themselves didn’t learn that way.
I think they’re terrible:
- They add another layer of abstraction. They make computers harder to understand.
- They are either too simple (like manipulating a graphic pen [e.g. a 'turtle']). They work like a bad video game, and end up competing (and losing) to video games.
- or, they are too complex. Some teach object oriented design, which is way to much for a beginner who needs fast turnaround time to stay motivated.
- They teach few transferable skills, but teach lots of skills that are useless to anyone not using that toy
Put another way, are you teaching computer science, or are you teaching toys? Lessons should pierce the veil, teach how things actually work. Not distract the learners attention with toys. Computers are interesting enough without help.
What to Do?
Graphics. Take any (real) language you like, then write an SDL binding to it so the learner can plot colored pixels.
This leads to gradients (loops), to horizontal/vertical lines (coordinates & loops), to boxes (functions), to user-input, then to simple games.
You must setup their programming environment — this is their training wheels. Try to pick languages without much boiler plate (and then write that boilerplate for them). Integrate with SDL (or other GFX library) and get it to the point where they can plot pixels. If you’re language has a REPL use it, otherwise write a makefile and teach your kid how to use it and run the resulting program.
SDL & Lisp
Here’s example Lisp and SDL integration. It’s intended to be simple, without any options. When these limitations cause your learner to change it, so much the better.
It’s really just 2 files. A C library to setup SDL in the simplist way possible, and a Lisp bridge that calls those C routines, and provides some primitives.
It sets up an 800×600 window, where each ‘pixel’ (on the lisp side) is actually an 8 by 8 grid of real pixels. I did this to improve visibility. In time, the learner will probably want to use real pixels and fullscreen graphics, so you’ll help him make those changes to this library.
gfx.c
#include "SDL/SDL.h"
SDL_Surface* screen = NULL;
int sdl_start (int x, int y, int d) {
if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD ) != 0) { return -1; }
screen = SDL_SetVideoMode( x, y, d, SDL_SWSURFACE );
if (screen == NULL) { return -1; }
return 0;
}
void sdl_stop () {
SDL_FreeSurface( screen );
screen = NULL;
SDL_Quit();
}
char* gfx_error () { return SDL_GetError(); }
void gfx_show () { SDL_Flip(screen); }
void* gfx_raw () { return screen->pixels; }
void gfx_lock () { SDL_LockSurface(screen); }
void gfx_unlock () { SDL_UnlockSurface(screen); }
gfx.lisp
(defpackage :gfx
(:use :common-lisp :sb-alien)
(:export ;; +width+ +height+ +depth+
+wide+ +tall+ +white+ +black+ +red+ +green+ +blue+
gfx-start gfx-stop gfx-show))
(in-package :gfx)
(load-shared-object "libSDL.so")
(load-shared-object (car (directory "gfx.so"))) ;; Get the abs path of gfx.so.
(define-alien-variable screen system-area-pointer)
(define-alien-routine sdl-start int (width int) (height int) (depth int))
(define-alien-routine sdl-stop void)
(define-alien-routine gfx-error c-string)
(define-alien-routine gfx-show void)
(define-alien-routine gfx-raw system-area-pointer)
(define-alien-routine gfx-unlock void)
(define-alien-routine gfx-lock void)
(defconstant +width+ 800)
(defconstant +height+ 600)
(defconstant +depth+ 32)
(defconstant +white+ #xFFFFFF)
(defconstant +black+ #x000000)
(defconstant +red+ #xFF0000)
(defconstant +green+ #x00FF00)
(defconstant +blue+ #x0000FF)
(defun gfx-start ()
(if (zerop (sb-sys:sap-int screen))
(or (zerop (sdl-start +width+ +height+ +depth+))
(error (gfx-error)))
(error "Graphics are already initialized")))
(defun gfx-stop ()
(if (zerop (sb-sys:sap-int screen))
(error "Graphics are not initialized.")
(sdl-stop)))
(defun dot (color x y)
(setf x (min (max x 0) +width+) y (min (max y 0) +height+))
(let ((offset (ash (+ (* y +width+) x) 2)))
(setf (sb-sys:sap-ref-32 (gfx-raw) offset) color)))
(defconstant +wide+ (/ +width+ 8))
(defconstant +tall+ (/ +height+ 8))
(defun put (color x y)
"Puts an 8x8 pixels on the screen."
(setf x (* x 8) y (* y 8) color (truncate color))
(gfx-lock)
(dotimes (dx 8) (dotimes (dy 8) (dot color (+ x dx) (+ y dy))))
(gfx-unlock)
(gfx-show))
(gfx-start)
(push #'gfx-stop sb-ext:*exit-hooks*)
(defun testit ()
(dotimes (x +wide+)
(dotimes (y +tall+)
(put (boole boole-ior (ash (truncate (* x 255) +wide+) 8) (truncate (* y 255) +tall+)) x y))))
Makefile
This only builds gfx.so. Active development is intended to be done in the Lisp REPL.
gfx.so : gfx.c
gcc -c -fPIC `sdl-config --cflags` `sdl-config --libs` gfx.c && ld -shared -o gfx.so gfx.o
It’s interesting you thought about this right now. I just had the same idea after answering a question at StackOverflow: http://stackoverflow.com/questions/1621774/which-programming-language-is-manageable-by-an-11-year-old-kid/4704334#4704334
I’m going to turn that into a blog post; I’ll definitely mention this as well.
The topic also came up in LispForum (http://www.lispforum.com/viewtopic.php?f=2&t=969). Any language is fine, as long as getting to it is easy (install it for them).
But many answers don’t even approach things kids would be interested in (i.e. reading books, HTTP, postscript, Win32 Gui, etc). When I started, I just wanted gradients and dumb games – I assume as much of other kids.