A first look at newLISP

» Cool Lisp dialect, but what's with the dynamic scoping?

Lisp has always intrigued me. I have been looking at it, on and off, for years. Yet it somehow never seemed a natural fit for me, personally. I'm not good with deeply nested expressions. Aside from that, there are so many Lisp dialects and implementations that it's hard to choose. Common Lisp is standardized and has many features, yet lacks a comprehensive standard library and has a user community that is generally perceived as, shall we say, less than friendly. Scheme, OTOH, is clean and much smaller, but rarely seems to be used outside of academia. Other dialects are obscure (Goo) or look suspiciously like vaporware (Arc). (Yes, yes, I am probably misrepresenting these languages; feel free to disagree. In any case, these are my impressions.)

So, when I saw newLISP, it seemed like a reasonable alternative. Unlike most other Lisps, it comes with "batteries included", and is used for practical purposes. It's small, fast, supports graphics, has installers for many platforms, and supports a number of libraries that we've come to expect in other languages: regular expressions, XML handling, networking, multiprocessing, etc. It has an interactive shell (naturally) which can double as a telnet or web server. What's not to like?

Well... it turns out that there are a few things that turn me off. :-( Dynamic scoping, for example. The manual claims that you can get around this using "contexts" (namespaces); I haven't tried this yet. Still, this example (from the manual) somehow disturbs me greatly:

> (define (add-three-nums x y z) (print-vars) (+ x y z))
(lambda (x y z) (print-vars) (+ x y z))
> (define (print-vars) (print "X=" x " Y=" y " Z= " z "\n"))
(lambda () (print "X=" x " Y=" y " Z= " z "\n"))
> (set 'x 4)
4
> (set 'y 5)
5
> (set 'z 6)
6
> (print-vars)
X=4 Y=5 Z=6
6
> (add-three-nums 70 80 90)
X=70 Y=80 Z=90
240
> (print-vars)
X=4 Y=5 Z=6
6

I think what bothers me is that this kind of scoping requires me to think about variable lookup rules in a whole new way. I don't think I've ever used a (non-toy) programming language that uses this scoping rule by default.

Another thing I don't like is the so-called "implicit indexing". It works like this. Say you have a list (or array); then (mylist N) returns the N-th item in that list. For example:

> (set 'names '(guido larry matz lutz bill))
(guido larry matz lutz bill)
> (names 1)
larry

More bizarrely, (N mylist) is used for slicing:

> (2 names)
(matz lutz bill)

This corresponds to Python's mylist[N] and mylist[N:]... but why the special syntax is used, is beyond me. You don't have to use it... for the examples above, you can use (nth 1 names) and (slice names 2) instead. But I'm used to the fact that function application is fairly straightforward in Lisp (or at least in Scheme)... these constructs seem to break that.

Anyway... the syntactic sugar is no big deal, but the dynamic scoping makes me rather wary. I wonder what the rationale is behind this decision, considering that CL and Scheme use lexical scoping.