Looks like just what I have been trying to find, since I am incapable of writing my own. I did start with 'Learn C * Build Your Own Lisp' book [1], and I will finish it for educational purposes; it is a great, short book to work through, and should help with grokking Carp. The closest I have come to finding something similar for livecoding visuals and audio, or games is Extempore [2], which has xtlang, a Scheme, with…
Carp: a statically typed lisp, without a GC, for high performance applications
61–70 of 71 posts
Re: Carp: a statically typed lisp, without a GC, for high performance applications
#62I saw this a month or two ago and submitted a pull request that I still need to fix up to have it accepted. My original intention was to benchmark a bit against SBCL, but I got sidetracked with the pull request, then lost time and then forgot about it. I need to get back to it and see about getting it submitted. Anyway, it sounds neat, but even after playing with it a bit, I'm not sure how necessary it is. SBCL (and…
Re: Carp: a statically typed lisp, without a GC, for high performance applications
#63Earlier quoted context omitted.
Very simple. Each C allocated structure is allocated at the end of its C scope, and free'd at each end. Since the compiler knows the scope of each variable it's trivial. Harder is of course the ffi, which doesn't generally know if the extern call allocated something. This is undecidable for the compiler and he has to trust the user/program. Other lisps have an attribute for those externally malloc'd args.
No, really no. First of all the values of the variables can escape their scope, e.g. when used as a return value. Secondly, some child scopes outlive their parents, e.g. closures. As the parent comment correctly points out you'd literally need to solve the halting problem to infer all the lifetimes for arbitrary code.
you only need a GC to recycle cyclic data structures, with links back to previous nodes. since Carp does not create such data structures in the generated C code the reclamation scheme can be kept simple.
heap vars to be kept global (such as closed-over upvals you are complaining about to be leaking) are kept global and released at the end. every dynamic language does keep it functions and closed over values global.
however, lexical closures are released at the end of scope, and remaining tracked heap vars are copied.
Re: Carp: a statically typed lisp, without a GC, for high performance applications
#64This is fantastic. AFAIK there are no Lisps our there that are designed with games in mind which is a huge shame because I often think how perfect it'd be for game dev (Arcadia and Nightmod spring to mind but imo they're shoehorns. Good ones, but still).
There are a couple of high-performance, low-latency lisps, either with a low-latency GC or refcounted or compiling to C as Carp does. ECL (also typed), Vicare, Larceny, Ypsilon, the new guile, Gambit-C, Chicken, Chez, Bigloo, stalin, Corman CL, or fast typed CL: sbcl, franz, lispworks and few more. Or the ones compiling to LLVM or JVM or .NET. Most prominent Clojure with a very unlispy syntax.
Of course libgc is pretty simple and slow, good for foreign code (i.e. ffi's needed in games), slower than Cheney-2 finger copying allocators which I got down to 10ms, compared to 100-300ms for mark-sweep. But copying collectors need 2x memory, so not usable for small devices such as phones. And a bit complicated for foreign memory, which prefers conservative mark & sweep.
Re: Carp: a statically typed lisp, without a GC, for high performance applications
#65Looks like just what I have been trying to find, since I am incapable of writing my own. I did start with 'Learn C * Build Your Own Lisp' book [1], and I will finish it for educational purposes; it is a great, short book to work through, and should help with grokking Carp. The closest I have come to finding something similar for livecoding visuals and audio, or games is Extempore [2], which has xtlang, a Scheme, with…
You should have a look at Hypergiant library for Chicken Scheme. It compiles to C as well. https://github.com/AlexCharlton/Hypergiant
I've also looked at Lobster, which is now statically typed by default, not optional.
Re: Carp: a statically typed lisp, without a GC, for high performance applications
#66Earlier quoted context omitted.
No, really no. First of all the values of the variables can escape their scope, e.g. when used as a return value. Secondly, some child scopes outlive their parents, e.g. closures. As the parent comment correctly points out you'd literally need to solve the halting problem to infer all the lifetimes for arbitrary code.
tracking the scope of vars is a simple compiler job (yes, also across functions, when used as byval or byref args or return values) and not a uncomputable problem. please stop spreading fud. you only need a GC to recycle cyclic data structures, with links back to previous nodes. since Carp does not create such data structures in the generated C code the reclamation scheme can be kept simple. heap vars to be kept glob…
In other words, they leak if the program no longer references them.
> every dynamic language does keep it functions and closed over values global.
Yes, but most of them collect closed-over values when they are no longer used. Using a garbage collector. To avoid memory leaks.
Re: Carp: a statically typed lisp, without a GC, for high performance applications
#67Earlier quoted context omitted.
tracking the scope of vars is a simple compiler job (yes, also across functions, when used as byval or byref args or return values) and not a uncomputable problem. please stop spreading fud. you only need a GC to recycle cyclic data structures, with links back to previous nodes. since Carp does not create such data structures in the generated C code the reclamation scheme can be kept simple. heap vars to be kept glob…
> heap vars to be kept global (such as closed-over upvals you are complaining about to be leaking) are kept global and released at the end. In other words, they leak if the program no longer references them. > every dynamic language does keep it functions and closed over values global. Yes, but most of them collect closed-over values when they are no longer used. Using a garbage collector. To avoid memory leaks.
Tracked global vars are of course free'd at the end of the program. There's no leak.
2nd closed-over values inside global closures can only be freed at end. A common problem in non-GC'd languages, which can only be fixed by adding a GC. Yes. The goal here is to avoid a GC. So don't reference big memory inside closures (as upval or return val, local is OK), or undef them explicitly, as in every dynamic language.
Using local closures would fix that, but Carp has no syntax for that I think. It would need an assignment from lambdas. Most langs prefer a simple global deffun variant instead. Lua got that right. That's why lua is the preferred game VM. But being able to use the easier and more simple lisp syntax should be preferred.
Re: Carp: a statically typed lisp, without a GC, for high performance applications
#68To the author: please, please, please port (or reuse) LuaJIT's C-header parser for FFI; it's the best FFI interface specification method if seen among JNI, Python, V8 and even C# (because you can just use the C header, with support for typedefs, unions and packing). It really looks like a great language!
Interesting, thanks a lot for the tip!
Re: Carp: a statically typed lisp, without a GC, for high performance applications
#69Earlier quoted context omitted.
> heap vars to be kept global (such as closed-over upvals you are complaining about to be leaking) are kept global and released at the end. In other words, they leak if the program no longer references them. > every dynamic language does keep it functions and closed over values global. Yes, but most of them collect closed-over values when they are no longer used. Using a garbage collector. To avoid memory leaks.
Oh my, have you ever implemented a dynamic language? Tracked global vars are of course free'd at the end of the program. There's no leak. 2nd closed-over values inside global closures can only be freed at end. A common problem in non-GC'd languages, which can only be fixed by adding a GC. Yes. The goal here is to avoid a GC. So don't reference big memory inside closures (as upval or return val, local is OK), or undef…
Cool, we're agreed then.