Live data from Hacker News

Pixie – A small, fast, native Lisp

pixielang.org

111–120 of 164 posts

Re: Pixie – A small, fast, native Lisp

#111
post #27

> And it's small. Currently the interpreter, JIT, GC, and stdlib clock in at about 10.3MB once compiled down to an executable. Oh how the definition of "small" has changed. I actually would like to know how they managed to make something like this so big . To compare, LuaJIT is about 400 KB, and that includes the Lua standard library, a JIT almost certainly more advanced than Pixie's current one, an incremental GC, a…

10.3MB definitely is not small. I was expecting couple hundreds of K, or 1M.

Re: Pixie – A small, fast, native Lisp

#112
post #62

Earlier quoted context omitted.

SBCL does not create binaries per se, but dumps the program image. While it practically is a binary, it's not equal to an executable that a conventional compiler/linker produces.

I wonder why tree shaking is so ineffective. Is that because any symbol could be accessed dynamically at runtime?

eval is the root of all evil. String to symbol lets you introduce anything.

Re: Pixie – A small, fast, native Lisp

#114
post #112

Earlier quoted context omitted.

I wonder why tree shaking is so ineffective. Is that because any symbol could be accessed dynamically at runtime?

eval is the root of all evil. String to symbol lets you introduce anything.

In lisp eval does not take a string as its input, but a form, i.e. a linked list, containing the program to execute. Maybe you confuse it with JavaScript or Python eval (or the like) where the function both reads in a string and runs the program it parsed from that string. There are diverse functions to convert a string to a symbol in different lisps.

Re: Pixie – A small, fast, native Lisp

#115

Earlier quoted context omitted.

> But there are also interpreted interpreters aren't there? I mean, not in use.... What would be the point? Every other interpreter worth using is AOT compiled, it's hardly something to boast about. One exception might be JRuby, I suppose. Kind of a strange comparison to go out of your way to disabuse.

Not strange at all. The main language inspiring pixie is clojure, whose interpreter runs on the JVM. I might even go so far as to say that the main reason to use pixie is because you want to write clojure but can't afford to use a JVM for the task at hand

If we're going by the traditional idea of "bytecode interpreter" or "threaded interpreter", clojure is emphatically not one of them. It JIT compiles the lisp to JVM bytecode; the equivalent in Pixie would be JIT compiling to native code.

IIRC with RPython/pypy the two techniques are interleaved, but most users I've seen opt for some JIT optimization.

Re: Pixie – A small, fast, native Lisp

#116
post #114
post #112

Earlier quoted context omitted.

eval is the root of all evil. String to symbol lets you introduce anything.

In lisp eval does not take a string as its input, but a form , i.e. a linked list, containing the program to execute. Maybe you confuse it with JavaScript or Python eval (or the like) where the function both reads in a string and runs the program it parsed from that string. There are diverse functions to convert a string to a symbol in different lisps.

Perhaps i'm rusty.

in this case

    (funcall #'+ 1 2 3)
or the more scheme-ish

    (apply '+ '(1 2 3))
i think the symbol plus gets evaluated to # and then is called with 1 2 3 - CL will do apply, of course, not sure about scheme and funcall. I'm totally willing to accept my mental model is wrong, i don't have an interpreter handy.

So if that's true, you run into this problem:

    (funcall (string->symbol "+") 1 2 3)
    (apply (string->symbol "+") '(1 2 3))
maybe string->symbol does not introduce in to the function namespace, but i bet there's a way or a flag to do it.

so anyway, at the end, you run into this problem:

    (funcall (string->symbol "any-random-function") 1 2 3)
    (apply (string->symbol "any-random-function") '(1 2 3))
this makes tree shaking hard.

you could, of course, look for the handful of ways to bind symbols to functions, maybe do constant folding and include a minimal set if the compiler can prove what's actually needed.

but in general i think tree shaking is hard when you can load things like that dynamically.

Re: Pixie – A small, fast, native Lisp

#117
post #92

I'm the original author of pixie, and yeah, I'm a bit surprised to see this hit HN today. It should be mentioned that I put about a year of work into this language, and then moved on about a year or so ago. One of the biggest reasons for my doing so is that I accomplished what I was looking for: a fast lisp that favored immutability and was built on the RPython toolchain (same as PyPy). But in the end the lack of sup…

As a somewhat different data point, we've been developing pycket, an implementation of Racket on top of rpython, for the past 3 years, and while it faces many of the same challenges, we've been very happy with the results. The JIT can remove almost all of the intermediate data structures caused by the functional nature of the language, and we support tail calls and first class continuations. Overall, pycket is almost…

Yes! Pycket is a great language, I used your paper as a reference more than once while working on Pixie.

Re: Pixie – A small, fast, native Lisp

#119
post #61

Earlier quoted context omitted.

> Clojure vectors are nice for the performance they give. What difference does it make when representing code?

Vectors eval to themselves, while lists eval to a function/macro/special-form call. Vectors also differ from lists in that they are ordered and indexed, so in macros and special forms they tend to be used to represent positional bindings.

This has nothing to do with performance. Also, there is no such clear distinction in how vectors and lists are used. You still require context to know if a vector is evaluated to itself or not, or if a list is a call. Without context, you can't say looking at [x y] which of x or/and y is being evaluated:

    (let [a [x y]] ...)
    (let [x y] ...)
    (fn [x y] ...) 
As for parenthesis, you have special cases too:

    (defn foo ([] (foo 0)) ([n] ...))

And sometimes, people aren't sure about what to use: https://github.com/bbatsov/clojure-style-guide/issues/64

Re: Pixie – A small, fast, native Lisp

#120
post #25

Earlier quoted context omitted.

A big one is persistent data structures. Where 'persistent' may not mean what you think it means. In Clojure it is impossible to surgically modify a data structure. That is, you can't do something like: (SETF (CAR (CDR x)) 'foo) which would alter a data structure. You can modify a data structure, but it returns a new data structure, yet the old one remains if it is not GC'able. All of the common data structures have…

How is the cost of copying close to zero or not apparent?

The data structures in Clojure are built on shallow 32-way trees. When you "change" a map or a vector, the algorithm only copies from the root node down to the parent of the leaf you're changing. That's log32(N) copied nodes in a tree of N nodes total.
Post reply on HN