top | item 9168636

Pixie: A sweet Clojure-ish language

140 points| coding4all | 11 years ago |blog.goodstuff.im

105 comments

order

616c|11 years ago

I like the side-note.

> As a side note, expressing configurations in Clojure S-expressions makes a ton of sense. Clojure S-expressions provide a superset of JSON and Clojure's eval allows you to define a function to compute certain values. It's an escape hatch so that you're configuration files don't need to become accidentally Turing complete. The Turing complete nature of your configuration files is well defined as Clojure.

I had posted a while back wondering why more formats do not just derive from sexp or SXML (yes, say that out loud in the office). As I think some Lispers (I am even below beginner) cannot help but notice that if sexpr are coincidentally (I am sure it can be done without, but still, I am not sure if McCarthy and company just started with sexp or choose it specifically and held their ground beyond it was their choice) core to the lisp's homoiconic power-features, why more people do not just want sexp as the core data definiton, keep the data and program as close as possible, and just macro the data back, tossing back and forth between code and data as the division is limited.

Anyway, I like that far more intelligent people than me not only like this idea, but are encouraging it and pushing it forward.

(Yes, flame away. I know some people love Lisp and hate, I just thought it is an interesting premise; I am ready for you to throw shoes at me, HN.)

kyllo|11 years ago

Steve Yegge wrote a blog post about this a few years back that I found eye-opening.

The whole nasty "configuration" problem becomes incredibly more convenient in the Lisp world. No more stanza files, apache-config, .properties files, XML configuration files, Makefiles — all those lame, crappy, half-language creatures that you wish were executable, or at least loaded directly into your program without specialized processing. I know, I know — everyone raves about the power of separating your code and your data. That's because they're using languages that simply can't do a good job of representing data as code. But it's what you really want, or all the creepy half-languages wouldn't all evolve towards being Turing-complete, would they? https://sites.google.com/site/steveyegge2/the-emacs-problem

innguest|11 years ago

Tell me about it. First thing I asked when I saw HTML over a decade ago was "Oh so you can close tags out of order?" - "Uhm, no, the last opened tag must be closed first" - "Then why do I need to say its name when closing? There's no ambiguity, it's always 'close the last opened tag', so why say its name again?". Folks at W3C must not know Lisp.

threeseed|11 years ago

This seems like bit of a short sighted move not that I disagree with it.

Project Jigsaw which will be a big part of Java 9 aims to make the JVM more modular which will reduce the memory footprint substantially. Personally I would like to see a version of Clojure that targets this JVM specifically and abandons backwards compatibility.

Leaving the JVM means you abandon the decade of libraries many of which you simply can't get on any other platform (in particular for the enterprise). Given that Clojure has been gaining a lot of ground in these large companies it seems like a missed opportunity.

mateuszf|11 years ago

In fact JVM is pretty fast. If you run a simple java app without dependencies and only displaying "Hello world" it will run in about 1s on modern hardware. The problem with Clojure is AFAIR related to parsing and loading a big number of namespaces which is quite slow.

weavie|11 years ago

It can call into C libraries so there is a whole other ecosystem available to it.

john2x|11 years ago

From the README

> Although parts of the language may be very close to Clojure (they are both lisps after all), language parity is not a design goal. We will take the features from Clojure or other languages that are suitable to our needs, and feel free to reject those that aren't. Therefore this should not be considered a "Clojure Dialect", but instead a "Clojure inspired lisp".

And I agree that seeing maybe Clojure 2.0 abandon backwards compatibility with Java < 9 would be nice.

jared314|11 years ago

> This seems like bit of a short sighted move ... Leaving the JVM means you abandon the decade of libraries

Pixie is not officially connected to Clojure in any way.

The creator has been involved in Clojure's development, and is remixing parts he likes into a new language and platform. I would peg this more as a research project that the Clojure team could take some pointers from.

adamc|11 years ago

Jigsaw keeps getting moved back, to the point that I don't have much faith it will be in version 9. Wait and see, I guess.

pjmlp|11 years ago

> And the JVM has the slowest startup time of any runtime I've ever encountered.

Blame Clojure not the JVM.

https://nicholaskariniemi.github.io/2014/02/11/jvm-slow-star...

Besides if 0.04s is still too slow, there are quite a few (commercial) AOT compilers to native code available.

However, Pixie does look quite cool.

What I am missing in Clojure is the ability to take advantage of type metadata to compile it AOT to Android Dalvik/ART friendly bytecode.

Apparently not even 1.7.0 will fix the performance issues.

jeremyjh|11 years ago

.04 is user time. The elapsed time was .12 - this is how long you have to wait. Still it's a fair point: 120ms is noticeable but not painful.

masklinn|11 years ago

It's unclear what machine and JVM configuration they're using. Using the JVM 1.8 (java version "1.8.0_20") on a 2010 MBP (2.4GHz i5) I get ~190ms (180~200) for their program.

By comparison, on the same machine using an equivalent program

- Lua 5.2.3 takes 20ms

- CPython 2.7.5 takes 40~45ms

- MRI 2.0.0p481 and CPython 3.4.3 clock in at 55~60ms

- Pypy 2.5.0 takes 85~95ms

weavie|11 years ago

> There are some things that I would like to see from/in Pixie...

> Some form of package distribution support... could this be piggy-backed on Clojars?

There is Dust :

https://github.com/pixie-lang/dust

which pulls packages from Github.

kra34|11 years ago

I'm already replacing my project's ancient Go and Rust based services with Pixie powered end points!

namikaze|11 years ago

Could you elaborate some points that motivated you to switch from go? What would be next?

Gonzih|11 years ago

Language and implementation both look very promising! I was looking for small footprint and fast startup modern lisp for a long time for my embed hobby projects. And finally it's here! I'm really excited about this language and where it stands now compared to when I first discovered it.

davexunit|11 years ago

You should check out Scheme implementations like Guile and Chicken.

andrewchambers|11 years ago

I want to see a clojure clone embedded as a Go scripting language. The immutability means that the interpreter would be mostly threadsafe, and thus would support goroutines well.

lmm|11 years ago

Embedding an immutable language in a mutable one is a recipe for awkwardness - how would you expose host-language things to the inner language? Better to do it the other way around - mutable scripting language embedded inside immutable host.

bmillare|11 years ago

Can anyone verify if Pixie has concurrent multithreading or is it limited to greenthreads as described in the article? Based on the fact that atoms are implemented and they would not be necessary in a single threaded environment, I would guess that support for concurrent multithreading would be at least in the works, if not already possible.

namelezz|11 years ago

Dynamic typing and parentheses are what keep me away from Clojure or Lisp like languages. How can I get over them?

afandian|11 years ago

There aren't many languages that have radically fewer parentheses than Clojure / LISP.

Clojure:

    (defn blub-extra [a b]
        (blub (inc a) (inc b))) 
8 parens + 2 brackets

Scala:

    def blubExtra(a: Int, b: Int): Int {
       blub(inc(a), inc(b))
    }
8 parens + 2 braces

Java:

    Integer blubExtra(Integer a, Integer b) {
        return blub(inc(a), inc(b));
    }
8 parens + 2 braces

Ruby:

    def blubExtra(a, b)
        blub(inc(a), inc(b))
    end
8 parens

Python:

    def blubExtra(a, b):
        return blub(inc(a), inc(b))
8 parens, one colon

C:

    int blubExtra(int a, int b) {
        return blub(inc(a), inc(b));
    }
8 parens + 2 braces

It's roughly the same numbers of brackets (or equivalent) in Clojure, Scala, C and Java. A bit less in Python and Ruby.

59nadir|11 years ago

If you truly have been shunning Lisps because of parentheses I can only tell you that it will start to make sense once you see that they're just lists and that the fact that everything (including your code) is some variation of a list means that you are now (sometimes in the background) able to modify everything as if it was a list.

S-expressions are uniform in that they all look the same way. This means you have one form for literally everything in the program and you will have no problem parsing that form. It makes reading, mentally parsing and editing easier because everything is neatly delimited by parentheses.

In terms of readability, do you have any particular difficulties parsing the following code?

    (define (sum/recursive lst [sum 0])
      (if (null? lst)
          sum
          (sum/recursive (rest lst)
                         (+ sum (first lst)))))
We are defining a function, sum/recursive, that will take a list and return the sum of all the numbers in that list.

We use a default value of 0 for a function parameter called sum to store the sum. When the input list is empty ('(null? lst)' returns true) we return that variable. There is no return keyword, we just specify that variable and it will be returned.

If the list isn't empty, we apply sum/recursive on the rest of the list and as a second parameter we add the first number in the list to the already accumulated sum ('(+ sum (first lst))'). Using matching parens in your editor will make it obvious when you have matched the right amount of parens.

It should be noted that Racket, this Lisp variant, uses '[]' as well to delimit certain parts, for readability.

JackMorgan|11 years ago

I think Clojure is actually a lot safer by default than most people expect for a Lisp. Check out this comparison I wrote up between C#(or Java), F#, Clojure, and JavaScript on common edge case safety. http://deliberate-software.com/programming-language-safety-a...

In most ways I care about, Clojure is actually safer than C#. Now, if you're coming from an ML HM language, sure, you'll be taking a step back perhaps.

NhanH|11 years ago

I don't know where this trick come from, but I've read it a long time ago, and you might find it helpful.

Lisp languages in fact have the same(ish) amount of parentheses as any other language, the trick is that the placement slightly differ: the opening parentheses come before the function name, rather than after it. Ie foo(bar) => (foo bar) . foo(bar(baz)) => (foo (bar baz)).

threeseed|11 years ago

Time.

With Clojure/Lisp languages you are basically starting from the beginning. Most of the approaches you would take to constructing your applications don't work. It just takes a lot of practice for you to recognise patterns and then both the typing and parentheses will seem natural.

lmm|11 years ago

Compile-time typing really is valuable, IME. Maybe you should look at Shen?

(Can't help you on the brackets. I mostly stick to Scala myself)