Erlang Programming Exercise: 3-1
I'm posting the exercises starting with chapter 3. The previous chapters have you work in the shell and don't require much file work. Exercise 3-1 is:
Write a function sum/1 which, given a positive integer N, will return the sum of all the integers between 1 and N.
And the second part:
Write a function sum/2 which, given two integers N and M, where N =< M, will return the sum of the interval between N and M. If N > M, you want your process to terminate abnormally.
Here is my solution: threeone.erl
-module(threeone). -export([sum/1, sum/2]). sum(1) -> 1; sum(Number) -> Number + sum(Number - 1). sum(Lower, Lower) -> Lower; sum(Lower, Upper) when Lower =< Upper -> Upper + sum(Lower, Upper-1).
If you give sum/1 a number less than 1, you'll infinite loop.
The above solution doesn't use Erlang's tail call optimizations. If you give them a very large set of numbers to add up, they keep eating up memory. I wanted to see what would happen when it ran out of memory or stack space, so I told it to sum up a billion. After my system started swapping and started to crawl I killed the process. Maybe next time.
Here is the reworked version that takes advantage of tail call optimization and can sum up numbers from 1 to a billion without making my system swap. The beam.smp process stays around 10mb of memory.
-module(threeone_tco). -export([sum/1, sum/2]). sum_range(Sum, Lower, Lower) -> Sum + Lower; sum_range(Sum, Lower, Upper) -> sum_range(Sum + Upper, Lower, Upper-1). sum(Number) when Number > 0 -> sum_range(0, 1, Number). sum(Lower, Upper) when Lower =< Upper -> sum_range(0, Lower, Upper).
The big change comes from passing the Sum as an argument to the next function call. To use TCO (Tail Call Optimization) you want to leave no work to be done in your function, and the last thing your function does, should be calling itself. Previously, the function would still have to add two numbers after it's recursion finished.
Cheers,
-Halzy
Learning Erlang
It all started way back when I was doing concurrent programming in Java for the MMORPG when a buddy of mine pointed out CouchDB. It's a neat project, but was written in some strange language called Erlang. I started to look more into Erlang and found that the language was designed to addressed some of the more complicated aspects of concurrent programming. This appealed to me because those were my current pain points with the game. When do we lock around what data, which threads are changing what, do I need to use volatile for this variable too. It's a lot to think about, it's hard to get right, and Erlang solves those problems for you if you're willing to think differently.
I started by reading Programming Erlang by Joe Armstrong and now I'm reading through Erlang Programming by Francesco Cesarini and Simon Thompson. I'm enjoying the second book more than the first one, but this could be a side effect of being more comfortable with Erlang because I read the first book. I'm so taken with this bizarre language that I've decided to work through all of the exercises in Erlang Programming. I'll be posting my solutions and hopefully, by the time I get through all of them I'll feel comfortable enough with Erlang to build something with it.
Cheers,
- Halzy
Quick math game.
Yesterday I made a quick math game to help with some math studies. You have to click on the game, then type in the answer and hit enter (or click GO!).
C++ and Spirit
So I've been busy doing taxes, getting over my cold, and refreshing my C++. As part of the C++ refreshing I was using Antlr and some STL libraries. While looking at the STL libs I also went to look at Boost, only to find Spirit, a C++ recursive descent parser. I haven't looked at it much, but I'm going to re-do the first couple examples using it, and compare them to the Antlr versions. It may be better suited for what I'm doing since Antlr 3 doesn't have a (working?) C++ output. I know already that if I switch, I'm going to miss AntlrWorks.
Antl3 actions in C
I started working with rule actions in Antlr 3 + C (A3C). In section 3.2 of the book Terence adds an action to load a stored value from a recognized ID. I decided to keep it simple and just print out some information for that recognized ID. My action grammar:
atom returns [int value]
: INT
| ID
{
printf("Position: \%d\nToken Index: \%d\nText: \%s\n", $ID.pos, $ID.index, $ID.text->chars);
}
| '(' expr ')'
As you can see, the rule for atom is looking for ID which is defined as ('a'..'z'|'A'..'Z')+. When it finds this alphabetic string it's going to print out the position of where it appeared on the line, its index and the value of the token (the matched text).
The action token ID.text is very similar to the Java equivalent, the difference being that it is a struct and to get to the characters you have to use the struct's chars variable. You can find the struct defined in antlr3string.h.
There are a couple of other properties that you can use off of the token variables. Other than .text, you can use: (this is mostly for my own reference).
- type
- line
- pos
- channel
- index
- tree
TTFN!
Y! Q2/07 Hack Day
Today Yahoo! released the AS3 version of their maps API. They also released the hack that Jon and I worked on back in Q2. Check it out, and if you don't have Flash9 and refuse to upgrade, you can try spinning and flicking your iPhone to simulate it*. You almost get the same effect.
*You assume full responsibility for any damages done to your iPhone.
Antlr3 + generated C + OSX
I've been a fan of Antlr for a while now. I've used it to generate intrinsic classes for ActionScript2 so that our team could build an incremental compiler. I just bought the Antlr3 book (in PDF format) and have been going through the examples as I reach them.
As I went through the book I decided that I wanted to combine learning Antlr with my recent LLVM fascination. LLVM is in C/C++ so I decided to use the 'C' output language option in Antlr. I haven't found any documentation on line on how to use the C API, but through some trials I've ported the first example in the book to C.
The first big trial that I faced was that XCode defaults to C++ mode, which is fine for compiling C code as long as you use the right decorations. Some of the Antlr3C support lib uses 'or' which the preprocessor converts to '||'. I spent a day and found that you can disable this by using the '-fno-operator-names' compiler flag.
Most of the code is very similar to the Java version. The second problem I ran into is when you try to connect the dots between creating the lexer and the parser. In Java you just create a CommonTokenStream and pass the lexer into its constructor. In the C version you have to drill down the nested structs to find the token stream. It's not hard to find, it just takes way to long to drill down through the files.
extern "C" {
#import <antlr3.h>
#import "ExprLexer.h"
#import "ExprParser.h"
}
int main (int argc, char * const argv[]) {
if(argc != 2) {
printf("Which file do you want to parse?");
return 0;
}
pANTLR3_INPUT_STREAM pInputStream = antlr3AsciiFileStreamNew((pANTLR3_UINT8)argv[1]);
pExprLexer exprLex = ExprLexerNew(pInputStream);
pANTLR3_COMMON_TOKEN_STREAM pTokenStream = antlr3CommonTokenStreamSourceNew(0, exprLex->pLexer->tokSource);
pExprParser exprPar = ExprParserNew(pTokenStream);
exprPar->prog(exprPar);
return 0;
}
Seaside — Bobbing
Well, I made it to the end of chapter four. I'd have gone on but www.swa.hpi.uni-potsdam.de seems to have died for the moment. The tutorial is writtem for Squeak which means that those of us running VisualWorks get to debug learn more.
Some of the subtle differences betwen Squeak and VisualWorks crop up. The Date objects in Squeak have a 'yesterday' and 'tomorrow' versus the Date object in VisualWorks which has a 'today' which you can add and subtract days from. OrderedCollections are different enough to make you go look up function names.
Hopefully the server comes back up so I can finish the other 6 chapters. KTHNXBAI!
Seaside — Sink or Swim
On their site they have a couple of examples, the 'easiest' is a counter. I have no idea how to replicate that in VisualWorks/Seaside. This is my first VisualWorks/Seaside app. Lets see how well it goes.
I've found a neat tutorial: http://www.swa.hpi.uni-potsdam.de/seaside/tutorial
Hopefully it explains some things. It seems objects have an odd lifespan. :-S
