Nit-picking languages

It’s that (too frequent) time again … when I anxiously (and full of fickleness) wonder what language to increase familiarity with.

The last year, I learnt quite a bit of common lisp, or atleast enough to write a lot of exploratory code in, working with libraries, timing, profiling, improving, and so on.

I had a rude shock when I learnt from one of my Scheme heroes that he really just prefers Haskell now. WTF? But seriously, he makes good points, chief among which is the lack of confidence in refactoring existing lisp code.

But both have the same “lack of libraries” barrier (sure, you’d say, why don’t you build your own — but that’s not the point).

So I’ve been moving around among these, toying with some web-development style languages (and always recoiling from JS), when I suddenly realized that I have absolutely zero experience with any of the .Net languages.

So, (just thinking out loud here) why not learn me some F#, and kill two birds with one stone?

Lisp, CLOS and Math

What, you say, mathematicians just have to use Haskell ??

Stop right there, and read this.

Technically, there’s nothing new to see here at all. Lisp is high-level and low-level. Lisp is multi-paradigm. Lisp has uniform syntax. Blah blah blah. You’ve heard it all.

Still, some people seem to require an “argument from authority” (and usually still keep looking) … in which case you might be persuaded by this.

An extract (describing how defclass and defgeneric can be handily abused to yield whatever you like):

For example, a mathematician who installs under CLOS the traditional mathematical categories must organize his work as follows:

  • The defclass statements will be used to define what a “set” object is, what a “group” object is, what a “chain complex” object is, and so on.

  • The defgeneric statements will be used to define functions working on these objects, but these “functions” are traditionally called in this case functors in mathematics; therefore one defgeneric statement for the sum functor, another defgeneric for the classifying space functor, and so on.

  • Finally each generic function will have various methods to adapt the generic function to specific cases; for example the product of two objects of some category is also an object of this category with the corresponding structure to be defined. Therefore one product method for the sets, another product method for the magmas, another method for the monoids, and so on. The call-next-method and change-class functions will allow these methods to possibly refer to the less specific ones.

Calculating, Scheming, and Paul Graham

I came across [this paper] recently, and it challenged some of the thoughts/assumptions that had been building in my mind for a while (it discusses Scheme vs Miranda, but you can imagine Lisp vs Haskell instead).

It also mirrors a short email exchange I had with someone who I expected to be a Scheme/Lisp “champion”, but who gently led me down from my gas balloon of hype.

Yes, S-expressions are great, and one can fall in love with them, and the notion of “building material” for a language to build an application or solve a problem, but there’s no point being dogmatic about them.

Also, another tangential perspective: people consider Paul Graham a big advocate of Lisp, but in my opinion there is no one who has harmed the cause of Common Lisp more than Paul Graham.

Instead of praising the language that allowed him to build his own “killer app”, or teaching the specific details of his implementation, or his own work with the language, what did he proceed to do instead? Ask everyone to wait for his “perfect language” (i.e. stop using Common Lisp!!), and write inflated, abstract articles attracting only language lawyers and the my-language-is-longer-than-yours crowd. Sheesh.

If you want to learn Common Lisp, read The Land of Lisp or PAIP or PCL instead, or browse the sources of Hunchentoot or gendl (or some of the other well-used open-source libraries out there).

The “trinity of computation”

I never thought of it this way

Logic tells us what propositions exist (what sorts of thoughts we wish to express) and what constitutes a proof (how we can communicate our thoughts to others). Languages (in the sense of programming) tells us what types exist (what computational phenomena we wish to express) and what constitutes a program (how we can give rise to that phenomenon). Categories tell us what structures exist (what mathematical models we have to work with) and what constitutes a mapping between them (how they relate to one another). In this sense all three have ontological force; they codify what is, not how to describe what is already given to us.

In this sense they are foundational; if we suppose that they are merely descriptive, we would be left with the question of where these previously given concepts arise, leading us back again to foundations.

Memristance is futile. Not.

I came across this wired article recently, and what I read sounded too science-fiction-y to be true, so then I decided to go to the source, and found this video (see below) by a researcher at HP, and it turns out to be both true and “science-fiction-y”.

We are used to thinking in terms of standard circuit elements — resistors, capacitors, inductors. One establishes a relationship between voltage and current, the second better voltage and charge, and the third between magnetic flux and current.

Now it never occurred to me to really think about it this way (it’s one of those things that’s only obvious in hindsight), but there is a missing piece of symmetry here.

Look at that list again, and it might jump out at you that among current, voltage, charge and magnetic flux, they’re related in pairs to each other, with the exception of charge and magnetic flux. Seeing this now, it might be reasonable to speculate on another circuit element that should do precisely that. And indeed someone did, about forty years ago, and named the missing piece the memristor.

Now I should acknowledge that there is a bit of controversy whether what HP labs claims to have discovered really matches up with this idea, so we’ll just have to wait a few years to test these claims, since the first commercial applications of this technology won’t be out for another five years at least.

But let’s continue. One of the observations made in the video linked I above is that the memristance obeys an inverse square law. This means the tinier the dimensions, the greater the observed effect. Which also means this is something that would belong purely in a chip, and not something you’d be putting on a breadboard any time soon.

The most exciting property, though, is that it’s behavior in the future depends on its past. So it is both a logic component as well as a storage component. So you could build a dense cluster of these things and determine which parts do what function, in a configurable sense, much like an FPGA on steroids.

I used to think (again, only because this is what I was taught) that the fundamental logic component was a NAND gate — but this turns out not to be true. Instead, it turns out that if we consider the interaction between input A and input/output B expressed using memristors, as an IMP gate, then we can construct a NAND gate out of these.

Further, multiple layers of these memristors can be stacked above a conventional CMOS layout, and densely packed together, leading to unprecedented on-chip memory, perhaps on the order of petabits!

So, how would this change things? It would certainly deprecate the SRAM ->DRAM->Hard Drive pyramid of caches we have right now, and we would not only have an ocean of universal memory, but our processing elements would be floating on this ocean, and entirely commingled with it!

We certainly won’t need to deal with the Von Neumann bottleneck any more …

Comparative Latencies

It is usually hard to get an idea of how the time taken for various fundamental operations varies, and it does matter, but it’s hard to viscerally get it (time intervals in nanoseconds, microseconds, milliseconds aren’t really felt in the same way).

I came across this idea of representing the smallest number as a single second and everything else in terms of it, so that the relationship between the numbers is represented in more of a human scale, which results in the following table:

Op Latency Table

I wanted to show this in a chart, but it never shows more than the last two values, so I had to break it down into a series of smaller charts (I could use a log scale to represent them too, but that would’ve again lessened the impact you feel when seeing these numbers side by side)

Mostly similar, as long as it’s on the chip

 

This is a big jump!
Tremendous jump! Main memory latency is like 0.1% of the SSD access time!
… so imagine how much slower disk is, compared to RAM.
And if that was slow, you should check out the internet …
… exceeded only by an operation on the “machine”; this is finally when we can feel seconds ticking by.
Op Latency 6
Obviously, the worst thing you can do is try to restart the “real” system.

 

Summing up

I came across this post talking about numerical speed in Clojure, so I thought I would try out the equivalent in Common Lisp (Clozure CL) on my Macbook:

CL-USER> (let* ((arr-size 3000000)
        (double-arr (make-array arr-size :element-type 'single-float)))
       (dotimes (i arr-size)
         (setf (aref double-arr i) (random 1.0)))
       (time (loop for i from 0 below arr-size
            summing (aref double-arr i))))
(LOOP FOR I FROM 0 BELOW ARR-SIZE SUMMING (AREF DOUBLE-ARR I))
took 45,649 microseconds (0.045649 seconds) to run.
During that period, and with 4 available CPU cores,
     45,558 microseconds (0.045558 seconds) were spent in user mode
         57 microseconds (0.000057 seconds) were spent in system mode
1500183.5

So — 45 milliseconds, not bad.

Lispium ?

What if you did the following:

  • Take a chromebook
  • Modify the chromium build running to run Sbcl within it.
  • Create lisp bindings to the internal surface, so that all UI elements can be created and manipulated within the Lisp image.
  • Allow downloading, compiling and running arbitrary lisp code
  • One of the tabs is always a Repl
  • Add a caching filesystem that would persist part or whole of the image

… might this create a modern-day Lisp machine? Maybe.

Did I miss anything obvious here? If not, this sounds doable in a few years.

I’m lazy, do you if you like this idea (I’m sure there’s a guaranteed niche market for these machines), go ahead and throw it on to Kickstarter. Or something.