Showing posts with label life. Show all posts
Showing posts with label life. Show all posts

Sunday, May 10, 2009

Geeking out with Lisp Flavoured Erlang

One of the features I dislike the most about Erlang is records. They're ugly and they require too much typing. Erlang makes me write


Dog = #dog{name = "Lolo", parent = #dog{name = "Max"}},
Name = Dog#dog.name,
ParentName = (Dog#dog.parent)#dog.name,
Dog1 = Dog#dog{
name = "Lola",
parent = (Dog#dog.parent)#dog{name = "Rocky"}}


When I want to write


Dog = #Dog{name = "Lolo", parent = #dog{name = "Max"}},
Name = Dog.name,
Size = Dog.size,
Dog1 = Dog{
name = "Lola",
parent = Dog.parent{name = "Rocky"}}


In the defense of records, they're just syntactic sugar over tuples and as such they enable fast access into a tuple's properties despite Erlang's dynamic nature. In compile time, they're converted into fast element() and setelement() calls that don't require looking up the property's index in the tuple. Still, I dislike them because 1) in many cases, I'd rather optimize for more concise code than faster execution and 2) if the Erlang compiler were smarter could allow us to write the more concise code above by inferring the types of variables in your program when possible. (I wrote a rant about this a long time ago, with a proposed solution to it in the form of a yet unfinished parse transform called Recless.)

Parameterized modules provide a somewhat more elegant and dynamic dealing with types, but they still require you to do too much work. You can define a parameterized module like this:

-module(dog, [Name, Size]).

This creates a single function called 'new/2' in the module 'dog'. You can call it as follows:


Dog = dog:new("Lola", "big").


It returns a tuple of the form


{dog, "Lola", "Big"}.


You can't set only a subset of the record's properties in the 'new' function. This doesn't work


Dog = dog:new("Lola").


To access the record's properties you need to define your own getter functions, e.g.


name() ->
Name.


which you can call it as follows:


Name = Dog:name().


(This involves a runtime lookup of the 'name' function in the 'dog' module, which is slower than a record accessor).

There's no way to set a record's properties after it's created short of altering the tuple directly with setelement(), which is lame and also quite brittle. To create a setter, you need do the following:


name(Val) ->
setelement(2, THIS, Val).


Then you can call


Dog1 = Dog:name("Lola").


to change the object's name.

When LFE came out I was hoping it would provide a better way of dealing with the problem. Unfortunately, records in LFE are quite similar to Erlang records, though they are a bit nicer. Instead of adding syntactic sugar, LFE creates a bunch of macros you can use to create a record and access its properties.


(record dog (name))
(let* ((dog (make-dog (name "Lola")))
(name (dog-name dog))
(dog1 (set-dog-name dog "Lolo")))
;; do something)


LFE still requires us to do too much typing when dealing with records to my taste, but LFE does give us a powerful tool to come up with our own solution to the problem: macros. We can use macros generate all those repetitive brittle parameterized module getters and setters that in vanilla Erlang we have to write by hand. This can help us avoid much the tedium involved in working with parameterized modules.

(ErlyWeb performs similar code generation on database modules, but it does direct manipulation of Erlang ASTs, which are gnarly.)

Let's start with the 'new' functions. We want to generate a bunch of 'new' functions allow us to set only a subset of the record's properties, implicitly setting the rest to 'undefined'.


(defun make_constructors (name props)
(let* (((props_acc1 constructors_acc1)
(: lists foldl
(match-lambda
((prop (props_acc constructors_acc))
(let* ((params (: lists reverse props_acc))
(constructor
`(defun new ,params
(new ,@params 'undefined))))
(list
(cons prop props_acc)
(cons constructor constructors_acc)))))
(list () ())
props))
(main_constructor
`(defun new ,props (tuple (quote ,name) ,@props))))
(: lists reverse (cons main_constructor constructors_acc1))))


This function take the module name and a list of properties. It returns a list of sexps of the form


(defun new (prop1 prop2 ...prop_n-m)
(new prop1 prop2 ... prop_n-m 'undefined))


as well as one sexp of the form


(defun (prop1 prop2 ... prop_n)
(tuple module_name prop1 prop2... prop_n)


The first set of 'new' functions successively call the next 'new' function in the chain, passing into it their list of parameters together with 'undefined' as the last parameter. The last 'new' function takes all the parameters needed to instantiate an object and returns a tuple whose first element is the module, and the rest are the object's property values. (We need to store the module name in the first element so we can use the parameterized modules calling convention, as you'll see later.)

Now let's create a function that generates the getters and setters


(defun make_accessors (props)
(let*
(((accessors idx1)
(: lists foldl
(match-lambda
((prop (acc idx))
(let* ((getter `(defun ,prop (obj) (element ,idx obj)))
(setter `(defun ,prop (val obj)
(setelement ,idx obj val))))
(list (: lists append
(list getter setter)
acc)
(+ idx 1)))))
(list () 2)
props)))
accessors)))


This function takes a list of properties and returns a list of sexps that implement the getters and setters for the module. Each getter takes the object and returns its (n + 1)th element, where n is the position of its property (the first element is reserved for the module name). Each setter takes the new value and the object and returns the tuple after setting its (n + 1)th element to the new value.

Now, let's tie it this up with the module declaration. We need to create a macro that generates the module declaration, constructors, getters, and setters, all in one swoop. But first, we need to expose make_constructors and make_accessors to the macro by nesting them inside a (eval-when-compile) sexp.


(eval-when-compile
(defun make_constructors ...)
(defun make_accessors ...))

(defmacro defclass
(((name . props) . modifiers)
(let* ((constructors (make_constructors name props))
(accessors (make_accessors props)))
`(progn
(defmodule ,name ,@modifiers)
,@constructors
,@accessors))))


(defclass returns a `(progn) sexp with a list of new macros that it defines. This is a trick Robert Virding taught me for creating a macro that in itself creates multiple macros.)


Now, let's see how this thing works. Create the file dog.lfe with the following code


;; import the macros here

(defclass (dog name size)
(export all))


Compile it from the shell:


(c 'dog)


Create a dog with no properties


> (: dog new)
#(dog undefined undefined)


Create a new dog with just a name


> (: dog new '"Lola")
#(dog "Lola" undefined)


Create a new dog with a name and a size


> (: dog new '"Lola" '"medium")
#(dog "Lola" "medium")


Get and set the dog's properties


> (let* ((dog (: dog new))
(dog1 (call dog 'name '"Lola"))
(dog2 (call dog1 'size '"medium")))
(list (call dog2 'name) (call dog2 'size)))
("Lola" "medium")


This code uses the same parameterized module function calling mechanism that allows us to pass a tuple instead of a function as the first parameter to the 'call' function. Erlang infers the name of the module that contains the function from the first element of the tuple.

As you can see, LFE is pretty powerful. I won't deny that sometimes I get the feeling of being lost in a sea of parenthesis, but over time the parentheses have grown on me. The benefits of macros speak for themselves. They give you great flexibility to change the language as you see fit.

Wednesday, July 11, 2007

San Francisco ErlLounge, Jul 18th

About a month ago, I packed my stuff, said farewell to Boston, and moved to the San Francisco Bay Area. I currently live in the town of San Mateo, where occasionally cars drive by and people walk their dogs. It's very exciting. I will soon move to Palo Alto for a few months, and then who knows. Whatever it is, it won't be as lively as San Mateo.

I'm planning on attending the San Francisco ErlLounge on Jul 18th. Visit http://umichigan.facebook.com/p.php?i=2223888&k=33553ba7bd for details. You should attend if you can. I'll tell you thrilling stories about San Mateo. I promise.

On an unrelated note, the spammers got me beat, and I finally gave up and disabled comments on this blog. If you want to share your thoughts, you can email me at yarivsblog at gmail dot com.

Monday, November 27, 2006

Europe, November 2006

I'm here in Barcelona, where I will stay for a few more days until the end of my trip. I've had a great time, but I can't wait to get back home. It feels like it's time to go back to regular life.

I started in Stockholm, then I went to Copenhagen, Paris, Lyon, Granada, Seville and Barcelona. I spent a few days in most of these cities, where I mostly did a lot of walking around and sight-seeing. I visited a few museums, but I didn't want to spend too much time in museums because I tend to enjoy more wandering around the streets of a new city, soaking in their sights, smells, and sounds.

Seeing a number of artistic creations that are generally regarded as masterpieces has led me to think about where great software stands in the realm of creative endeavors. As in most fields, some software is great and some isn't, but how come most people don't value great software in the same way that they value great music, paintings or architecture? This question can be discussed in great lengths, but I think the answer boils down to the following points: software can only be understood by programmers -- to non-programmers, all code looks like the same gibberish (much code looks like gibberish to coders as well :) ); software is always utilitarian -- practically all software is written as a means to an end, not an an end in itself; software stimulates the left brain exclusively -- it doesn't trigger a gut reaction like other art forms because its appreciation always requires analytical thinking; most people don't care about how an application or a software library is written -- they just want it to work.

So, maybe great software will never be regarded as art, but I think most people would agree that software development is a craft that requires skill and creativity. In addition, all programmers would agree that some code is beautiful and some isn't. I think the field that resembles software the most in the way we regard its creations isn't sculpture, painting, or music, but math. Like software, math is arcane, complex, logical, and most of it is boring, but many mathematical proofs are among the greatest achievements of our civilization.

Ok, enough philosophising -- let's get back to my travels :)

I went on this trip because I had a strong itch to see more of Europe. It's safe to say that this desire is now quite satisfied. By the last week or so of my trip, I had actually gotten pretty tired of traveling. Although the cities I've visited have plenty of unique charm, visiting a sequence of cities for a few days each ends up feeling repetitive. It would probably be more rewarding to stay in one place for a longer time period, where I would get a richer exposure to the local language and culture. But then again, 3.5 weeks probably isn't enough time for a profound cultural experience, anyway. I would have to stay in a foreign country for at least a few months in order to learn the local language and feel a stronger connection to the place and its people.

(It may even require a longer period to make proper Cultural Learnings of Europe for Make Benefit Glorious Nation of U, S and A : ) )

I actually think I've had my fix of city traveling for a while. Looking back at my trips, I have enjoyed nature vacations more than anything, and there are plenty of natural treasures nearby, including many of the US national parks, that I haven't yet visited. Next time, I will try to plan a nice nature adventure.

When I get back home, I will have to plan the next phase of my career. I have a number of ideas for cool Erlang apps, and also a few offers for different kinds of gigs, but I haven't picked a concrete direction yet. I will certainly keep working on ErlyWeb (there are a number of small improvements I will make as soon as I get home), but I think ErlyWeb is quite good as it is and I don't want it to make it bloated by adding too many features to it. (One aspect of ErlyWeb that could definitely use some work is support for additional database drivers in ErlyDB, but I will probably let other developers lead this effort because I don't have a strong need for other drivers right now.) I will also try to build at least one of the apps I have thought up and see how far I can take it. If all goes well, it will become the next YouTube. If not, I hope it will at least merit a line or two on my resume :)

Boston, get ready to make room for one more person :)

Saturday, November 11, 2006

12th Erlang User Conference

Here I am at Stockholm, Sweden, blogging a day after the 12th International Erlang User Conference.

I had a blast.

I arrived here a few days ago after a long journey from Boston via Paris. A few days before I left, Joe Armstrong generously offered to host me. Accepting the invitation couldn't have been any easier -- I don't get to stay very often for 3 days with the creator of my favorite programming language :).

Spending time with Joe was great. We had many interesting conversations about Erlang, computer science, culture, business, politics, design, and life. It was a rare opportunity to befriend someone who has accomplished so much and who has such a wealth of knowledge and ideas about the fields in which I'm most interested.

Joe is passionate about concurrent programming and the design of fault tolerant systems. This is how he summarized the main ideas behind Erlang (I'm probably paraphrasing): "To build a fault tolerant system, you need at least two computers. Why? Because one of them can crash. If you have more than one computer, you need distributed programming. Distributed applications run in different threads, and therefore concurrency is an integral part of fault tolerant systems."

Many of the presentations were very interesting, but the best part (at least for me) was meeting all the Erlangers I knew only from email correspondence, among whom are Claes (Klacke) Wikstrom, Mickael Remond (the founder of Process One), Ulf Wiger, Robert Virding and many others.

Everyone I met was very friendly, intelligent, down-to-earth, and had a healthy sense of humor. They all love programming in Erlang.

I had a great time chatting with Klacke. Klacke has had one of the most impressive careers of anyone I've ever met. He's created Mnesia, Yaws, distributed Erlang, and many parts of the Erlang emulator. He's also one of the people behind Bluetail, Kreditor, and now tail-f. Klacke constantly comes up with great quotes. Here are a couple of good ones as I remember them: "It feels like I have a sharp knife in my pocket, and other people have a blunt one", "Some problems you can't imagine solving if you don't have the right tools".

I also enjoyed talking with Ulf Wiger, who has developed with Joe Armstrong a very interesting framework for cooperative web development in Erlang called Erlhive. Maybe we will have opportunities for collaboration somwhere down the road.

Finally, I had a nice tour of Stockholm today (but too bad it rained). It's a beautiful city. I walked around the old town and I also visited the Vasa museum, whose exhibit is an impressive warship from the 1600's that capsized due to an engineering blunder: to please the the King's whims, the engineers loaded the ship with too many canons. Due to the excess weight at the top of the ship, it had several glorious minutes of sailing before it sank in the Stockholm harbour. Oops.

I would like to write in more detail, but my jetlag is starting to wear thin and I have to get some sleep as I'm flying to Copenhagen tomorrow. After that, I'm travelling for 3 weeks in Europe, visiting Amsterdam, Paris, Lyon, the south of France, and Spain (mostly Barcelona).

I'll end this posting with few pictures I've taken:

IMG_2124
Me, Joe and Mickael Remond

IMG_2119
Me and Klacke, A.K.A the Erlang Open Source Web Squad. Our weapons: Erlang, Yaws and ErlyWeb. Our mission: to end web development suckage, one webapp at a time :)

Wednesday, September 06, 2006

First Day in Boston on the "Job"

Yesterday was my first day as a resident Bostonian as well as a semi-unemployed Erlanger.



I must say that although my original impression of Boston wasn't very enthusiastic, I think this town will grow on me.



Boston is a college town in the truest sense of the word. In New York, everyone looks like he/she came from a different planet: people dress different, look different, speak different languages, and seeking different goals. In Boston, on the other hand, you feel like almost everyone is a student. I live somewhere between Boston College and Boston University, which makes the impression even stronger.



Because of its abundance of colleges, Boston feels like a very young town. In my advanced age of 26, I can't help but feel like I'm a TA or something :)



My new "office" is the Boston Public Library on Copley Square:



IMG_1573.JPG



(You're probably wondering what that blue cow is doing there. Apparently, the cows are all over Boston. Check out the rest of the set for more cow pictures.)



IMG_1588.JPG



Sometimes I don't get why many startups spend their money on renting office space when you can get a comfortable, quiet environment with good internet connectivity for free at the public library. Maybe it's that VC money thing :)



The Boston Public Library actually wins in the tech department over the New York Public Library for providing free Wi-Fi in the entire building, not just one room.



I didn't get much coding done yesterday, but today I'm hoping to finish implementing transaction handling in ErlyDB. It might take longer, though, so don't get your hopes up too high :)

Monday, September 04, 2006

Goodbye, New York. Hello, Boston!

This past weekend, after a ~3 year tenure in Manhattan, NYC, I moved to Boston.



It was a crazy weekend that included endless shopping, moving boxes and furniture, painting walls, getting 2 parking tickets, and even attending my friend's wedding. (Guess where? In New York, of course! :) ).



I'm exhausted, but I made it.



Now I need to figure out my life out here.



Paul Graham thinks that nerds don't like New York. At least in my case, he's way off the mark. I love New York. I think it's one of the best cities on earth. No city is as exciting and fascinating as New York.



I will miss New York a lot.



Maybe Paul Graham is right: maybe I'm not a real nerd. Maybe all this Erlang stuff is just a facade, and deep down in my soul I really want to be a hip hop dancer or something :)



Nah... I really like coding. I enjoy this stuff. I sometimes work crazy hours just because I like it. When I don't work crazy hours, I often write code when I get home from work. Not always, though. I have a life outside of my MacBook.



So why Boston, of all places?



I didn't move here because I love Boston. I know Boston pretty well, and although I find it nice enough, I've never fallen in love with it. I definitely don't like it as much as I like New York.



The main reason I moved here is because my girlfriend of two years has been living here for a year now, and I wanted to live closer to her.



The second reason I moved to Boston is that wanted to be able to live cheaply for a while so I can live off my savings while I work on a fun project I want to build. I'm 26 years old, and I feel that this is a good time to do it. I don't have a lot of money, but I also don't have a wife, kids, college bills or mortgage payments. I don't even have a car (I'm from New York, remember? :) ). My savings will carry me for a few months. After that, maybe I'll have to find a real job or a consulting gig or something.



If that happens, I'll cross my fingers and hope that I can get a gig writing Erlang code.



I really enjoy working with Erlang much more than other languages for some reason. I don't even know if it's worth it anymore trying to come up with an objective-sounding list of justifications rather than just saying that I like how it feels.



Even if my project doesn't take wings, my investment in it will certainly bear fruit as I am planning on releasing all the framework-level code I write as open source. ErlyDB will see many improvements, but I will also probably release contributions to higher levels of the Erlang web development stack.



I hope that in a number of months, few people will question that Erlang is a great language for building cutting-edge web applications.



We'll see how all this plays out. I'll keep you posted on my progress.