1. 2

Look at K and Mathematica (aka Wolfram) for two languages that integrate the ideas from APL and Lisp in a more interesting way. In these languages, multidimensional arrays are represented by nested lists, and all scalar operations are generalized to operate on lists. This is a powerful idea whose benefits go well beyond the linear algebra implemented by LispE.

The idea is most powerful if you have only one kind of list (like in K). So a character string is just a list of characters. A matrix is a list of lists of numbers. Instead of representing bit strings as integers (as LispE does with the bitwise operators), a bit string is a list of booleans. All of your scalar operations (on numbers, booleans, and characters) are generalized to work on lists.

1. 1

Do you have any good resources for learning K? I have a few bookmarked here but in everything I’ve found there seems to be a lack of practical exercises/projects so I end up forgetting everything I read.

1. 1

I’m not sure if any of my resources are “good”. Another problem is that there are many dialects of K.

1. 1

Thanks. The last one is the one I’m trying to follow this time.

2. 1

K crash course was good. It refers to k7, which is no longer current, though it can still be run via web.

Q for mortals is decent, though very slow.

1. 1

I believe this is the same as https://github.com/kparc/kcc

1. 1

Latter is incomplete, in the process of being updated to k9.

1. 1

Oh, good to know.

3. 1

LispE operates on tensors, which are implemented as nested lists.

1. 2

Tensors do not an apl make. Tensors, a concise notation, a rank operator…

In apl, everything is an array, and functions operate homogenously on the same. Power emerges from that.

In lisp, everything is an atom or a pair of things, and functions operate homogenously on the same. Power emerges from that, too.

Newer lisps add things like arrays, but an array is little more than a concession to performance; its role is similar to that of the cons: a container for other objects. Lisp’s language is abstraction, and it speaks it well.

When you try to blend the two, you end up with something that is neither a very good lisp nor a very good apl. (It may be good at being something else. I do not mean to make a value judgement.) Tensors feel more scalar than lisp’s aggregates and more aggregate than lisp’s scalars, and the homogeneity of each language is lost.

1. 1

Actually, you should have a look on how lists are implemented in LispE (see https://github.com/naver/lispe/blob/master/include/listes.h). They are implemented as arrays, not as lists. I worked with many versions of Lisp over the years, and I had an issue with the idea of pushing elements at the beginning of the list, which is usually quite unnatural in most languages. I opted instead to a different implementation which is composed of two layers: ITEM (the array implementation) and LISTE, which contains a pointer to an ITEM. LISTE also contains an index to the first element in the array. A CDR for instance, creates a LISTE object that shares the same ITEM with the initial list, but move its index one notch over.

1. 1

I don’t see why something’s being unnatural in one language should have any bearing on that thing’s role in another language.

Which being said, you can push elements to the end of a list, by keeping a pointer to the final cons. Another pattern which is very common is to add elements to the head of a list and reverse it once done.

That’s all mostly beside the point, though; again, the semantic role of arrays in lisp is almost identical to that of conses in this context.

1. 1

You may be interested in gamelisp for a different take on how to do a “lisp” with a vector rather than cons cells.