clojure-turtle is a Clojure library that implements the Logo programming language in a Clojure context. Quil is used for rendering.
Logo is a simple language that is useful in introducing programming to beginners, especially young ones. Logo also happens to be a dialect of Lisp. clojure-turtle tries to maintain those beneficial aspects of Logo while using Clojure and Clojure syntax. The goal is to make learning programming and/or Clojure easier by disguising powerful concepts with fun!
clojure-turtle artifacts are released to Clojars.
If you are using Maven, add the following repository definition to your pom.xml:
<repository>
<id>clojars.org</id>
<url>http://clojars.org/repo</url>
</repository>With Leiningen:
[clojure-turtle "0.1.0"]With Maven:
<dependency>
<groupId>clojure-turtle</groupId>
<artifactId>clojure-turtle</artifactId>
<version>0.1.0</version>
</dependency>First, install Leiningen.
Second, run a REPL session that has clojure-turtle loaded inside it. This can be done in a couple of ways:
- Create a new Leiningen project and add the clojure-turtle dependency into
project.clj. Then runlein repl. - Use git to clone the clojure-turtle repository, move into the
clojure-turtleworking directory, then runlein repl.
Load the clojure-turtle.core namespace.
(use 'clojure-turtle.core)
; WARNING: repeat already refers to: #'clojure.core/repeat in namespace: user, being replaced by: #'clojure-turtle.core/repeat
;=> nilThe symbol repeat is overridden to behave more like the Logo function, but the Clojure core function is still available as clojure.core/repeat.
The use call will also evaluate Quil code that creates a sketch in a separate window, in which our turtle lives and operates.
It's forward, back, right, and left as in Logo. Go forward and back by a length (in pixels). Right and left turn the turtle by an angle, in degrees. It's Clojure syntax, so 'executing commands' (function calls) are done within parenthases.
(forward 30)
;=> #<Atom@4c8829b7: {:y 29.99999999999997, :angle 90, :pen true, :x -1.3113417000558723E-6}>(right 90)
; #<Atom@4c8829b7: {:y 29.99999999999997, :angle 0, :pen true, :x -1.3113417000558723E-6}>repeat is like the Logo function, or like Clojure's repeatedly. Going from the Logo syntax to clojure-turtle's syntax for repeat, commands that are being repeated are put within parenthases notation. The square brackets that group the repeated commands are replaced with (all ... ). The equivalent of the Logo REPEAT 3 [FORWARD 30 RIGHT 90] would be
(repeat 3 (all (forward 30) (right 90)))
;=> #<Atom@4c8829b7: {:y -2.6226834249807383E-6, :angle 90, :pen true, :x -9.535951726036274E-7}>Let's see how we can simplify this.
(def side (all (forward 30) (right 90)))
;=> #'user/side
(left 90)
;=> #<Atom@4c8829b7: {:y -2.6226834249807383E-6, :angle 180, :pen true, :x -9.535951726036274E-7}>(repeat 4 side)
;=> #<Atom@4c8829b7: {:y -1.311341712550984E-5, :angle 180, :pen true, :x -4.76797586142362E-6}>As you just saw above, we can take the instructions that we pass into repeat, give them a single name, and refer to that name to get the same effect.
Let's simplify further.
(def square (all (repeat 4 side)))
(left 90)
(square)So given a named set of instructions, we can invoke the instructions by putting the name in parenthases just like we do for functions like forward, left, and repeat
(def square-and-turn (all (square) (left 90)))
(left 90)
(square-and-turn)
(left 45)
(repeat 4 square-and-turn)The turtle has a pen that it drags along where it goes, creating a drawing. We can pick the pen up and put the pen down when we need to draw unconnected lines. setxy also teleports the turtle without drawing. setheading turns the turtle in an exact direction.
(penup)
(forward 113)
(right 135)(pendown)
(repeat 4 (all (forward 160) (right 90)))(setxy -100 0)(setheading 225)clean erases all drawing. home brings the turtle to its original position and direction.
(clean)(home)clojure-turtle uses Quil, which uses Processing. clojure-turtle also has the full power and fun of Clojure available to it, too.
What do you get when you enter the following?
(defn any-square
[s]
(repeat 4 (all (forward s) (right 90))))
(any-square 10)
(any-square 20)(def lengths [40 50 60])
(map any-square lengths)(defn times-2
[x]
(* 2 x))
(right 90)
(map any-square (map times-2 lengths))
(right 90)
(->> lengths
(map times-2)
(map any-square))(defn polygon-side
[n s]
(forward s)
(right (/ 360 n)))
(defn any-polygon
[n s]
(repeat n (all (polygon-side n s))))
(clean)
(right 180)
(any-polygon 5 20)
(def sides [6 7 8 10 12])
(def lengths (reverse [30 40 50 60 70]))
(map any-polygon sides lengths)(defn rand-side
[]
(forward (rand-int 50))
(setheading (rand-int 360)))
(fn? rand-side)
(fn? side)
(clean)
(home)
(repeat 4 side)
(repeat 100 rand-side)What possibilities exist when you incorporate the full power of Clojure? What can you create?
Distributed under the Apache 2 license.
This is not an official Google product (experimental or otherwise), it is just code that happens to be owned by Google.
Quil is distributed under the Eclipse Public License either version 1.0 (or at your option) any later verison.
The official Processing.org's jars, used as dependencies of Quil, are distributed under LGPL and their code can be found on http://processing.org/














