7 ms·
Pixie: A sweet Clojure-ish language
- weavie 12y 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 https://github.com/pixie-lang/dust which pulls packages from Github.
- agumonkey 12y agoDirect link to pixie's github https://github.com/pixie-lang/pixie https://github.com/pixie-lang/pixie
- namelezz 12y agoDynamic typing and parentheses are what keep me away from Clojure or Lisp like languages. How can I get over them?
- yawnt 12y agoparentheses, at least in my exp, just fade away after a while.. there's core.typed which is static typing for clojure [0] [0] https://github.com/clojure/core.typed https://github.com/clojure/core.typed
- namelezz 12y agoThank you for the link. I will look into the core.typed.
- threeseed 12y agoAlso Prismatic's schema. It achieves some of the same goals for why you would want strong typing: https://github.com/Prismatic/schema https://github.com/Prismatic/schema
- escherize 12y ago+1 for Prismatic Schema. It's not only an awesome way to validate your maps, but it is an extremely good way to write documentation.
- minikomi 12y agoIt's also very worth looking at Typed Racket and Racket's contracts system! [1] http://docs.racket-lang.org/ts-guide/ [2] http://docs.racket-lang.org/guide/contracts.html?q=contracts
- 59nadir 12y agoIf 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.
- currywurst 12y agoLisp's super power (homoiconicity) comes at a trade-off of reduced discriminability. A good syntax highlighter and well-indented code (like you provided) reverses this effect considerably, but imho, it still takes a lot of getting used to for beginners. In any case, the bigger part of the being productive in a codebase is to figure out how it encodes the domain, what idioms and patterns are favoured etc. So sometimes, it's just not worth adding another source of aggravation for "new arrivals".
- escherize 12y agoI disagree with regard to Clojure. IME, the fact that it's a lisp doesn't seem as hard for noobs to grasp as immutability by default, or pickup up the functional programming mindset. We usually go for folks who use Emacs, so they may already have an indoctrination. When you compare Clojure to other lisps, I think you'd agree it's more discriminable, given the plethora of literals that dont use parenthesis: vectors [1 2 3] sets #{1 2 3} maps {:key "value" :name "Bryan"}
- threeseed 12y agoTime. 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 12y agoCompile-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)
- afandian 12y agoThere 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.
- bjz_ 12y agoI think it's the positioning of them that makes them stand out to people, plus the fact that they tend to bunch up at the end of things.
- afandian 12y agoOf course, I know. But most people express it as 'too many parens', without (I believe) actually thinking too hard. I was just trying to provoke a few thoughts! The position of parens is something to get used to, but then again so is Python's indentation, Scala's type system, etc etc. Every language has something unique to get used to.
- forki23 12y agoas someone already pointed out on twitter: F#: let blubExtra a b = blub (inc a) (inc b) 4 parens.
- forki23 12y agoUsually we would write it as: let blubExtra a b = inc b |> blub (inc a) which 2 parens less, but at the cost of using the (very idiomatic) pipe operator.
- gleenn 12y ago
- JackMorgan 12y agoI 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-algorithm/ 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.
- smenko 12y agoClojure is horribly unsafe. I spent a year writing Clojure and half the time we were fixing bugs where someone had wrapped a map in another map or changed the shape of a data structure. For all that's worth, I'd rather use Javascript. To add insult to injury (the amount of wasted time on something that could be easily checked by a compiler and a sane type system) there's all the bad habits you acquire and the general lack of confidence in your code, which took a good six months after that to cure. I'm sticking with types now, thank you very much...
- JackMorgan 12y agoSounds like you needed Schema, which can ensure the shape and contents of a map as :pre and :post assertions in every function you annotate, then be turned off for production use. https://github.com/Prismatic/schema https://github.com/Prismatic/schema That's why I come back to Clojure every time, if I need anything, it's available as a library. Need better typesafety? Just add in what you need with a macro or two. (Schema is not much more than that). That's not really possible easily with Javascript, and Javascript has a lot more unsafe by default edge cases than Clojure. I'm not sure why if a mostly safe dynamic language bothers you, you'd now prefer an extremely unsafe dynamic language? Lastly, types only give you a single dimension of safety, is this that exact shape, and ensuring I don't put a square peg into a round hole: both of which Schema adds in easily. Clojure is ALSO safe along many other dimensions, like thread saftey, immutably, null reference exceptions, etc.
- smenko 12y ago
- NhanH 12y agoI 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)).
- bbradley406 12y agoThis trick is very helpful, but I would argue that there are still a lot more parentheses due to almost everything being written as a function in lisp. When I started programming in Racket arithmetic and comparison expressions tripped me up frequently. My tip to beginners in this area would be to use the dot-notation first, then switch to the standard way once comfortable. for example: (20 . > . (10 . / . 5)) may be more clear than (> 20 (/ 10 5))
- threeseed 12y agoThis 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 12y agoIn 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.
- fijal 12y ago1s to print hello world is an awful lot I would like to point out.
- potatosareok 12y agoUpvoted you because I agree. JVM has many strong points but I don't think anyone is disputing that startup time is a weakness. I've used some java tools that you invoke from a command line and I'm always slightly annoyed by how slow they are. As an aside - I was trying to reduce -Xmx to improve HelloWorld startup (lol idk...) and Xmx smaller then 1024k and it couldn't start up with less then 1024k so there's that. On my windows computer (also I barely know what I'm doing so probably even timing it wrong). [Mon Mar 09 03:22:31 zebra@ZEBRA:~ ] $ time a.exe Hello, world real 0m0.098s user 0m0.015s sys 0m0.015s [Mon Mar 09 03:22:34 zebra@ZEBRA:~ ] $ time java Hello Hello, world! real 0m0.285s user 0m0.000s sys 0m0.031s
- 12y ago
- andrewchambers 12y agoI 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 12y agoEmbedding 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.
- tsmarsh 12y agoClojure is an immutable language built on top of mutable hosts. Interop is handled beautifully. A go hosted Clojure (gojure?) would probably be fine.
- lmm 12y agoCalling Clojure from Java is not remotely what I would call beautiful; it's a lot of Strings and pain (especially when you compare to calling Scala from Java). Calling Java from Clojure is substantially more elegant (it requires a structured FFI but Clojure is good at those).
- andrewchambers 12y agoI don't know if it would be an exact clojure clone, would need a few tweaks and the addition of native channels.
- nsjph 12y agoWell the closest I've found is https://github.com/zhemao/glisp https://github.com/zhemao/glisp which is similar syntactically, but doesn't have immutability.
- andrewchambers 12y agootto + clojurescript would probably work, but would lack many features + thread safety.
- pjmlp 12y 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-startup.html 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.
- masklinn 12y agoIt'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
- andrewchambers 12y agoYou are missing clojure start time which for me is over 1.5 seconds on top of the jvm start time.
- masklinn 12y agoI'm not missing anything, I'm saying the statement > And the JVM has the slowest startup time of any runtime I've ever encountered. looks completely correct in and of itself. Clojure's startup time can be blamed for making things worse (by a fairly significant bit), but the JVM is already, without Clojure, the slowest-starting runtime I have on my machine. And that's what pjmlp objected to.
- pjmlp 12y agoI get 130ms on Windows 8.1, Core Duo 2.53 GHz with jdk1.8.0_40. And 120ms If I disable the JIT. With a normal hard disk. Maybe it does take a few ms more than Lua or Python, but hardly anything significant.
- Gonzih 12y agoLanguage 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 12y agoYou should check out Scheme implementations like Guile and Chicken.
- bmillare 12y agoCan 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.
- 616c 12y agoI 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.)
- fmargaine 12y agohttps://github.com/Zirak/SEN https://github.com/Zirak/SEN
- kyllo 12y agoSteve 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 https://sites.google.com/site/steveyegge2/the-emacs-problem
- kra34 12y agoI'm already replacing my project's ancient Go and Rust based services with Pixie powered end points!
- namikaze 12y agoCould you elaborate some points that motivated you to switch from go? What would be next?
- felixgallo 12y agoThis week's hottest language is SVIRFNEBLIN. It's got everything: privilege escalators, compile-to-malgeboge, mini-hdmi, and that thing where your types are all fragments of Sapphic erotic literature!
- picks_at_nits 12y agoOh, Stefon, don’t ever change.
- gigasquid 12y agoA quick video if you want to see pixie startup time in action https://www.youtube.com/watch?v=LlDQTLRrcZI https://www.youtube.com/watch?v=LlDQTLRrcZI