Version 14 of Teach programming to children

Updated 2003-06-11 06:44:50

Arjen Markus (5 june 2003) The idea grew over breakfast in the hotel in Nuremberg, where Clif Flynt, Pascal Scheffers, Richard Suchenwirth and I stayed for the Fourth European Tclers' Meeting (Andreas Kupries stayed at the same hotel, but we were earlier to rise): let us develop a program that allows young children to learn how to program in a playful way. The basic principle is simple:

  • It is a drawing program where you type in commands
  • The graphics cursor is for instance a puppy dog
  • The commands can be simple or composite, so that the child will learn to think in structures

Of course, over breakfast the thing grew into an intelligent life-form: as the child uses the program longer, the puppy would grow, increasing in size and showing different behaviour. Or what about ways to draw the actual lines and so on: wagging tail, sniffing on the ground, dropping droppings ...

Basic (Tcl) commands are:

  • lines $thickn - set the line thickness
  • colour $name - set the colour for drawing
  • start line - record the current position of the graphics cursor
  • draw line - draw a line from the last stored position to the current one and store the current position
  • move $dist - move a certain distance
  • turn left|right - turn the direction over 90 degrees
  • draw circle - draw a circle
  • fill circle - draw and fill a circle

The commands as shown above are a bit abbreviated and serve merely for the discussion (see below).

A user will type in something like (in this case, a Dutch kid :):

   teken heel groot rondje

This gets translated (using a very straightforward word-by-word approach) into:

   draw very big circle

Which is in turn analysed as:

   command=draw
   object=circle
   attribute=big
   qualifier=very
   names={}
   numbers={}

And run as the command:

   $command $object $attribute $qualifier $names $numbers

(each actual Tcl command will have this signature)

This way, our kid user can type:

   I want to draw a very big circle

or:

   teken hier een grote cirkel
   (draw a very big circle here)

This allows rather casual use of the commands with the possibility of ambiguity and misinterpretation...

Question: should we try to repair typos? If so, what is a convenient way of doing this?

Question: can we use [msgcat] for the translations? It is in some way going the other way around when compared to the usual use.


The code below translates Dutch sentences into Tcl commands like decribed above

 # kid.tcl --
 #    Some experimental code to translate sentences to commands
 #

 namespace eval translations {

    namespace export mc translate

    variable dictionary {
 {line obj lijn}
 {big attr grote groot}
 {small attr klein kleine}
 {circle obj cirkel rondje}
 {square obj vierkant}
 {draw cmd teken}
 {fill cmd vul}
 }         

 proc mc {word} {
    variable dictionary

    foreach d $dictionary {
       if { [lsearch $d $word] > -1 } {
          return [lrange $d 0 1]
       }
    }
    return [list $word ?]
 }

 proc translate {line} {
    set words   [split $line]
    set names   [list]
    set numbers [list]

    foreach v {cmd obj attr qual} {
       set $v ""
    }

    foreach word $words {
       if { [string is double $word] } {
          lappend numbers $word
       } else {
          foreach {translated type} [mc $word] {break}
          if { $type != "?" } {
             set $type $translated
          } else {
             lappend names $word
          }
       }
    }

    if { $cmd != "" } {
       puts "$cmd $obj $attr $qual $names $numbers"
    } else {
       puts "$cmd $obj $attr $qual $names $numbers"
       puts "[mc "Unknown command:"] $line"
    }
 }

 } ;# End of namespace

 #
 # Test the above code
 namespace import translations::*

 puts [mc "teken"]

 translate "ik teken een grote cirkel"
 translate "vul klein vierkant"

Here are some basic drawing commands - nothing fancy yet and not hooked up to the translation procs


 namespace eval drawcommands {

    namespace export colour thickness move turn draw start stop lines

    variable colour    "black"
    variable thickness 1
    variable posx      200
    variable posy      200
    variable dirx      1
    variable diry      0
    variable anchorx   {}
    variable anchory   {}
    variable prevx     $posx
    variable prevy     $posy


 proc colour { obj attr qual names numbers } {
    variable colour
    set colour $obj
    .draw itemconfigure "cursor-centre" -fill $colour
 }

 proc lines  { obj attr qual names numbers } {
    variable thickness
    set fullword "$qual$attr"

    switch -- $fullword {
    "verythin"  { set thickness 1 }
    "thin"      { set thickness 3 }
    "thick"     { set thickness 6 }
    "verythick" { set thickness 12 }
    default {puts $fullword}
    }
 }

 proc move { obj attr qual names numbers } {
    variable posx
    variable posy
    variable dirx
    variable diry
    variable prevx
    variable prevy

    set dist [lindex $numbers 0]
    set delx [expr {$dirx*$dist}]
    set dely [expr {$diry*$dist}]
    set posx [expr {$posx+$delx}]
    set posy [expr {$posy+$dely}]
    .draw move "cursor" $delx $dely
    .draw coords "anchor-line" $prevx $prevy $posx $posy
 }

 proc turn { obj attr qual names numbers } {
    variable posx
    variable posy
    variable dirx
    variable diry

    set oldx $dirx
    set oldy $diry
    if { $obj == "left" } {
       set dirx [expr {$oldy}]
       set diry [expr {-$oldx}]
    } else {
       set dirx [expr {-$oldy}]
       set diry [expr {$oldx}]
    }
    # TODO: rotate cursor
 }

 proc start { obj attr qual names numbers } {
    variable anchorx
    variable anchory
    variable posx
    variable posy
    variable prevx
    variable prevy

    if { $obj == "line" } {
       if { $anchorx == {} } {
          .draw create line $posx $posy $posx $posy -tags "anchor-line"
          .draw raise  "cursor"
       }
       set anchorx $posx
       set anchory $posy
       set prevx   $posx
       set prevy   $posy
    }
 }

 proc stop { obj attr qual names numbers } {
    variable anchorx
    variable anchory
    variable prevx
    variable prevy
    variable posx
    variable posy

    if { $obj == "line" } {
       .draw delete "anchor-line"
       set anchorx {}
       set anchory {}
       set prevx   $posx
       set prevy   $posy
    }
 }

 proc draw { obj attr qual names numbers } {
    variable anchorx
    variable anchory
    variable posx
    variable posy
    variable dirx
    variable diry
    variable prevx
    variable prevy
    variable colour
    variable thickness

    if { $obj == "line" } {
       .draw create line $prevx $prevy $posx $posy \
          -fill $colour -width $thickness
       .draw raise  "cursor"
       set prevx $posx
       set prevy $posy
       set anchorx $posx
       set anchory $posy
    }
 }

 };#End of namespace


 #
 # Auxiliary proc to delay execution of the commands
 #
 proc delayed {delay body} {
    set time 0

    foreach cmd [split $body "\n"] {
       after $time $cmd
       incr time $delay
    }
 }

 canvas .draw -width 400 -height 400 -background white
 pack .draw -fill both

 .draw create oval 195 195 205 205 -fill black -tags {"cursor-centre" "cursor"}
 .draw create oval 195 195 205 205 -outline black -tags "cursor"

 namespace import drawcommands::*

 delayed 250 {
    start line {} {} {} {}
    lines {} thick very {} {}
    colour green {} {} {} {}
    move {} {} {} {} 100
    draw line {} {} {} {}
    turn left {} {} {} {}
    move {} {} {} {} 100
    draw line {} {} {} {}
    turn left {} {} {} {}
    move {} {} {} {} 100
    turn left {} {} {} {}
    move {} {} {} {} 100
    draw line {} {} {} {}

    stop line {} {} {} {}
    move {} {} {} {} 100
    start line {} {} {} {}
    colour red {} {} {} {}
    lines {} thick {} {} {}
    move {} {} {} {} 100
    turn right {} {} {} {}
    move {} {} {} {} 100
    draw line {} {} {} {}
 }

Lars H (6 Jun 2003): The idea that one should use Tcl/Tk for teaching programming to children has been on my mind for quite a while now. Many aspects of Tcl that seem strange to adult programmers are quite natural to a child:

  • Children shouldn't find expr prolix to use, because they spend several hours a week doing sums and know from recent experience that these aren't as easy as many other languages would make us believe.
  • Basic string operations (split, join, string, etc.), on the other hand are rather easy to explain to a child, but prolix in more traditional computer languages.
  • The idea that Everything is a string, in the sense that there isn't any information that is hidden from the string representation, is also something that should appeal to children. Magic might be fun to look at, but there is also the desire to get to know how the tricks are done.

(Sometimes I even feel conspiratorial about the whole idea. If Tcl can be thought to the world's youth today, then in ten years time it will dominate the world!)

I am however unsure whether the approach sketched above will be of much use. It is creating a sandbox language built up around a collection of features that are expected to suit the focus group, but there isn't all that much one can do with them. There is a definite risk that the command language (full sentences in the child's mother tounge) is considered too prolix in comparison with the effects one can get out of the thing controlled. One language which very much went that way is AppleScript (which can provide a surprising amount of control of one's Macintosh), but we haven't seen that used to teach children programming, have we? Thinking back to my own childhood, I didn't have any trouble with using Basic commands such as RESTORE even though I didn't understand it as an English word. Using full sentences in text based adventure games was OTOH not a goal; most commands followed a simple <verb><noun> pattern, and more complicated constructions such as

  KILL TROLL USING SWORD

felt overly complicated. A problem with basing command languages on natural language is that children will quickly be disappointed when the computer fails to understand perfectly valid natural language commands because the words aren't in the expected order or something like that. If they continue, they will discover that most of the details in the natural language are unnecessary and therefore stop including them, after a while arriving at the actual command language. However for the sake of imitating natural languge, the command language has probably sacrificed a lot of its power (control structures, variables, etc.) and then there isn't much point in having it.


Setok: "Me too". For quite some time I have been thinking about using Tcl to teach children to program. The way I see it, a language should be simple enough for children to program. If it's not, something needs to be done about it. I also don't believe in inventing an artificial language for children. Perhaps providing easy procs to make some things simpler (but then again, I also believe these procs should enter general use if they really are simpler). In fact, I usually hate tools which are made for educational purposes. I learnt a version of BASIC when I was 8. Sometime later I found the tortoise programming thing a waste of time. I'm sure other children could be the same.


I Thought that this was called Logo -- JBR

AM I should read more about Logo, I guess, but my intention is not so much a drawing language (isn't that what Logo is all about?) as well as a simple programming "language" that is more suitable for children than ____ (fill in any language you want).

It is also my first - hm, no, second - attempt to use natural language in a programming context. (My first was an unsuccessful entry to the Obfuscated C Contest)