Learning to program (ix) – all about style

In the previous eight posts, we have designed a program to calculate the age of a tree, given its circumference, and species. In these basic lessons, the core techniques for writing a program in Julia have been covered. Along the way we made changes to the basic program which improved both its functionality, and the the code within it. Now let’s look briefly at the codes style. Style you say… why is that important? It is important because while compilers or interpreters don’t care what a program looks like, humans do. It’s nice to look at a program that is formatted in an aesthetically pleasing manner. Here is the program as it stands:

function readNum(str)
   print(str)
   c = parse(chomp(readline()))
   return c
end

n = readNum("How many trees? ")

species = ["Silver Maple", "White Birch", "Black Walnut",
 "Red Oak", "White Oak", "American Elm"]
g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:n

   c = readNum("Enter the circumference of the tree (inches): ")

   println("Tree Species: ")
   for i=1:length(species)
      println("(",i,") ",species[i])
   end
   t = readNum("Choose a tree (?): ")

   d = c / pi
   age = d * g[t]
   println("The ", species[i], " is ", round(age,2), " years old")

end

It is already quite well formatted, with 3-space indenting (see previous posts on indenting), and good whitespace between sections. There are only two things not quite right: (i) poorly named variables, and (ii) a lack of comments. Variable names like c, and g and non-descriptive, so therefore require a comment, which is wasteful. If they were better named, there would be no need to comment them. Comments are important to inform the reader of a program what is going on. They are really only needed for parts of the program which are not self-explanatory (i.e. complex pieces of code). Here is the program with better style:

# This program calculates the approximate age of a tree using
# the measured circumference of a trunk (4ft from the ground),# and a growth factor specific to the species of tree.

function readNum(str)
   print(str)
   aNum = parse(chomp(readline()))
   return aNum
end

nTrees = readNum("How many trees? ")

species = ["Silver Maple", "White Birch", "Black Walnut",
 "Red Oak", "White Oak", "American Elm"]
growthF = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:nTrees

   treeCirc = readNum("Enter the circumference of the tree (inches): ")

   println("Tree Species: ")
   for i=1:length(species)
      println("(",i,") ",species[i])
   end
   menuItem = readNum("Choose a tree (?): ")

   treeDiam = treeCirc / pi
   treeAge = treeDiam * growthF[menuItem]
   println("The ", species[i], " is ", round(treeAge,2), " years old")

end

The pink code shows variables that have been modified with better names. The orange code, an overall comment on what the program does – there is no need for specific comments in the program, as the variables are descriptive, and the code short and self–explanatory.

 

 

Learning to program (viii) – strings and functions

Now that we have briefly looked at strings, we can improve upon the function readNum(), defined previously. Remember that it only had one line of code inside it, which didn’t make it that useful. Now consider this snippet of code:

print("How many trees? ")
n = readNum()

What about if we combined these two lines of code into one? So somehow integrate the print statement into the function readNum(). This can be achieved by passing the phrase “How many trees? “, to the function readNum(). So readNum() would be activated in the following manner:

n = readNum("How many trees? ")

The function itself now looks like this:

function readNum(str)
   print(str)
   c = parse(chomp(readline()))
   return c
end

It takes str as input, and gives it to print, which prints it out. The other two lines are the same as before. This reduces the size of the overall program.

function readNum(str)
   print(str)
   c = parse(chomp(readline()))
   return c
end

n = readNum("How many trees? ")

species = ["Silver Maple", "White Birch", "Black Walnut",
 "Red Oak", "White Oak", "American Elm"]
g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:n
   c = readNum("Enter the circumference of the tree (inches): ")

   println("Tree Species: ")
   for i=1:length(species)
      println("(",i,") ",species[i])
   end
   t = readNum("Choose a tree (?): ")

   d = c / pi
   age = d * g[t]
   println("The ", species[i], " is ", round(age,2), " years old")

end

 

Learning to program (vii) – strings

In the same way that we put all the growth factors into an array, we can do the same with the tree species.

species = ["Silver Maple", "White Birch", "Black Walnut", 
           "Red Oak", "White Oak", "American Elm"]

Now we can use this to “shrink” the program code for the menu.

function readNum()
   c = parse(chomp(readline()))
   return c
end

print("How many trees? ")
n = readNum()

species = ["Silver Maple", "White Birch", "Black Walnut",
           "Red Oak", "White Oak", "American Elm"]
g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:n

   print("Enter the circumference of the tree (inches): ")
   c = readNum()

   println("Tree Species: ")
   for i=1:length(species)
      println("(",i,") ",species[i])
   end
   print("Choose a tree (?): ")
   t = readNum()

   d = c / pi
   age = d * g[t]
   println("The ", species[i], " is ", round(age,2), " years old")

end

It is also possible to modify the code in the final println in order to specify the type of tree selected by the user. Here’s what the program looks like when it runs:

How many trees? 2
Enter the circumference of the tree (inches): 97
Tree Species:
(1) Silver Maple
(2) White Birch
(3) Black Walnut
(4) Red Oak
(5) White Oak
(6) American Elm
Choose a tree (?): 1
The American Elm is 92.63 years old
Enter the circumference of the tree (inches): 40
Tree Species:
(1) Silver Maple
(2) White Birch
(3) Black Walnut
(4) Red Oak
(5) White Oak
(6) American Elm
Choose a tree (?): 6
The American Elm is 50.93 years old

 

 

Learning to program (vi) – arrays

So this is a little bit more challenging. Our program works fine, however the if statement which selects the value of the tree is somewhat large. If you had 200 trees to choose from, it would be kinda messy. Is there a better way? Yes, by storing the values of growth factor in an array. An array is just a container, which can hold more than one value. An array to hold the growth factors can be created in the following manner:

g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

Each of those values is an element in the array g. So the value of g[1] = 3.0, g[2] = 5.0, etc. Now we can modify the program to use this new container. Basically we can remove the entire if statement, and replace the single g in the equation, with the container g.

age = d * g[t]

Here the value of t entered by the user to specify the type of tree is used to access the appropriate element of g. This is what the whole program looks like now:

function readNum()
   c = parse(chomp(readline()))
   return c
end

print("How many trees? ")
n = readNum()

g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:n

   print("Enter the circumference of the tree (inches): ")
   c = readNum()

   println("Tree Species: ")
   println("(1) Silver Maple")
   println("(2) White Birch")
   println("(3) Black Walnut")
   println("(4) Red Oak")
   println("(5) White Oak")
   println("(6) American Elm")
   print("Choose a tree (?): ")
   t = readNum()

   d = c / pi
   age = d * g[t]
   println("The tree is ", round(age,2), " years old")

end

As you can see, the program has shrunk considerably in size. Now adding 20 more trees is as simple as adding more values to the array g, and modifying the menu.

 

Learning to program (v) – adding a subroutine

Our program as it stands works quite well.

print("How many trees? ")
n = parse(chomp(readline()))

for i=1:n
   
   println("Enter the circumference of the tree (inches): ")
   c = parse(chomp(readline()))

   println("Tree Species: ")
   println("(1) Silver Maple")
   println("(2) White Birch")
   println("(3) Black Walnut")
   println("(4) Red Oak")
   println("(5) White Oak")
   println("(6) American Elm")
   print("Choose a tree: ")
   t = parse(chomp(readline()))

   if (t == 1)
      g = 3.0
   elseif (t == 2)
      g = 5.0
   elseif (t == 3)
      g = 4.5
   elseif (t == 4)
      g = 4.0
   elseif (t == 5)
      g = 5.0
   elseif (t == 6)
      g = 4.0
   end

   d = c / pi
   age = d * g
   println("The tree is ", round(age,2), " years old")

end

The most unreadable part is still the three lines that read in info:┬áparse(chomp(readline())). As this is used three times, it might be nice if we put it in its own “subroutine”, which is a way of creating a piece of a program which can be used anywhere. These are more often called functions. By doing this we are able to “hide” code. Here is what a simple function would look like in Julia:

function readNum()
   c = parse(chomp(readline()))
   return c
end

It uses the pair function-end, to define the function. It is given a name, in this case readNum, and because it doesn’t take any inputs there is nothing in between the parentheses. The line of code that reads the number from the user is placed inside the function, and passed back to the program using the function using the return statement.

function readNum()
   c = parse(chomp(readline()))
   return c
end

print("How many trees? ")
n = readNum()

for i=1:n

   print("Enter the circumference of the tree (inches): ")
   c = readNum()

   println("Tree Species: ")
   println("(1) Silver Maple")
   println("(2) White Birch")
   println("(3) Black Walnut")
   println("(4) Red Oak")
   println("(5) White Oak")
   println("(6) American Elm")
   print("Choose a tree (?): ")
   t = readNum()

   if (t == 1)
      g = 3.0
   elseif (t == 2)
      g = 5.0
   elseif (t == 3)
      g = 4.5
   elseif (t == 4)
      g = 4.0
   elseif (t == 5)
      g = 5.0
   elseif (t == 6)
      g = 4.0
   end

   d = c / pi
   age = d * g
   println("The tree is ", round(age,2), " years old")

end

This is a very simple example of a function – some will argue there was little point, as one line of code in each instance was replaced with “one line of code”. But were there more lines repeated, then it could be quite beneficial.

 

Errors never cease to amaze…

I saw this error on a checkout page for an online store I was considering purchasing from. I guess Liquid is some sort of web-system… still errors like this should never percolate up to the user.

At the end I didn’t purchase anything… scared away by “asset snippets”.

Learning to program (iv) – going loopy in Julia

Our program as it stands works quite well. Here it is again:

println("Enter the circumference of the tree (inches): ")
c = parse(chomp(readline()))

println("Tree Species: ")
println("(1) Silver Maple")
println("(2) White Birch")
println("(3) Black Walnut")
println("(4) Red Oak")
println("(5) White Oak")
println("(6) American Elm")
print("Choose a tree: ")
t = parse(chomp(readline()))

if (t == 1)
   g = 3.0
elseif (t == 2)
   g = 5.0
elseif (t == 3)
   g = 4.5
elseif (t == 4)
   g = 4.0
elseif (t == 5)
   g = 5.0
elseif (t == 6)
   g = 4.0
end

d = c / pi
age = d * g
println("The tree is ", round(age,2), " years old")

But it only works once. What if we wanted to calculate the age of a series of trees? This would require some form of repetition. Say we let the user enter the number of trees whose age they want to calculate:

print("How many trees? ")
n = parse(chomp(readline()))

Then we can use the value of n to repeat the whole process n times. This may be done using a for loop:

for i=1:n
   # something
end

The something is replaced by the whole of the program from the previous post. So now the program looks like this:

print("How many trees? ")
n = parse(chomp(readline()))

for i=1:n

   println("Enter the circumference of the tree (inches): ")
   c = parse(chomp(readline()))

   println("Tree Species: ")
   println("(1) Silver Maple")
   println("(2) White Birch")
   println("(3) Black Walnut")
   println("(4) Red Oak")
   println("(5) White Oak")
   println("(6) American Elm")
   print("Choose a tree (?): ")
   t = parse(chomp(readline()))

   if (t == 1)
      g = 3.0
   elseif (t == 2)
      g = 5.0
   elseif (t == 3)
      g = 4.5
   elseif (t == 4)
      g = 4.0
   elseif (t == 5)
      g = 5.0
   elseif (t == 6)
      g = 4.0
   end

   d = c / pi
   age = d * g
   println("The tree is ", round(age,2), " years old")

end

Now the user can specify how many trees they want to calculate the age of, and the program will run accordingly.

 

 

Learning to program (iii) – an intermediary Julia program

Last time the Julia program we wrote worked on Silver Maples only. Now we will try and extend it to work with a series of different tree species. Here is the program as it stands.

println("Enter the circumference of the tree (inches): ") 
c = parse(chomp(readline())) 
d = c / pi 
g = 3.0 
age = d * g 
println("The tree is ", round(age,2), " years old")

Now to add more tree species requires the use of a sort of menu. Here is a piece of code to print a menu for the user to select an option from:

println("Tree Species: ")
println("(1) Silver Maple")
println("(2) White Birch")
println("(3) Black Walnut")
println("(4) Red Oak")
println("(5) White Oak")
println("(6) American Elm")
print("Choose a tree (?): ")
t = parse(chomp(readline()))

It basically prints out a table of six tree species, then prompts the user to enter the number which represents the menu item of the tree they want. The only thing missing is the growth factor associated with each tree? Now we need to use the number entered to assign a value to the variable “g“. This can be achieved using an if statement. The if statement is used in just about every language to make decisions. Basically we want to ask:

if the user inputs “1”, then the value of g is 3.0, because this is the growth factor for a Silver Maple.
if the user inputs “2”, then the value of g is 5.0, because this is the growth factor for a White Birch.
etc.

Here is the piece of code that does that:

if (t == 1)
   g = 3.0
elseif (t == 2)
   g = 5.0
elseif (t == 3)
   g = 4.5
elseif (t == 4)
   g = 4.0
elseif (t == 5)
   g = 5.0
elseif (t == 6)
   g = 4.0
end

Only one value of g will be assigned, depending on the value of t, which was the menu item selected by the user. Now let’s look at the whole program:

println("Enter the circumference of the tree (inches): ")
c = parse(chomp(readline()))

println("Tree Species: ")
println("(1) Silver Maple")
println("(2) White Birch")
println("(3) Black Walnut")
println("(4) Red Oak")
println("(5) White Oak")
println("(6) American Elm")
print("Choose a tree: ")
t = parse(chomp(readline()))

if (t == 1)
   g = 3.0
elseif (t == 2)
   g = 5.0
elseif (t == 3)
   g = 4.5
elseif (t == 4)
   g = 4.0
elseif (t == 5)
   g = 5.0
elseif (t == 6)
   g = 4.0
end

d = c / pi
age = d * g
println("The tree is ", round(age,2), " years old")

Now the program is more functional, and technically, any number of tree species can be added to the if statement to expand its usability.