10 ms·
Carp, a compiled Lisp with type inference and a borrow checker
- michaelmior 9y ago> Carp compiles to C...It also likely doesn’t matter much, because chances are your machine has a C compiler. Whether or not I can compile the code is only one of the many concerns to consider when picking between C and LLVM.
- hellerve 9y agoThat’s quite true, but from the users perspective, it mostly doesn’t matter, at least in my mind. For people interested in the internals—which is an increasing amount of the user base—, and the people working on the compiler, it most definitely is a concern.
- michaelmior 9y agoOne place I can see this being an issue for users is debugging. I haven't tried Carp so I don't know how much of a practical issue this is. But if what is actually being compiled is a C program, how do I tie issues in the compiled C program all the way back to my source in Carp?
- slowmovintarget 9y agoClojure + Rust => Carp?
- afghanPower 9y agoMy first thought as well.
- chubot 9y agoIt sounds like arrays are mutable in Carp, so it doesn't feel like Clojure to me. As far as I understand, Clojure is also not big on macros, while Carp appears to be.
- slowmovintarget 9y agoAye, that's the one big disappointment. Maybe the first pet project is an implementation of Clojure's immutable collections.
- Rusky 9y agoImmutable collections don't play well with non-GC memory management.
- dgreensp 9y agoExactly. Someone who doesn’t see the value in a GC-less language is not going to see the value here. I personally think “functional persistent” data structures, as a language default, trade a lot of runtime performance in order to achieve some guarantees like thread-safety and functions not having side effects. Every mutation to every array or dictionary is treated like a transaction in a MVCC database, with the garbage collector in charge of cleaning up the records of every past version that wasn’t actually necessary to keep around, because no multiversion concurrency was actually necessary in that case. I encourage languages to experiment with other methods of achieving similar benefits. I think limiting side effects and shared mutable state is very important, but at a local level, imperative code that mutates a data structure is highly readable and performant. Certain algorithms practically require it. Certain hardware practically requires it. Functional languages let you think in terms of abstract “compound values,” but in practice these are backed by tons of little heap-allocated objects, partly so that lots of sharing can be done when the data structure is copied on every change.
- chubot 9y agoI'm guessing it wouldn't be the same language then. Most languages are pretty tied to their own dataa structures, and that's especially true of Lisps because code is data. After all, Clojure is not Scheme. You might be looking for C++ :-P As I mention here, it is impressive that you can actually implement these structures are libraries. https://www.reddit.com/r/ProgrammingLanguages/comments/7cdz5u/immer_clojurelike_persistent_data_structures_in_c/ https://www.reddit.com/r/ProgrammingLanguages/comments/7cdz5...
- partycoder 9y agoFrom their github (https://github.com/carp-lang/Carp https://github.com/carp-lang/Carp) The key features of Carp are the following: - Automatic and deterministic memory management (no garbage collector or VM) - Inferred static types for great speed and reliability - Ownership tracking enables a functional programming style while still using mutation of cache friendly data structures under the hood - No hidden performance penalties – allocation and copying is explicit - Straight-forward integration with existing C code
- dkersten 9y agoThis actually sounds like exactly what I’ve been wanting! I use Clojure and it’s great, but I’ve been wanting to use something to interop with some C++ code but while I like C++ more than most, I’d rather write in Clojure (or something like it). Awesome!
- zitterbewegung 9y agoAdd an interface to Caffe or Torch and this could be even cooler. I wanna try this out. Looks like a better prescheme from s48.org
- rad_gruchalski 9y agoLooks really good. Might give it a shot. What's the concurrency story?
- hellerve 9y agoNone at the moment, to my knowledge. High on the list of priorities, but it’s not far enough along, I fear.
- arximboldi 9y agoI really want to like Carp but I somehow feel that the Rusty memory model does not fit the Lisp philosophy... all the borrowing story comes from a basis mutability. I wish for something more Clojurish based on immutable data. Then one can exploit the power of inferred type linearity/affinity to transparently build safe "transients" and other cool stuff. Maybe some day I should write such Lisp myself on top of my C++ immutable data structures [1] :-) [1] https://github.com/arximboldi/immer https://github.com/arximboldi/immer
- zitterbewegung 9y agoThat’s one of its strengths though . A lisp with type inference and performance is quite rare. More lisps should be less lispy .
- shakna 9y ago> A lisp with type inference and performance is quite rare. You mean apart from several Scheme implementations? Chez Scheme is blisteringly fast, and on-par with C for quite a few things. Gambit-C (Compiles to C), Chicken (based on the Cheney-on-the-MTA model) and Bigloo (designed to replace C++) also deserve a reference here.
- baldfat 9y agoRacket which is moving to a Chez Scheme top and you can further go with typed Racket seems to fit that 'rare' category.
- metaobject 9y agoBigloo has a special place in my heart. I spent a few years building scheme bindings to various C graphics and networking libraries. I can't quite put my finger on it, but I found it very enjoyable. Getting C-like performance from scheme is just wonderful.
- white-flame 9y ago> A lisp with type inference and performance is quite rare. That's quite a befuddling thing to say, in every aspect. The popular SBCL is likely the fastest general Lisp out there (gets close to or equal to C when declared properly), and type inference is certainly part of those speed wins.
- sillysaurus3 9y agoI've been waiting for a non-Clojure lisp to make some headway. Immutability is mostly a fad: look at how incredibly complicated Clojure's implementation is. It's not worth sacrificing elegance just to attract the true believers.
- macintux 9y agoHonest question: is immutability complicated in Clojure because it's hard, or because it's running in a virtual machine with no meaningful support for it? The Erlang VM has immutability deeply baked in, and it just works(™).
- sillysaurus3 9y agoIt's hard. http://hypirion.com/musings/understanding-persistent-vector-pt-1 http://hypirion.com/musings/understanding-persistent-vector-...
- banachtarski 9y agoI would argue the immutability is actually not a great thing in Erlang to be honest. It makes it hard to reason about what gets copied, what gets shared in the global heap which may be a source of contention, makes code unnecessarily verbose, etc. I think it's one of those features (like lazy evaluation in Haskell) that language practitioners tend to advocate without necessarily understanding what tradeoffs they are making in the process.
- ams6110 9y agoIt actually makes reasoning easy. What gets copied: everything. What gets shared: nothing.
- im_down_w_otp 9y agoExcept that isn't true in Erlang (or other BEAM languages). Binaries larger than some threshold are managed on a shared-heap. I think a couple other things have been promoted to being managed that way too fairly recently.
- thomastjeffery 9y agoSince this is about a pre-alpha language, it would be helpful for future web searchers to have a date in the title.
- mark_l_watson 9y agoSorry to be a little off topic but I think search engines should penalize material that is not clearly marked with date of creation.
- Animats 9y agoThe cool kids only give a month and year, because what they have to say will be gone or irrelevant in a year.
- macintux 9y agoI've seen academic papers with no date and it drives me crazy. I'm sure there's some reason for it related to the publication process but can be hard to vet a paper without knowing more about the context in which it was written.
- hellerve 9y agoThat’s probably true. I honestly didn’t expect this little blog post to gain that much attention, honestly.
- hellerve 9y agoComments like these are the reason why I need an editor.
- jstewartmobile 9y agoSo, Chicken Scheme[0] with a borrow checker? [0] https://www.call-cc.org https://www.call-cc.org
- bjoli 9y agoBut without dynamic typing and Cheney on the MTA and with a completely different way of managing memory. And not a scheme.
- jstewartmobile 9y agoScheme is a lisp, and I'm pretty confident that two of the biggest selling points of lisp are dynamic typing and a strong distaste for (if not an outright prohibition of) mutation. Put it as a question because if you take those two things away, wouldn't it just be Rust with parenthesis?
- steinuil 9y agoThe selling point of lisp is macros, and macros alone. Different dialects will have different characteristics: Common Lisp is dynamically typed and usually makes heavy use of mutation, others like Lux are purely functional and statically typed. > wouldn't it just be Rust with parenthesis? That's pretty much what it is.
- metaobject 9y ago> The selling point of lisp is macros, and macros alone. That's a fairly bold claim.
- jstewartmobile 9y agoYes, but will macros retain their power in a statically typed environment?
- bjoli 9y agoThey work OK in typed racket, but you will have to help the type checker a bit for the more complex macros. And they provide utility that the type system doesn't. The for style loops are extremely useful
- ameliaquining 9y agoHow does dynamic memory work in this language?
- Veedrac 9y agoIt seemed they don't distinguish between mutable and immutable references (?). Does Carp not handle the issue of shared mutability, eg. iterator invalidation, like Rust?
- eriksvedang 9y agoCorrect, not at the moment. Overall the type system is less expressive but also less dependent on annotations. Differentiating between immutable and mutable refs is probably coming though, it’s a useful distinction for sure.
- chombier 9y agoIs there a documentation about the type system somewhere?
- mratzloff 9y agoI realize that almost every language could be described as a subset of C++, but I read articles like this and think... Deterministic language that has type inference, C interop, and uses ownership to govern object lifetimes? We have that. It's C++11. auto with std::unique_ptr and std::move(). Only slightly serious. ;-)
- sitkack 9y agoSo Carp could compile to that subset of C++. But C++11 isn't _just_ that. It is all of C++11. C++ would even more successful if it was easy to make a proper subset of it.
- geokon 9y agoThat's what the GSL was supposed to be https://github.com/Microsoft/GSL https://github.com/Microsoft/GSL It seemed really cool. All compile time checks. I have no idea why it didn't take off
- pjmlp 9y agoSure it did. Some of the new C++17 library updates come from there, and both clang and VC++ implement those static checks.
- geokon 9y agoI've only have a pretty basic understanding of how it works, but I thought the checks didn't rely on the compiler. They're special templates that fail when their conditions aren't met And when I say it didn't take off - I mean that I haven't come across a single large project that has take up using the GSL. Hope I'm wrong - maybe I just haven't looked in the right place?
- pjmlp 9y agoNo, GSL is a kind of stop-gap solution, until standard catches on. For example std::string_view and ongoing design on std::array_view are based on gsl::span. The gsl::byte is also no longer needed on C++17 thanks to std::byte as yet another example. The GSL asserts are there until code contracts[0] get into the standard. The magical types like gsl::owner allow clang-tidy and VC++ checkers to apply a Rust-like memory tracking usage. Kate Gregory did a presentation at CppCon 2017. "10 Core Guidelines You Need to Start Using Now" https://www.youtube.com/watch?v=XkDEzfpdcSg https://www.youtube.com/watch?v=XkDEzfpdcSg As for not taking off, being initially a Microsoft proposal, it is surely used by Office and Windows teams, specially given they already use SDL (Security Definition Language) macros as well. [0] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0542r0.html http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p054...
- yawaramin 9y agoVery excited about Carp. In general I like the simplicity of Lisp but ironically I'm not a fan of dynamic typing. Carp may be a real innovation. A bit surprised though that the Carp C runtime functions are not namespaced. With names like `IO_println` there's a risk of clashes. Unless the compiler is doing some tricks to hide names?
- eriksvedang 9y agoThe ”IO_” part is the namespace, so no clashes!
- yawaramin 9y agoIt's not enough :-) Ask the OCaml folks, they're going through this pain right now because their stdlib modules are called `Array`, `List`, and so on. They're planning to put them all under `Stdlib`, so e.g. `Stdlib.Array` and so on, but it's going to be a big effort with a lot of pain. The main problem will arise when users create their own libraries; suppose some people create a `Option` libraries and then later you want to add a standard option type to Carp, it will be painful. Better to namespace your stuff under `Carp` from the beginning, so e.g. `Carp_IO_println`, `Carp_Option_map`, and so on.
- eriksvedang 9y agoOK, I see what you mean now. Thanks for the feedback, I'll make sure to think about this more before stabilising the modules.
- vog 9y agoI wonder how this compares to the Python ecosystem, whose standard library is also quite large. (Anyone remembers their famous "batteries-included" mantra?) Python 2 didn't have a stdlib namespace, or "package" in Python speak. But when they created their clean-slate approach with Python 3, they also decided not to introduce a stdlib package. External Python packages just avoid the stdlib package names, and everything seems fine. So, is there something in the Python language that makes the missing? Or is it just the Python community which doesn't care about (or plays down) this issue?
- mhd 9y agoAs a Perl programmer, that name confuses me slightly.
- senorsmile 9y ago## confusing indeed ... || croak "Wrong language!";
- sitkack 9y agoOthers might be interested in Henry Baker's Lively Linear Lisp [0] HN Discussion. https://news.ycombinator.com/item?id=14248419 https://news.ycombinator.com/item?id=14248419 [1] http://home.pipeline.com/~hbaker1/LinearLisp.html http://home.pipeline.com/~hbaker1/LinearLisp.html
- agumonkey 9y agoLoved that article, made me realize a lot of things about ... lots of things.
- sitkack 9y agoThat bibliography is amazing. The best papers also have great bibliographies where I can dive in and learn mind altering ideas. Boring papers have boring bibliographies that just echo a list of the big papers in a field.
- catnaroek 9y agoThe borrow checker is the reason to use Rust, in spite of its annoyances (clunky syntax, limited type inference, non-interactive programming, long compilation times, etc.), so it's always nice to see someone trying to provide the upsides of Rust without the downsides. That being said, your website is disappointingly terse regarding how Carp recovers the advantages of Rust in the context of a Lisp derivative. What makes this particularly suspicious is the fact that, in the past, Lisp programmers have claimed to recover the advantages of other statically typed languages in a Lisp setting, but there have always been huge caveats, like “the system can be very easily circumvented, reducing the benefits of static typing to nothing”. The main reason why I feel confident that Rust is a safe language isn't just the fact that rustc seems to catch many bugs in practice. That alone wouldn't distinguish it from the countless static analysis tools for C and C++ that have existed for decades. The main reason why, at least in my opinion, Rust is such a trustworthy language in spite of its ginormous complexity, is the fact that its core developers, in particular Niko Matsakis, do a terrific job of communicating the process by which Rust's features are conceived and designed. When you read Matsakis' blog [0], it becomes patently clear that Rust's developers take into account the kind of corner cases that in many other languages are only discovered months or years after the feature has been implemented [1][2]. Other languages that inspire similar confidence in me are: (0) Standard ML. It has a formal proof of type safety. (1) Pony. It has a formal proof of type safety. (2) Haskell, as specified in the Haskell Report (i.e., without the crazy GHC-specific language extensions), because its type system is similar to Standard ML's, and there are no reasons to believe the differences introduce any type safety holes. (3) OCaml, again without the crazy extensions (GADTs, first-class modules, etc.), for more or less the same reasons as Haskell. Links: [0] http://smallcultfollowing.com/babysteps/ http://smallcultfollowing.com/babysteps/ [1] http://joyoftypes.blogspot.pe/2012/08/generalizednewtypederiving-is.html http://joyoftypes.blogspot.pe/2012/08/generalizednewtypederi... [2] http://io.livecode.ch/learn/namin/unsound http://io.livecode.ch/learn/namin/unsound
- eadmund 9y ago> in the past, Lisp programmers have claimed to recover the advantages of other statically typed languages in a Lisp setting, but there have always been huge caveats, like “the system can be very easily circumvented, reducing the benefits of static typing to nothing”. It seems to me that the benefits of static typing only apply to accidental mistakes (e.g. using a pointer to a character as though it were an integer, or a pointer to a struct, or whatever), and thus that a system with deliberately-circumventable static typing is just fine.
- swlkr 9y agoThis project looks really good. I would love to have a clojure inspired lisp that's fast and doesn't require the JVM.
- sitkack 9y agoYou might try Avian or Multi-OS Engine for embedding a JVM within your program. [0] https://github.com/ReadyTalk/avian https://github.com/ReadyTalk/avian [1] https://software.intel.com/en-us/multi-os-engine https://software.intel.com/en-us/multi-os-engine
- pjmlp 9y agoOr even one of the commercial JDKs with AOT native code compiler.
- deleted 9y ago[deleted]
- igt0 9y agoI wonder why nobody said one word about Shen Language[1]. [1] http://www.shenlanguage.org/ http://www.shenlanguage.org/
- bogomipz 9y agoI'm curious about the borrow checker, is this Rust invention or did a similar concept exist elsewhere in some other language(s)? Can anyone recommend any resources specifically on the idea of the borrow checker?
- steveklabnik 9y agohttps://forge.rust-lang.org/bibliography.html https://forge.rust-lang.org/bibliography.html has links to previous work we built upon.
- nimmer 9y agoNim https://nim-lang.org https://nim-lang.org is programmable as well, more mature, and multiple memory management models are coming out.
- CyberDildonics 9y agoWhen you say 'mature' has the compiler stopped crashing all the time?
- weberc2 9y agoDoes Carp support ADTs or pattern matching? I couldn't see anything in the documentation.
- greatNespresso 9y agoI find it really interesting, and I would definitely like to try it out (the article is great by the way) I am not that good at C or Haskell, so that would be a great way to improve on this too, and that would be my main objective actually. So noob question : how would I go adding some C networking libs to Carp ? Should I directly call the code from Carp (and is that possible at the time) or should I embed it in the language core and go the haskell route ? I am new to this but would really love to embark into the adventure, for learning purpose.