Posts Tagged ‘Lisp’

There are wide choice of programming languages catering to a diverse application domain. This post is an attempt at classifying them based on how much the language/implementation tries to abstract the machine details from the programmer.

We can broadly classify languages as

  • Assembly language (x86 assembler AT&T syntax or Intel syntax)
  • Compiled (C)
  • Compiled to byte code of VM and compiled just in time (Java2)
  • Compiled to byte code of VM and interpreted (Python)
  • String interpreted (TCL)
Assembly Languages

Such languages need the least amount of work to make them executable. Assemblers like the x86 assembly language is closely tied to the machine code. It is basically a one is to one mapping between machine instruction to a human readable string called mnemonics. Assemblers also make it easy to assign labels to address locations to ease programming effort. Modern assemblers also support macros which can make programming repetitive code easier. There is little scope for optimization or higher order data structures in assembly languages, since they just mirror the target machine code. Such languages are the least portable since they are always tied to a target machine architecture. Few examples of assembly languages would be the x86 assembly language, Motorola 6800 assembly etc.

Compiled Languages

Such languages are a step taken for portability. They abstract the underlying machine instructions and give higher order constructs for arithmetic operations, branching, looping and basic data types. They are compiled in to target machine code directly. Once compiled, the binary can be natively run in the target machine. Arguably they are slower than assembler, since the actual machine code is generated by a compiler and will not be as optimized as hand coded assembler. But in practice, for any modern processor with multiple cores and pipelining, the compiler tends to generate more optimized code. Such languages can have support for higher order data structures like lists, maps etc either natively or via standard libraries. C, C++, Pascal etc are some examples of compiled languages.

Compiled to Byte Code of a VM (JIT compiled)

These languages are another step towards portability. First they are compiled to byte code of a virtual machine. The virtual machine executes the byte code by compiling it in to native machine code Just In Time (JIT). Practically these are slower than compiled languages since there is another layer of abstraction. But they are more portable than compiled languages. The same compiled byte code can be run on any platform that supports the VM, while for compiled languages, different binaries are required for different platforms. Typically they support a full range of higher order data structures. Examples include Java2, Ruby core 1.9.

Compiled to Byte Code of a VM (Interpreted)

The first step of these languages is the same as the above. They are compiled to byte code of a virtual machine. The virtual machine itself executes the byte code by interpreting it. They are generally slower than JIT implementations. They have same portability as JIT implementations. Performance also depends on the optimization effort gone in to the VM implementation. For example Python2 (byte code interpreted) is faster than Ruby core 1.9 (JIT) while Java2 (JIT) is way faster than compiled Lisp (SBCL). Examples include Python, Ruby.

String Interpreted

Such languages interpret the source code string directly. Because of this, these are usually the slowest of the lot. Consider this statement – a = 100 + 2. The 100 and 2 are strings and instead of doing the addition 100 + 2 natively, the interpreter knows how to add integers as strings. The interpreter is easier to implement than byte code compilation but performance is the least. TCL, JavaScript are examples of string interpreted languages.

We can see a pattern emerging. From assembly to string interpretation, the language/implementation abstracts machine details more and more from the programmer. As a result performance keeps decreasing while portability keeps increasing. Beyond a point, performance decreases without any increase in portability, but implementation becomes easier. Also more abstracted languages usually provide higher order data structures and automatic memory management for free.

Also the level of abstraction really depends on the implementation rather than the language itself. For example, Python2 is both byte code interpreted (official CPython) and JIT (PyPy). The implementation can vary not only in the VM. For example Common Lisp has a compiled implementation (SBCL), compiled to C/C++ or byte code interpreted implementation (ECL).

Advertisements

For anybody who loves programming, there is a problem of plenty. Naturally we are curious to learn more and there is simply too many options to pursue. When I started my career 4 years ago, the only language I knew fluently (well kinda) was C. I wanted to learn C++ and a scripting language for rapid prototyping. It has been 4 years, and I have learnt C++ and Python.

Now comes the predicament. What to study next. There are plenty of options. Should I study GUI programming via wxWidgets or learn Internet technologies like HTML and JavaScript. Both will not help me in my line of work (carrier class embedded software development in telecom domain). But it will be fun, and turn around time is much quicker. Applications always have this magical aura of being useful directly. Users interact with application directly and the developer gets feedback instantly. With infrastructure like Linux or the iPhone, we have to wait for some application to utilize the new goodies so that end users can appreciate the infrastructure.

Or I can take MIT Open Course Ware course on Operating Systems or strengthen my knowledge of algorithms. Both will help me in my line of work and should be tons of fun. But people around me (friends and relatives) identify with Internet technologies much better. Imagine showing my dad a terminal shell on the basic OS I wrote as part of MIT OCW or red black trees in action. Now imagine showing my dad an iGoogle widget written in HTML and JavaScript that he can interact with. But having a better understanding of the infrastructure OS or the algorithms can make us better programmers in general. This will benefit application programming too.

Another fascinating thread to follow is to learn Lisp. It may not give us any practical benefits. But I trust people when they say that learning Lisp is a profoundly enlightening experience for a programmer. I want to experience it first hand. But should I take it up now? If not now when?

Apart from technology, processes and paradigms are also a good candidate to delve into. Modern software engineering principles, design patterns, architectures, refactoring, software metrics, aspect oriented programming, functional programming, concurrent programming, literate programming etc are also promising. All of them, like investing in infrastructure, will help in general.

One of the things to consider while choosing is, how long will it be relevant. Ideally, we do not want to invest in something that will become irrelevant in the future. Till now I have invested in time proven technologies/tools like C, C++, Python, Vim, Linux… which are here to stay for good. Another aspect of relevancy is that it should be universally useful. It should still be relevant outside of my current organization, without licensing issues. Copyrights and licenses can make a current technology irrelevant for our purposes. Sticking with open standards and open source technologies with strong communities and vision ensures that our investment will not be obsolete quickly. HTML, JavaScript, OS concepts, algorithms and Lisp all are here to stay for good. Processes and paradigms may or may not stand the test of time and can quickly become a fad. Plus they can be picked up while focus is on learning the others.

So we have 3 main streams to pursue. Internet technologies (HTML and JavaScript), infrastructure (OS and algorithms) and Lisp. Well investing in infrastructure seems to be the most logical choice for me. It will directly help me in my line of work. It will help me be a better programmer by providing me a better understanding of the underlying universal principles of computer science. Both will be around for a long time (forever is more like it). Both will help me in my pursuit of the other two streams. So this can be a foundation for the other two streams 🙂

I am not the only on faced with this predicament. I quote Frederick P Brooks Jr from The Mythical Man Month.

The computer-related intellectual discipline has exploded as has the technology. When I was a graduate student in the mid-1950s, I could read all the journals and conference proceedings; I could stay current in all the discipline. Today my intellectual life has seen me regretfully kissing sub discipline interests goodbye one by one, as my portfolio has continuously overflowed beyond mastery. Too many interests, too many exciting opportunities for learning, research, and thought. What a marvelous predicament! Not only is the end not in sight, the pace is not slackening. We have many future joys.

So it is not really a predicament. We are just spoilt for choice. As Brooks predicts, we have many future joys. Amen.