Over a million developers have joined DZone.

So, What Is This Boo language Anyway?

·

This article is taken from Building Domain Specific Languages in Boo from Manning Publications. It introduces the Boo language and demonstrates its syntax. For the table of contents, the Author Forum, and other resources, go to http://manning.com/rahien/.

It is being reproduced here by permission from Manning Publications.
Manning early access books and ebooks are sold exclusively through Manning. Visit the book's page for more information.

MEAP Began: February 2008
Softbound print: November 2009 (est.) | 400 pages
ISBN: 1933988606

MEAP

 

Use code "dzone30" to get 30% off any version of this book.

Boo is an object oriented, statically typed language for the common language runtime with a Python inspired syntax and a focus on language and compiler extensibility.

Boo is an Open Source project, released under the BSD license. This means that you are free to take, modify and use the language and its products in any way you want, without any limitation(1), including for commercial use.

Rodrigo B. de Oliveira started the project in early 2004. Since then, it has grown significantly in popularity and features. The project is active and is continually evolving. At the time of the writing, the released version of Boo is 0.8.2.

Note, however, that Boo seems to be following the trend of many open source projects in that it is not really rushing toward 1.0 release. Boo has been stable for a number of years, and I have been using it for production for the last two years.

Production, in this case, means systems that move money around with my neck on the line. I have a high degree of trust in Boo, and it has not failed me yet.

Now that we have spoken a bit about the history and some of the background, we will quickly move forward to talk about the language itself.

Getting Boo

You can download the binary distribution of Boo from the Boo website: http://boo.codehaus.org/

You can execute booish in order to get a command interpreter that will allow you to experiment with Boo directly. It makes it very convenient when you want to quickly try out some ideas, or verify an assumption.

Probably the first question that needs to be answered is why Boo?

What makes Boo unique?

Boo is a CLR based language, this means that when we use Boo we benefit from the rich library, JIT optimizations and plenty of good tools. Leaving aside the ability to extend the compiler, Boo has the following to offer:

Syntactic sugar for common programming patterns - List, hash and array literals, object initialization, string formatting and regular expression matching are all first class concepts in Boo, with direct support for all of them in a natural manner.

Automatic Variable Declaration and Automatic Type Inference(2) – the compiler takes care of things for you, instead of having to type the same thing over and over and over again. Some would say that this is bad, for them I would reply that they should try it first. From my experience, it works. Take a look at listing 1:

Listing 1 – Exploring Boo’s type inferencing

def random(): return 4 # selected by dice roll, guaranteed to be random val = random()

Is there are reason that I would need to specify the type over and over again? The compiler can figure it out for itself and not bother you with it. If you want to get a compiler error, you can explicitly specify the type, such as in listing 2:

Listing 2 - Boo is statically typed, this code will cause compiler error

val as string = random() # will error about type mismatch

Automatic type casting – don’t make me explicitly say it, figure it out for me. I’ll have unit tests to check to cover me. The following example shows what automatic casting means:

obj as object
obj = "some string"
str as string = obj # will automatically cast obj to string

 

Duck typing – Boo is a strongly typed language, but you can ask the compiler to relax those constraints at certain scenarios. It makes some things much more natural, especially since you have a way to get into this infrastructure and decide what to do at runtime. If we will take a simple example, let us look at the XmlObject in listing 3 and what we can do with it.

Listing 3 – Using IQuackFu to get better syntax for working with XML

person = XmlObject(xmlDocument) print person.FirstName print person.LastName

What we just did was resolve, at runtime, that we were asked to get the value of a property called “FirstName”, and then a property named “LastName”.

These features take care of some rough spots in many cases, and they can be very useful when we are building our own languages on top of Boo. But first, you have to understand the syntax a bit…

Boo Basic Syntax

I am going to assume that just printing the BNF(3) of the language will be… an unpopular decision. What we will do instead is write a few sample programs, just enough to let you have a feeling for the language.

Significant whitespace vs. Whitespace agnostic

If you have done any work with Python, you are probably aware that one of the major gripes against the language is the significant whitespace issue. Python use the indention of the code to define control blocks. This means that you don’t need curly braces or explicit block ending like end (Ruby), End If (VB.NET), etc.
The code looks like this:

if lives == 0: print "Game over!" game.Finish() else: lives-- print "${lives} more lives"

As I mentioned already, this is a major point of contention with Python. Since Boo uses the same convention, the same issue has been raised against it as well. However, after spending several years working with it, I can say that it has been my experience that it very rarely caused any issues.

Saying that it very rarely causes issues is not the same as saying that it never causes issues, however.
When I wrote Brail, a templating language using Boo, the whitespace issue was a major issue. I wanted to use the usual HTML formatting, but that really messed up the formatting that boo required.

Luckily for us, Boo comes with Whitespace Agnostic mode, which we can utilize by flipping a compiler switch. The same code we have above would then turn to:

if lives == 0: print "Game over!" game.Finish() else: lives-- print "${lives} more lives"
end

 

The only difference that you will note is the “end” at the end of the statement. This is because now Boo will use the structure of the code to figure out where control blocks begin and end. Usually, this means that a block starts when a statement ends with a colon (“:”) and ends with a statement of the “end” keyword.

When writing DSLs, I tend to use the significant whitespace mode, and only go to the whitespace agnostic mode when I find that it causes issues.

The first sample program is, of course, Hello World. To make it a bit more interesting, we will use WinForms for it. Listing 4 has the details.

Listing 4 – Hello World using WinForms

import System.Windows.Forms

f = Form(Text: "Hello, boo!")
btn = Button(Text: "Click Me!", Dock: DockStyle.Fill)
btn.Click += do(sender, e): f.Close()
f.Controls.Add(btn)

Application.Run(f)

 

First, we import the System.Windows.Forms namespace. This is similar to the using statement in C#, but in Boo this also instructs the compiler to load the System.Windows.Forms assembly if the namespace could not be found in the loaded assemblies.

Then we create a Form and a Button. Note that Boo’s support property initialization at construction (C# 3.0 supports a similar notion, of object initializers).

We register to the button Click event, add the button to the form, and then start the application with the form as the main form.

Not bad for a hello world application. Note that you can type the source in listing 4 directly into booish, in order to experiment with the language.

Now, let us try to make something just a tad bit more complicated, shall we?

Tip, but it is a secret

When you are not sure how to do something in Boo, try doing it like you would with C# (with the obvious syntax changes), in most cases, it would work. It may not be the best way to do something, however.

Keep this a secret, I may get thrown out of the Boo Associated Hackers (BAH!) community if that would happen, and where I would be without my BAH membership?

Listing 5 is an HTTP server that allows you to download files from a directory.

Listing 5 – An HTTP server in Boo


import System.Net
import System.IO

if argv.Length != 2:
print "You must pass [prefix] [path] as parameters"
return

prefix = argv[0]
path = argv[1]

if not Directory.Exists(path):
print "Could not find ${path}"
return

listener = HttpListener()
listener.Prefixes.Add(prefix)
listener.Start()

while true:
context = listener.GetContext()
file = Path.GetFileName(context.Request.RawUrl)
fullPath = Path.Combine(path, file)
if File.Exists(fullPath):
context.Response.AddHeader("Content-Disposition", \ "attachment; filename=${file}")
bytes = File.ReadAllBytes(fullPath)
context.Response.OutputStream.Write(bytes, 0, bytes.Length)
context.Response.OutputStream.Flush()
context.Response.Close()
else:
context.Response.StatusCode = 404
context.Response.Close()

We have a tiny amount of argument validation, and then we setup an HttpListener and start replying to requests. I’ll admit that this is not the most interesting bit of code that I have ever seen, but it does manage to touch on quite a lot of different topics.

For anyone proficient in .NET, what we are doing should be very familiar. The language may be a bit different, but the concepts, the objects and methods that we call are all from the Base Class Library.

This familiarity is very welcome. We don't need to learn everything from scratch.

Tip – That annoying semi colon

One of the more annoying things when moving between languages is the semi colon. When I am moving between C# and VB.NET code, I keep putting semicolons at the end of VB.NET statements, and forgetting to end my C# code with proper semicolons.

Boo’s has optional semicolons, so you can put them or not, as you wish. This makes dropping into the language for a while a far smoother experience, since you don’t have to unlearn ingrained habits.

And one last sample program before we get back to talking about Domain Specific Languages. Listing 6 is a simple implementation of GREP.

Listing 6 – A simple GREP implementation


import System
import System.IO
import System.Text.RegularExpressions

# get all files matching a specific pattern from a directory
# and all its sub directories
# note: string* is a shorthand to IEnumerable<string>
def GetFiles(dir as string, pattern as string) as string*:
# get all sub directories
folders = Directory.GetDirectories(dir)
# for each sub directory, recurse into that directory
# and yield all the files that were returned
for folder in folders:
for file in GetFiles(folder, pattern):
yield file
# yield all the files that match the given pattern
for file in Directory.GetFiles(dir, pattern):
yield file

# argument validation
if argv.Length != 2:
print "Usage: grep [pattern] [regex]"

filePattern = argv[0]
textPattern = Regex(argv[1])

# get all the files matching the pattern in the current directory
for file in GetFiles(Environment.CurrentDirectory, filePattern):
# for each file, read all the lines
using sr = StreamReader(file):
while line = sr.ReadLine():
# if the line match the given pattern, print it
if textPattern.IsMatch(line):
print file, ":", line

A few points on interest in listing 6, GetFiles returns a generic type, IEnumerable of string (T* is Boo’s way of specific generic enumerables), it also uses yield to return results in a streaming fashion, the while loop will repeat until line will return a null reference (which is considered to be false in Boo).

We have gone over the major benefits of Boo as a language and its basic syntax. I hope that this gave you some feel about the Boo language.

(1) Well, if you are interested in creating a new language called Ba, you probably would want to make it clear where the project ancestry came from.

(2) C# 3.0 has introduced the var keyword, which allows the C# compiler to do much the same for local variables. Boo supports this for just about everything (fields, properties, methods, local variables, etc).

(3) Backus Naur Form – a formal way to specify the syntax of a computer language.

save
Topics:

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}