Sgeo's programming thoughts
The limit of extensible programming languages: Culture

There are a lot of programming languages, such as Lisps, that try to be extensible. They offer a philosophy of the end-programmer being able to add features that they want, features that take a while for other languages to receive, if ever. But this doesn’t necessarily work out that well. Immutable data structures can easily be added to Common Lisp, or many other languages, but it’s their pervasive use that makes them shine. For example, Clojure tries to use and encourage immutability, but whenever someone wants to work with code that doesn’t, (e.g. most Java code), there’s a mismatch, and often a wrapper will be written. Consider continuations: If not built-in to the language (or other manipulations, like Smalltalk’s thisContext), they may be hard to add to the language in a comprehensive way, even if the language offers features like macros. Observe Common Lisp’s cl-cont library: There are limitations on how the continuations it provides can be used.

There may be many features of a language which, if not pervasive, become less valuable or useful. Even though some languages may enable libraries to be written to provide such features, if one particular instance of the library doesn’t catch on, it’s still not as good as a language that has or encourages that feature from the start.

More activity

I’ve decided that I should be more willing to use the tumblr for off-the-cuff thoughts than I have been. Sorry if my next posts are less coherent.

I suspect, that, much of the time, when people say that X concept doesn’t work well, or is bad, they may only have exposure to a portion of the potential design space of X. Possibly because popular languages do X in an annoying way, or maybe the design space of X hasn’t been as thoroughly explored as it should be. Of course, X isn’t necessarily good, but just because most things do X in a certain bad way, doesn’t mean that X is bad. Two things that I suspect fit this mold: OO and static typing.

So, I’m working on a new esolang. I think it’s pretty cool, but the name I gave it uses a swear. I want to put my code for this thing on GitHub and talk about it here, but potential employers may see it. I don’t know how to deal with this, besides renaming it.

Namespaced anaphors in Clojure?

Suppose I have a macro, let’s call it aif, and within the macro I want people to be able to use the name it. Here’s how I might write such a macro in Clojure (note that this is only an example. if-let is probably a better thing to use in this particular use-case. Also note that I did not test this code).

(defmacro aif [test then else]
  `(let [~'it ~test]
    (if ~'it ~then ~else)))

This code is usable as such:

(aif (+ 2 2) (println it) (println "false"))

Within the forms provided to aif, a lexically bound variable “it” is visible. Within this post, I shall call things similar to “it” an anaphor.

Note how within the quasiquote (`) I use ~’ to prevent it from being expanded into some-namespace/it. let will only accept non-namespaced symbols, such as it, rather than a symbol such as sandbox/it or clojure.core/it, and normally, with quasiquote, bare symbols will get a namespace stuck onto them. The ~’ will prevent the namespace from being stuck on.

But suppose I have two anaphoric macros that I want to use together, that both expose an anaphor with the same name. There is no way to choose between them. It is also at times counterintuitive, if I’m exposing a function as an anaphor, that I don’t use that function the way that I would use any other function that a namespace provides.

One solution to this might be to not use anaphoric macros of this form (other anaphoric macros that do things other than provide a few names to use within their bodies are not under discussion in this post). For example, aif could be written differently, so as to accept a name. clojure.core includes such a macro, called if-let. However, as pointed out to me by amalloy on IRC, this could make some macros inconvenient to use. recur is, in a sense, an anaphor of loop.

A second solution, the one that I’m proposing, is to allow let to accept namespaced symbols. The form would still only be lexically binding, but could mean that the anaphor would be treated just like any other namespaced symbol. Suppose I’m written my aif macro in the aif namespace. So let’s say, instead of using `(let [~’it ~test] …) I used `(let [it ~test] …) or `(let [aif/it ~test]) (the latter two are equivalent). Then, users might use it as aif/it, or they may (require ‘[aif :as abc]) and then, within the macro, use abc/it. Or they may (use ‘aif), in which case they use it as before.

"Straight translations" of monads from Haskell to X

It annoys me when people try to translate the concept of monads from Haskell to their language of choice, without considering the idioms of the language receiving the translation. For example, in Haskell, variadic functions are limited and difficult, while in Clojure, they’re rather easy to deal with. There is no apply function in Haskell, but there is one in Clojure (apply essentially takes a function and a list, and calls the function, treating the list as arguments to be passed to the function). As such, there is liftM2, liftM3, etc., taking differing amounts of arguments, in Haskell. No good way to write a generalized liftMn. But in Clojure, liftMn can be written cleanly as a function. But, clojure.algo.monads does it as a macro, despite the fact that this is not necessary.

Factor’s list-monad’s return returns a list. This would seem to make sense, except Factor does not define length on lists. This can be annoying in some circumstances. It’s as though whoever was translating into Factor thought that the interesting property of the list monad is related to the view of lists as cons cells. It is not. The interesting property is the view of a bunch of items as being multiple-choice. Arrays would serve the purpose well, and do have length defined on them.

Dynamic Scoping in Factor

A problem with Factor’s dynamic scoping mechanism, pointed out by Chris Double, is that opening a new scope makes code inside that scope behave differently from if a new scope wasn’t opened. This could potentially be confusing behavior. It would be nice if with-variables and with-variable behaved in such a way that setting variables not mentioned by with-variables/with-variable behaved as though there was no new scope on the namestack.

Comments

Got comments working using Disqus. Was apprehensive because I didn’t think it would allow guests to comment, but it turns out it does if I enable the correct option.

Factor

I’ve taken an interest in the Factor programming language again. I’m not entirely sure why. I really like the environment, the code reloading that helps prevent some confusion that other languages with code reloading often face, the resumable exceptions, etc. I’m still scared of stack shuffling. And it occurs to me that I don’t see a way to, at the point of a non-resumable exception, edit the code at the surrounding point, ala Smalltalk. It looks like that could, in principle, be implemented, but I think it currently isn’t.

Also, my obsolete Linux system (Kubuntu 10.10) doesn’t like the Factor binary, so I tried to compile from source, but it needs a pre-existing Factor image, and there’s something wrong with the system that usually hosts that.

I intend to post code examples Eventually(TM)

Real Time Web Analytics