Showing posts with label coding. Show all posts
Showing posts with label coding. Show all posts

Thursday, November 29, 2007

Writing and Coding, Part 3: Artistic Expression

All right, I'll admit it. I've been putting this part of the series off. This is a huge topic, and the more I've thought about it, the less I feel I can do it justice in the time I have to prepare and the space I have to expound on it here. So instead of doing an in-depth exploration, I'm going to provide a very high-level overview. Put on your running shoes. Artistic Expression Programming seems to be a creative, artistic endeavor in two ways. First, you have phenomena like perl poetry, where code is explicitly, consciously used as poetry. This is related to the school of thought that looks at programming's primary purpose being communicating algorithms to a person. Executing the code on a computer is secondary, a means of making sure you are correctly expressing the algorithm. Aesthetics: De Gustibus Non Disputandum Personally, I tend to having simple, regular syntax, even at the expense of having simple, regular semantics (although I like that to be simple also). This bias is evident in a couple of ways: First, I prefer Python to Ruby. Ruby's semantics are probably more regular (everything's an object vs everything's an object, but it may be a classic object and some things are sealed), but the few times I've attempted to learn Ruby, the syntax just seems a little irregular. Not in a bad way, necessarily, but enough that it's squelched what little motivation I've had so far to learn what is probably a fine language. But that's beside the point. What I'm trying to illustrate is that people judge programming languages partially according to criteria that is strictly non-utilitarian. Having simple syntax doesn't make any difference in how capable Python is at building, say, web apps. (As I type this, I'm mentally constructing an argument that it does, but in general, I stand by this statement.) Of course, the academic in me is wanting to step back and define terms now. What does aesthetics mean? Maybe it's time to step back, pull out some literary theory books, and see where this leads us. Is there anything more dull than someone who is both a literature- and computing-geek?

Tuesday, November 27, 2007

Programming Fun

I just ran across a great post on Ruby being designed to be fun. I don't program in Ruby myself, yet. I've attempted to learn it several times. I get started working through Programming Ruby, but I never get very far. I never have much motivation to pick it up. It seems to occupy a niche that is happily occupied by Python in my programming ecosystem. If another language is going to displace Python, it will probably be some form of lisp. In the end, what finally makes me set aside Ruby are aesthetic reasons I'll talk about more later (when I finish the Writing and Coding series I'm working on). Of course, I also looked at Python once or twice before it clicked for me, so maybe there is some Ruby in my future. Still, I think that it is great that Ruby is designed for fun. When I did finally "get" Python, I had just come out of bad experiences with two other programming languages: I had hit Perl's 1000-line limit; then I switched to Java. Java's great, but it's not fun. Python made programming fun again. That sounds like I had just gotten out of two bad relationships when I met her. And maybe that's what it was.

Sunday, November 18, 2007

Writing and Coding, Part 2: Self-Discovery

One reason people create things, art generally, but I'm arguing here that creation in itself of anything is an act of self-discovery. People say that writing is an act of self-discovery. Journaling is writing for no purpose other than self-discovery. But even writing that is meant for public consumption also often helps the writer learn about herself. Of course, the act of self-discovery—like creativity—is usually messy, and writers rarely let it out in public. I remember that for one class I wrote a lot of personal essays, a form that I really enjoy (hmm, a blog?). I would pick a topic to write on. I'd get started, heading in one direction. About half way through, I'd discover something about myself or about the topic I was writing on. Because of that revelation, the essay would take a sudden turn and head off in another direction. That was good; I counted on it, hoped for it. But it made more work for me, because then I would have to fix the first half, make the whole essay go in the direction the last half did. Part of the essay would be thrown away, but in the end, I'd learned something, and the essay was much better. I've heard about others who draft novels by throwing away the first, the second, and even the third drafts. That astounds me. Knowing how much work goes into a novel, I have trouble imagining throwing a draft away. On the other hand, it would probably make a better final product. I just wonder if more planning up front could take the place of making such drastic edits. So when I write for self-discovery, I don't know where the work is headed, and I have to be willing to cut drastically, even throw out whole drafts. How does this apply to programming? Supposedly, Richard Feynman had written on his chalkboard, "What I cannot create I do not understand." Part of the programming I do is to help me understand problems. I'm not by nature a detailed thinker. I prefer to stay in the clouds, thinking about things in an abstract way. Programming requires me to be specific, however, and to think problems through thoroughly. In solving a problem in code, I learn something about the problem and what it takes to solve it. In learning to solve a problem this way, I often work my way to a solution gradually. I open up a REPL (lisp read-eval-print loop) or Python interactive interpreter. I open up a text editor. I go back and forth between the two, feeling my way to a solution. Working this way is fun, but it is wasteful. As I'm doing it, I may attempt several solutions that have to be thrown away. And often, the code that results is a mess and has to be thrown away anyway. But at that point, I understand the problem and what it takes to solve it, and I can quickly write something much better. That process sounds like what I did with the personal essays. But I am learning something about myself on this? After all, I'm talking about self discovery in this posting, not problem understanding. It can be. I should probably write another post focusing on this assertion, arguing just it, but the act of creating anything teaches us about ourselves, if we're listening. How do we interact with the environment we're changing? How is our approach different than other people's? Why is this problem interesting, not that one?

Friday, November 16, 2007

Writing and Coding, Part 1

When I named this blog, part of the reason I chose this name was because I enjoy both writing and coding, and I wanted to talk about both. I didn't want to start two blogs, however, and later abandon both. I would rather just abandon one. (There are already a few abandoned blogs with my name on them. No sense adding to that number without reason.) The other reason is that I've always thought that there are similarities between the two activities, as well as big differences, and I wanted to explore these. A lot of people have written on these before or presented papers. This is just my take. This is a complicated, many-faceted topic, so it will take me several days to discuss this. Here's the plan:
  • Writing and Coding, Part 2: Self-Discovery
  • Writing and Coding, Part 3: Artistic Expression
  • Writing and Coding, Part 4: Test-Driven Writing
  • Writing and Coding, Part 5: Ambiguity
  • Writing and Coding, Part 6: Conclusion

Wednesday, November 14, 2007

Editing Lisp

In which I decide to start hacking in lisp, and that rocks my editing world. The options for editing lisp in Vim are pretty limited. Well, let's be precise. Vim is a pretty good lisp editor, when you compare it with almost anything except emacs. There have been attempts to bring Vim up to emacs' level. There was a project to integrate ECL with Vim. It was part of a larger project, Slim-Vim to write a Vim interface to SLIME, the excellent emacs lisp development system. Unfortunately, Slim-Vim is dead. Both of its primary developers have abandoned it. According to their farewell emails, one now develops lisp using a commercial IDE, and the other uses emacs and SLIME. Generally, the advice for people like me is to suck it up and use emacs. You will be assimilated. Others do still use Vim for lisp, and I still prefer Vim for actually editing lisp. I've done some crazy, complicated things to get it to integrate with a running lisp system. The version of lisp I usually use, SBCL, doesn't include readline in the REPL ("Use SLIME," they say), and using it without command history, etc., is painful. So I would start emacs and SLIME, and I would start Vim. I would open the file in both emacs and Vim. Editing would occur in Vim, then I would refresh the buffer in emacs and feed my changes into SBCL. I know. Suck it up. Use emacs. Eventually, that will be how this story ends. First, I'm going to try Cusp, an Eclipse plug in for lisp development. Aside from being a lot prettier, I'm not sure what it has over emacs+SLIME. What do you use for lisp hacking? (If I get no answers, I'll assume everyone uses emacs.)

Tuesday, November 13, 2007

A Theory of Text Editors

When I started working with LINUX, I used GNU emacs. At the time, I was using some low-end hardware, even for the time. One day, I realized that my morning routine was to boot up, start emacs, and make a cup of coffee while I waited for emacs to wake up in the morning. That was insane. There was a lot I liked about emacs, but I needed something lighter weight. So I switched to Vim, and I still use it for all my editing needs. Vim messes with your brain. Once you've internalized the keystrokes, you're ruined for other editors. In the past, I would sometimes think that I needed to enter the 20th century and try some other editor—Eclipse, jEdit, or something. I'd install whatever it was I planned on using and tweaked it out, but I only used it at most a day, and the entire time I'd be thinking, "I could do this so much more quickly in Vim." Finally, I'd switch back just to make myself shut up. Of course, to really test drive a text editor, you need to give it a few weeks, so I never gave any of these a fair shake. I even tried viper once. This was a mode in emacs that used vi keystrokes and commands. I only used it about thirty minutes. It was too confusing. I remember the emacs keystrokes enough that I couldn't never quite decide whether I should use them or vi. I was less productive with it than I was with emacs by itself. My theory is that there are two levels to text editing: High-level semantics and low level syntax. I'll be abusing both of these terms, so let me explain what I mean by them. If you're editing Java or C# or Python or Lisp, semantics involves the libraries you're using. What properties does a Button have? What arguments does socket.socket take? Which comes first in elt, the index or the sequence? Eventually, if you use the language and its libraries enough, these questions go away. The other level is syntax. This involves editing at the character level: entering text, copying, pasting, moving, search-and-replace. This never goes away. In my experience, most IDEs are great at the semantic level, but poor at the syntactic level. They will answer any questions you have about the libraries and the language, but if you have to a sequence of keystrokes 1000 times, it is painful. Usually possible, but painful. On the other hand, Vim is brain dead at semantic stuff. At the syntactic level, however, once the keystrokes have branded themselves onto your brain, no other editor comes close. It tells you nothing about the objects, methods, or functions that you're using, but if you have to repeat something 1000 times, bang, you're done. So what's the point? Well, this posting actually started out as a discussion of editing lisp. It seems to have gotten derailed though. Lisp will have to wait for tomorrow.

Thursday, September 27, 2007

Targeting the DLR

I've been circling warily around CarbonLisp again. I think I've decided not to target the DLR initially. Instead, I will have a compiler that, like Common Lisp, will produce code that varies from very dynamic to static. Once that's done, I may add a DLR component. Of course, I have to get started first.

Thursday, September 20, 2007

Common Lisp Tutorial

If you want to learn Common Lisp, an excellent option is Practical Common Lisp, which is also a Lisp tutorial. It's available both in print and on-line. (Note, I get nothing from this shameless plug. But I do honestly recommend it. I have my own copy, and I refer to it regularly.)

Sunday, September 16, 2007

LiSP, Revisited

Remember that I ordered a copy of Lisp in Small Pieces from a sales that Amazon.ca was putting on? Like many people, I was informed that the price was due to a mistake, and they were canceling my order. Easy come, easy go. C'est la vie. Fill in your favorite cliché here. I did look at a copy of the book in a library. (I don't qualify for a library card there, so I didn't check the book out.) It looks like a great book. Maybe I'll have to get off my wallet and buy it anyway. While browsing through the book, I realized that I'm attempting to implement too much of Common Lisp initially. For example, the lisp reader needs access to the full-fledged lisp system in order to modify its own settings. It's a chicken-and-egg situation. You need a full lisp system to completely implement the reader, and you need a reader to completely implement the system. The answer, of course, is to implement a very restricted subset and bootstrap your way up. Duh. Anyway, now I think I have a plan to go forward with. I haven't done anything on it yet, though. I'll keep you posted when I do.

Tuesday, August 14, 2007

Lisp in Small Pieces

Amazon.ca was having an unexpected sale on Lisp in Small Pieces, one of the best books on implementing lisp. For about a day it was selling better than Harry Potter. Hmm. I'm implementing lisp, and I could always use a new book. My copy will arrive in two to four weeks. Until that time, CarbonLisp is going on vacation. In the meantime, I'll work on and blog about other projects.

Wednesday, August 8, 2007

Roadblocks and Dynamic Coding

What's happened since my last posting?
  • Google's identified this blog as a potential spam-blog and locked me out. I've gotten it unlocked. I guess i need to post more often.
  • I've gotten most of the framework code for the DLR finished. Nothing exciting, and I'm sure it's bug-ridden, but it's a start.
  • I've started on the lisp reader, and I realized I don't know what I'm doing. Fools rush in where angels fear to tread, and all that. Part of the problem is that I'm really doing exploratory programming, but in a static language. I'm not a big static language fan, anyway. I'm considering doing a toy implementation of lisp in Python to get started and to figure out what I'm doing.
I know, I know. That last point is just crazy talk. Of course, this whole blog has turned into the ramblings of a madman, anyway, so why the hell not get some traction by doing some exploratory programming in Python, then moving back to C#.

Sunday, July 29, 2007

Back from Vacation and Names

Most of last week I was on vacation. The rest of the week, I've spent a little time digging into ToyScript and filling out the framework I'll need for implementing lisp on the DLR. More about that later. I've temporarily decided to call this project SiliconLisp. This roughly follows the convention of naming dynamic languages for the CLR as Iron-. I've just changed the element it's made out of. Actually, I was originally going to call it CarbonLisp, but I didn't want to confuse this with the Mac windowing library Carbon. I may go with CarbonLisp anyway. If you have a suggestion for the name, please leave me a comment.

Wednesday, July 18, 2007

Looking into ToyScript

I'm checking out John Lam's ToyScript. It's an implementation of a small scripting language, and it was written as an introduction to working on the DLR.

Monday, July 16, 2007

Lisp and .NET

The Truth about Lisp Why does that link matter? Because I've been thinking about implementing Common Lisp on the CLR and the DLR. When interpreted, it would primarily work with the DLR, but as declare statements are added and the Lisp code becomes more static, it would be able to leverage the CLR directly. At one point, I was thinking about implementing Scheme, but I've moved away from that. When I started learning Common Lisp, I thought that I preferred Scheme. But now I've done a project in Scheme (a simple todo-list manager, similar to todo.txt, and I've decided that I prefer Common Lisp after all. Scheme's still great. I have a nice clean feeling whenever I code in it, but I think I prefer CL's more complete language specification. It's still not really complete enough. (Hello? threads, networking, Hello?) Also, I'm beginning to grok continuations, but I don't have a clue how I'd implement them in .NET. So I'm just not doing that right now. Still, what craziness is this? Well, I've been doing a lot of .NET at work, and I'd like to be able to use a more powerful, sane (for some definition of sane) language. I'd also like to be able to produce assemblies that can be called from C# or whatever. Basically, I want a lisp that is a first-class citizen of the CLR. And I've been wanting to do more Lisp for my personal projects. I'll let you know how it goes. Or I'll put my head between my knees and breath deeply until this latest light-headedness passes.

Monday, May 28, 2007

Erlang: The Pros

I had meant to post this much sooner, but there's been this thing called work. It gets in the way. Finally, here is the second half of my overview of Erlang. Concurrency Given it's background, it's no surprise that concurrency is easy and cheap in Erlang. Here's a contrived example:
12> PrintRandom = fun() ->              
        {A, B, C} = erlang:now(),           
        random:seed(A, B, C),
        io:format("~p~n", [random:uniform()])
        end.
#Fun

13> lists:foreach(fun(_) -> spawn(PrintRandom) end, lists:seq(1, 10)).
0.664105                                                             
0.664137
0.664170
0.664203
0.993887
0.993920
0.993953
0.993986
0.994019
0.994052
ok
First, the state for the random number generator is stored in each process, and it's initialized from a standard value. (Actually, maybe the random module should be on my Erlang: Cons list, although having the random module not produce random numbers probably makes debugging easier.) Line 13 spawns 10 processes, each of which prints a random number. Not very useful, but it should illustrate how easy it is to create processes. Also, you can easily spawn a lot processes. This code generates a random number and throws it away a million times in a million processes, and it executes in about 3.5 seconds on my machine:
-module(timespawn).

-export([make_random/0, spawn_random/1, ts/1]).

make_random() ->
    {A, B, C} = erlang:now(),
    random:seed(A, B, C),
    random:uniform().

spawn_random(0) ->
    ok;
spawn_random(X) ->
    spawn(fun make_random/0),
    spawn_random(X-1).

ts(X) ->
    timer:tc(?MODULE, spawn_random, [X]).
Distribution Another nice aspect Erlang is how easy it is to distribute processing. This is partially due to its open security model, which I listed as a negative. For example, in two separate console windows, I can start two different instances of Erlang. As long as I pass both the -sname argument (with different values) and the -setcookie argument (with the same value), they can talk to each other, even if they're on different computers in the same network. Functional I've worked with functional languages in the past, but I haven't really drunk the functional Kool Aid until now. I'm enjoying it this time, though, and want to start working more with one of the Lisps (probably Scheme), Haskell, or ML. When I do start on one (or more likely, on all) of these, I'm sure I'll talk about it here. OTP The OTP (Open Telecom Platform) is the standard Erlang library, and it contains modules that make writing fault tolerant, supervised, client-server, and distributed applications easy and fast. Conclusion I'm glad I've gotten to do a lot of Erlang recently. It's changed the way I think about concurrency and distribution, and it's raised my expectations of other systems that tackle the same problem. Even if I do most of my concurrent programming primarily in other languages, this will give me a good basis. And really, what more can I ask for from a programming language?

Sunday, May 13, 2007

Erlang: The Cons

Today, I'm going to talk about the warts I've seen in Erlang so far. I'm sure I'll find other things I don't like, and I'm also sure that I'll make peace with some of the things I've listed here. Nevertheless, here is my list of the bad and the ugly so far. (This isn't a tutorial on Erlang, so I'm not going to explain the code snippets below. Sorry.) Strings The one thing that really made me go "Yuck" as I was learning Erlang is strings. Strings are just lists of integers, which are treated as strings for printing. For example, if you crank up the read-eval print loop (REPL) and type in a list of integers, it gets printed as a string if there are no control characters in the string:
Eshell V5.5.4 (abort with ^G) 1> [69, 114, 105, 99]. "Eric"
Likewise, if you type in a string, it's interpreted as a list of integers:
4> lists:foreach(fun(X) -> io:format("~p ", [X]) end, "Rochester"). 82 111 99 104 101 115 116 101 114 ok
Initially, this just felt wrong to me. It still does in some respects, but I've also learned to appreciate how this makes string processing easy most of the time, particularly when it's coupled with Erlang's fantastic pattern matching features. For example, the function get_ints in the module below walks through a string and returns a list of all the integers in the string:
-module(get_ints). -export([get_ints/1]). get_ints(String) -> get_ints(String, [], []). get_ints([], [], Ints) -> lists:reverse(Ints); get_ints([], Current, Ints) -> CurrentInt = list_to_integer(lists:reverse(Current)), lists:reverse([CurrentInt|Ints]); get_ints([Chr|Data], Current, Ints) when Chr >= $0, Chr =< $9 -> get_ints(Data, [Chr|Current], Ints); get_ints([_Chr|Data], [], Ints) -> get_ints(Data, [], Ints); get_ints([_Chr|Data], Current, Ints) -> CurrentInt = list_to_integer(lists:reverse(Current)), get_ints(Data, [], [CurrentInt|Ints]).
To use this, save it in a file named "get_ints.erl", compile it, and call the function:
8> c(get_ints). {ok,get_ints} 9> get_ints:get_ints("This is the answer: 42"). "*" 10> get_ints:get_ints("This is the answer: 0, 42"). [0,42] 11> get_ints:get_ints("This is the answer: 0, 42, 23"). [0,42,23]
Notice that the first list of one integer ([42]) is interpreted as a string. I included the number zero (a control character) in the next test to force Erlang to print the results as a list of integers. Another small complaint with strings involves Unicode. I've done enough processing XML and processing phonetic data that good Unicode handling is important to me, no matter whether I'm using it much at the time or not. In one sense, Erlang handles Unicode just fine. A string containing a schwa character is just [601]. Unfortunately, this is the depth of its Unicode handling. It doesn't give you any information about the Unicode data points or a function to change a character from upper-case to lower- or vice versa. Security Another complaint is Erlang's security model. On the one hand, it has the virtue of being easy to set up, but if two nodes can connect and communicate, there's nothing one can't do on the other node. Having more fine-grained control over things would be nice. Speed Also, there's the issue of speed. Erlang is generally fast enough, and where it's not, you can easily set up a node written in C, Java, or C#. Still, being able to deal with everything in Erlang would be more convenient. REPL Finally, there are restrictions in working from the REPL that I could do without. To create a function like get_ints above, I more or less have to create a new module in a file and put the function there. There are ways to work around this, but they seem unnatural. I'd rather not use them. Nothing on this list is a deal-killer for me. I've been doing a lot of Erlang the past few weeks, and I've really enjoyed it. It's been productive and interesting. Still, I can always dream about a better world.

Sunday, May 6, 2007

Erlang: An Overview

Recently I've been programming in Erlang. It's a new computer language for me, and I thought I would talk about it. This will take several posts. Today I'll just provide an overview of the language and environment. Erlang was developed by Ericsson telecommunications for developing soft real-time concurrent systems. I've never developed real-time systems before, soft or hard, so I won't talk about that much. I haven't done a lot with concurrency, either, except a touch of threading here and there. Nevertheless, the concurrency and distributed features of this language are what really attracted me to it. Originally, Ericsson implemented Erlang in PROLOG, and this still shows in some parts of Erlang, such as the way it uses pattern-matching. As an undergraduate, I went through a period where I programmed more or less only in PROLOG for about two years, so a lot of this feels like a stroll down memory lane. Other parts are very new. It's primarily a functional language. It has a lot of features designed for doing telecom programming, such as processing binary data. Erlang code is organized into modules, which are compiled and run from a read-eval-print-loop (REPL). A short "hello world" style module would look like this:
-module(hello). -exports([hello/1]). hello(Name) -> io:format("Hello, ~p.~n", [Name]).
The -module line identifies the module, which is also the name of the file containing the module. The -exports line identifies the functions from this module that are exposed to the outside world. The hello function is the rest of the module. io:format is the standard way to print to the console. Next, I want to look at some of the parts of Erlang that I'm less fond of.