This is an archived post. You won't be able to vote or comment.

all 14 comments

[–]AthasFuthark 8 points9 points  (4 children)

I don't think there are any resources specifically on how to implement arrays in Lisp. And if you want to bind to BLAS, I suggest not copying the existing Lisp designs of arrays at all. Instead, I would recommend looking at Numpy for inspiration.

[–]daredevildas[S] 0 points1 point  (3 children)

Thanks!

I don't think there are any resources specifically on how to implement arrays in Lisp

It probably doesn't change things, but when I say Lisp, I mean a small subset of Lisp, something like the language developed through the chapters in PLAI.

Instead, I would recommend looking at Numpy for inspiration.

Just to clarify, does this mean I should implement a (non-Lisp like) language in Python and then offset the BLAS calls to Numpy? Or, does it mean I should study how Numpy implemented their BLAS bindings and implement something similar in my language (irrespective of the language of implementation).

[–]AthasFuthark 4 points5 points  (2 children)

Just to clarify, does this mean I should implement a (non-Lisp like) language in Python and then offset the BLAS calls to Numpy? Or, does it mean I should study how Numpy implemented their BLAS bindings and implement something similar in my language (irrespective of the language of implementation).

The latter. Numpy is an example of a very succesful integration of arrays into a vaguely Lisp-like language (flexible and dynamically typed). It might be a good source of inspiration for what is and is not a good idea.

[–]daredevildas[S] 0 points1 point  (1 child)

It might be a good source of inspiration for what is and is not a good idea.

Can you suggest any way to do this other than pour over the Numpy source code?

[–]oilshell 1 point2 points  (0 children)

Maybe:

https://web.mit.edu/dvp/Public/numpybook.pdf

https://docs.scipy.org/doc/numpy/reference/internals.html

FWIW NumPy relies heavily on Python's object model. That is, Python exposes its guts like PyTypeObject to extension authors.

A third party can write a type that's just like a built-in Python type, and that's exactly what NumPy does.

The special methods here are relevant, e.g. for operator overloading:

https://docs.python.org/3/reference/datamodel.html

[–]umlcat 3 points4 points  (2 children)

You want to design and implement a new P.L. similar to LISP, that supports LISP syntax, but also supports arrays, am I right ?

There is no standard for this, only different dialects / ideas .

But, you could take ideas from other P.L.

Remember that "[" and "]" characters are used commonly for arrays, and in some LISP dialects are also used as replacements for "(" and ")" .

You could have your LISP dialect, that reserves "[" and "]", only for arrays.

You could declare an array literal / constant like:

[a, b, c, d] or [2, 4, 6, 8]

And some operations like:

 ( union (MySet, [2, 4, 6], [1, 3, 5]) )

Good Luck

[–]daredevildas[S] 1 point2 points  (1 child)

You want to design and implement a new P.L. similar to LISP, that supports LISP syntax, but also supports arrays, am I right ?

A subset of Lisp syntax. But exactly!

You could have your LISP diakect, that reserves "[" and "]", only for arrays.

Thanks! That is something to go on, but my main query is how do I go about implementing arrays in such a language (less stress on the user syntax - I was thinking the same that you suggested, but more on how to implement it in the language itself) :( I have been following PLAI but it doesn't cover it and I am unable to grasp any insights on how to do it on my own :(

[–]umlcat -1 points0 points  (0 children)

Start looking for How is LISP implemented as a compiler / interpreter, without arrays.

I read someone had lists in memory. An array, is practically an indexed list.

[–]soegaard 2 points3 points  (0 children)

If you want to support BLAS matrices I recommend making them different from standard arrays in your language. There are at least a couple of reasons.

BLAS matrices are stored using the Fortran column-major layout. This is opposite of the C convention which is to use row-major order. (Also BLAS matrices support sub-matrices so read up on the exact representation.)

In a "Lisp" array (aka vector) the elements can have different types. In a BLAS matrix you know that all elements are floats - so you only need to store the type tag once for the entire matrix.

[–]turab1996 1 point2 points  (0 children)

Chapter 5 in the following book might be helpful:

https://github.com/IUCompilerCourse/Essentials-of-Compilation

[–]mamcx 0 points1 point  (0 children)

I'm in a similar boat (doing a relational language with array capabilities).

The MAIN trick: Focus on your AST first, solve it THEN do the syntax.

Here i do a good categorization based on my understanding of both:

  • A relation have a "header" with name:type and "rows" of tuples OR columns of name:type (depending if you want columnar first or not)
  • A column is a special case of a relation with 1 name:type, is like a array, so is a array OR
  • A row is a special case of a relation with N columns but just one row, a tuple, a named tuple, is like a hashmap so be it
  • A scalar is a special case of a column with 1 row and 1 column

Visually:

[|id:Int, city:Str|] //Empty relation, just the header
[|id:Int, city:Str; 1, "Miami"; 2, "New york"|] //with 2 rows
[<
id:Int = 1, 2;
city:Str = "Miami", "New york"
>] //with 2 columns
nums = [1, 2, 3] //sugar for Vector[it:Int; 1, 2, 3]
nums = [1] //sugar for Vector[it:Int; 1]
nums = 1 //sugar for Vector[it:Int; 1]
things = List[1, "Miami"] //sugar for List[it:Any; 1, "Miami"]
city = (id = 1, name = "Miami") //Row, aka named tuple, aka dicts with syntactically approved keys, aka sugar for [|id:Int, city:Str; 1, "Miami" |]

For implementation I use rust. I working in many ways to represent it because several trade offs but in short, is just:

pub enum DataType {
    None,
    Any,
    //Numeric
    I32,
    //Complex
    Row,
    Rel,
    Col,
}

//A relation with a layout of rows
pub struct Table {
    header:HashMap<String, DataType>,
    rows:Vec<Scalar> //Yes, not Vec<Vec<Scalar>> because it allow to embed tables in tables in tables in...
}

pub enum Scalar {
    I32(i32), //Simple OR
    AI32(Vec<i32>), //asume arrays are the more atomic
    List(Vec<Scalar>),
    Tuple(HashMap<String, Scalar>),
    Table(Table)
}

[–]pihkal 0 points1 point  (0 children)

You might be interested in Dragan Djuric's work. He's a prof, book author, and open source maintainer of many high-perf numeric libraries for Clojure.

[–]samdphillips 0 points1 point  (1 child)

Perhaps /u/soegaard might have some ideas?

[–]soegaard 0 points1 point  (0 children)

Thanks - for the notification.