search


Draw a Triangle
Mon Mar 12 00:00:00 UTC 2018
Summary of last class.

By definition, one complete rotation in a plane is 360 degrees. A regular polygon is a polygon with sides of equal length which also implies the angles are also equal. Therefore to draw a regular n-sided polygon your turtle must rotate at an angle of (/ 360 n) and move forward a distance of d repeated n times.

For the case of a triangle n is 3. Since the rotation angle is (/ 360 n) we subsitute n=3 into that formula to get (/ 360 3) which means 360 divided by 3. Type that into power turtle and you will get the number 120 which is our rotation angle. We can arbitarily pick the distance of 100 for d.

To draw a triangle we tell our turtle to turn right 120, move forward 100, turn right 120, move forward 100, turn right 120, move forward 100. translating that into code.


(right 120)
(forward 100)
(right 120)
(forward 100)
(right 120)
(forward 100)

If you type the code above into power turtle, it draws a triangle. It is tedious to repeatedly type that code everytime we want to draw a triangle. The sequence of code above to draw a triangle is too low-level. It is not obvious from reading it that it draws a triangle. We will use the Power of Names to give a name to that sequence of code. We can define a function to do this

(defn triangle [] 
	(right 120)
	(forward 100)
	(right 120)
	(forward 100)
	(right 120)
	(forward 100))
Type that into power turtle. Whenever we need to draw a triangle, we just call the triangle function like this (triangle). There are two main benefits for creating a function to draw a trinagle instead of using low-level commands:
  • High level communication
  • Decrease repetition
Notice that this triangle function does not have any parameters. We hard-coded the distance the turtle moves to 100. Let's make our triangle function better by extracting out hard-coded distance of 100 into the parameter. Let's call this parameter d for distance. We will use a new name so that it does not over-write the previous triangle function. Lets call this new function triangle2
(defn triangle2 [d] 
	(right 120)
	(forward d)
	(right 120)
	(forward d)
	(right 120)
	(forward d))
Copy and paste that code into power turtle to redefine the triangle function. The new triangle function takes a parameter d. We can call it like this (triangle2 300). This triangle function can draw a triangle of any size. Perform some experiments. Repeatedly call the triangle functions with various values of d. Is this behavior what you expected?

The triangle2 function is better than the triangle function because we extracted a hard-coded value into a parameter of the function. This allowed us to create a triangle of any size.

The REPL is your laboratory

The process of incremental improvement from the triangle function to the triangle2 function is very similar to the scientific method of improving and refining hypothesis. The scientific method requires experimentation. In the Clojure world, experimentation is done in whats called the REPL (Read Eval Print Loop). Power Turtle is a REPL that runs in the web browser. The area where you type in code is the power turtle REPL. It is where you can perform code experiments and hypothesis testing

We can improve triangle2. Lets create our improvement in a new function called triangle3. What can be improved with triangle2? We are repeating (right 120) (forward d). Let's extract reptition of code that into a function called right-forward

(defn right-forward [d]
                     (right 120)
                     (forward d))
 (defn triangle3 [d]
                     (right-forward d)
                     (right-forward d)
                     (right-forward d))

Compare triangle2 with triangle3. triangle3 is just a simple subsittion of the common code fragment extracted into a function called right-forward. We still have repeated code (right-forward d) is called 3 times. Fortunately power turtle has a built-in function called called repeat to allow us to repeatedly call a function

(defn triangle4 [d]
                     (repeat 3 #(right-forward d)))

I will not explain what that # means here. triangle4 calls the function right-forward 3 times. The function right-forward turns 120 degrees and draws a line of distance d I rename the function from right-forward to turn-draw to better reflect its intention. I also want to replace the 120 degree with a parameter called angle. I will also rename the d to distance. The result of this transformation is this function

(defn turn-draw [angle distance]
                     (right angle)
                     (forward distance))
                   
 (defn triangle5 [d]
                     (repeat 3 #(turn-draw 120 d)))

Finally since triangle5 is an equilateral-triangle i should create a function with that name

(defn equilateral-triangle [d]
                     (repeat 3 #(turn-draw 120 d)))

The steps I did getting from the function triangle, triangle2, triangle3, triangle4, triangle5 to finally equalaterial-triangle is a mini application of the scientific method of refining the triangle code. Evolution of animals go through a similar process. Evolution and the scientific method are similar or homomorphic processes.



The Power of Names
Sat Mar 10 15:52:06 UTC 2018
Call him Voldemort, Harry. Always use the proper name for things. Fear of a name increases fear of the thing itself.
What is a name?

This may seem like a silly question. Everyone has a name and everything we know about has a name. Everyone intuitively knows what a name is but when asked to define it, most people will have difficulty. In magic, knowing the True Name of something, gives you power over it. Knowing the incantations of a spell gives you magical power that can affect the world. In Semitic religions like Judaism, Christianity and Islam, the name of God is so scared that it is unknown. In the Old Testment, the Israelite did not know God's name but only refer to him as Yahweh which is Hebrew for 'I am who I am'. The Ten Commandments forbids the use of God's name.

Needless to say names are important, but what is it? Are names simply sequence of letters written on paper? Blind people cannot see those letters yet they can make and use names. Are names the sound that come out our of mouths? Deaf people cannot hear sounds yet they can make and use names. The ability to name things is essential to language. Imagine what it would be like if we could not name things. We could not have language.

Names are abstract symbols used to represent or substitute for something else. The name of a thing is not the thing itself. For someone with eyes, the abstract symbol takes the form of letters written on paper or computer screen. For a blind person, it is the feel of the bumps and grooves on their braille reader . For a deaf person, it is motion of the hands and fingers and facial expression.

Giving something a name gives us power over it. It allows us to to discuss it, to communicate it even if we do not know what it is. Science and mathematics are full of examples of this. Dark Matter is a prime example. Scientist do not know what Dark Matter is but they gave it a name. In algebra, an unknown is given an arbitary symbol x. Imaginary numbers were discoverd when trying to find solutions to quadratic equations. The square root of -1 keeps popping up as a solution. Mathematician didn't know what the square root of -1 was so they named it i for imaginary number. They thought it was a fake number because any real number squared is always positive. It turns out if imaginary numbers did not exist, we could not describe electricity or quantum mechanics which means if imaginary numbers didnt exist, we would not exist. Assigning the symbol i to the square root of -1 allowed mathemticians to explore and discover its properties. Centuries later, something that was thought to be imaginary, turned out to be essential to the description of the universe.

Giving something a name is important and it is the simplest and most fundament form of abstraction. Pick names carefully so that they capture the essence of the thing they represent. Software is nothing more than abstractions built on top of abstractions. It is the closest thing we have to magic spells. To the uninitiated, the symbols of names in a program look like the gibberish of a magic spell. These cryptic symbols and names bestow magical powers onto the person who understands their secrets allowing him/her to use the computer like a wizzard uses the magic wand to cast spells.

Naming things in Clojure

def is a "special form" that allows us to create global names. I shall use names and symbols interchangably.

(def my-name "sonny")

This creates a symbol called my-name to the string "sonny". Whereever I need to refer to the string "Sonny", I can substitute the symbol my-name instead.

We already saw one way of creating a function with a name using the defn macro

(defn square [x] (* x x))

square is the name of the function and x is the name of the parameter of that function. defn macro is a short-hand for def and fn . For example:

(def square (fn [x] (* x x))) ;;same as (defn square [x] (* x x))

fn is the special form that creates an anonymous function, or a function without a name. def is then used to associate the symbol square with anonymous function.

fn is also called lambda in other LISP dialects like Scheme . Lambda is where Lambda Calculus derives its name

def creates global names. Clojure also provides a mechanism for creating local names using let macro

(let [my-name "sonny"])

the symbol my-name is only visible within the let scope. In other programming language, this is called a local variable We will talk more about scope later. For the curious, let is a macro that expands into a function

Namespaces

All symbols exist in a namespaces. Namespace prevent collision of symbols with the same name. You are already familar with the concept of a namespace. For example, there are many people in the world with a first-name Sonny. To prevent confusion, we also have a last-name and a middle-name. My last-name is Su and my middle-name is Chung. My complete namespace consists of my first-name, middle-name, and last-name. Symbols in Clojures are organized in the same way to prevent conflict of name. if you look at the REPL above, you'll see 'cljs.user/square This means square is a symbol in the cljs.user namespace.

A namspace can be created using the ns form. For example:

(ns odessa) (defn square [x] (* x x))

Notice above that the namespace of the square symbol is now odessa and not cljs.user . This is like twp person having the same first-name but different last-name.