14 ms·
Carp – A statically typed Lisp, without a GC, for real-time applications
- protomikron 5y agoCan somebody please explain or give me some links how FP is supposed to work without a GC? For example Rust has different types of function pointers (Fn, FnMut, FnOnce), to guarantee the possibility of lifetime analysis (so it is arguable to consider it a functional programming language). On the other hand the most common FP languages (OCaml, Haskell) all come with a GC. Or am I wrong in assuming this is a functional language?
- astrange 5y agoAs long as you forbid or mark cycles (…or ignore the problem) lifetime analysis can be done statically. Which is better anyway. Automatic memory management doesn't need a GC.
- silon42 5y agoIt's really surprising that it's rare in functional languages. Immutability seems like it should guarantee no cycles (?), so reference counting could be used.
- jbjohns 5y agoWhy would immutability guarantee no cycles? Here is a line of valid haskell: star e = let (sp, a) = (Split a e, atom sp) in sp EDIT: I guess I should probably explain it: star is a function that takes an expression "e" and returns the value "sp" which is "Split a e" where "a" is the results of calling the "atom" function on "sp". This is creating a representation of a regex star operator. Note that the tuple defined in the let definition is only to define a name for the two values of the tuple so that they can refer to each other.
- JoelMcCracken 5y agoI mean generally tying the knot is a useful technique, but I think these scenarios all require/exploit non-strict, which is in itself not really immutable in the sense most people use it. But yes, such code is often useful so that e.g. a parent xml node can refer to its childen nodes while also children nodes can refer to their parents. Anyway, I'm not sure about this, but I think you can't have circular data structures in the context of strict evaluation (or can you? maybe by defering execution via anonymous functions? I wonder....)
- jbjohns 5y agoI'm fairly certain I've done similar things in Ocaml (in fact, I think it's where I learned this technique).
- wyager 5y agoThere are two ways to get cycles in Haskell. One is through “tying the knot”. E.g. to create an infinite list of 1,1,1,1,1,… ones = 1 : ones This will actually be compiled to a list cell with a pointer back to itself. You can construct more complicated self-referential data structures thanks to laziness. The other way you could get a cycle is that it actually does have mutable data structures, although their use is restricted so they can’t have any observable mutable effect in pure code. But you have e.g. IORef which is basically a mutable pointer. If you wanted no cycles you would need to eliminate some subset of laziness, knot-tying transformations, recursion, and any support for mutable data structures. But yes, I think it could be done.
- kragen 5y agoReference counting is usually very expensive, because even reading a variable updates the reference count, and ending a scope involves testing the reference count of every variable defined inside the scope and conditionally deallocating the referent. Without reference counting, here's the end of a hairy function scope that deallocates 15 local variables and restores two callee-saved registers: 11a6: 48 83 c4 78 add $0x78,%rsp 11aa: 5b pop %rbx 11ab: 41 5e pop %r14 11ad: c3 retq Now imagine looping over 15 local variables to decrement each reference count, test it, and do a conditional jump based on the result; if that's open-coded, your epilogue is humongous, and if it's in a reference-count-decrementing subroutine, it's going to have mispredicted branches all over the place, costing you maybe 15 cycles each, a total of about 100 cycles for this function. We're talking about adding an order of magnitude of cost to subroutine call, or more. (I think this function doesn't really need 15 local variables; that's the compiler's fault.) This gets worse with multithreading, because writing to the same reference count on different cores would even in the best case require one core stealing the cache line from another in order to modify it, which may stall the core; but often even an atomic reference count increment is more expensive even than that because it involves a memory barrier. Reference counting can become reasonably cheap if it's done at large granularity (filesystem files or COM objects, not conses); if you can elide almost all of the reference-count updates, as in Rust; or if your language runtime is just so dog-slow at everything that the extra cost of reference counting isn't that important, like CPython. 30 years ago or more, before generational GC had gone mainstream, reference counting was a more reasonable choice, because GC was going to be very slow in any case, and ref counting at least used less memory—especially important on machines without cache or virtual memory. (Purely immutable (applicative) languages like Haskell and Miranda are usually lazy, since that's the payoff for completely abjuring side effects. But lazy evaluation is implemented at the machine level by mutation.)
- naasking 5y ago> Reference counting is usually very expensive, because even reading a variable updates the reference count There are many papers out there on how to elide most ref count operations on locals, and runtimes that use ref counting for automatic memory management typically defer ref count updates in various clever ways (like Nim IIRC). You give up some latency for significant throughput gains.
- dwohnitmok 5y agoThe big thorn is closures, which show up all over the place in FP. You either need to limit closures vs ordinary functions (as e.g. Rust does), have manual memory annotations (such as e.g. what Swift does) or you basically need a GC. The former two choices are annoying if you really take advantage of functions as first-class citizens.
- silon42 5y agoYes, I thought that might be a problem... I guess Rust is the choice for me.
- pharmakom 5y agouse value semantics for everything is one way
- vnorilo 5y agoLisp is not necessarily functional. There's a lot of mutation in Common Lisp even if the community favors a functional style. I think the question is: how does Lisp function without garbage collecting cons cells? For one, I'm not sure they even rely on cons cells like "real" Lisp. Clojure doesn't either. They cite ML as inspiration. Carp language guide states object lifetimes are statically inferred [1] which my guess is they allocate on stack (or malloc/free by scope) and detect use-after-free at compile time. Another, more theoretical approach is using linear types which require all values to be "consumed" [2] 1: https://github.com/carp-lang/Carp/blob/master/docs/LanguageGuide.md https://github.com/carp-lang/Carp/blob/master/docs/LanguageG... 2: https://www.cs.utexas.edu/users/hunt/research/hash-cons/hash-cons-papers/BakerLinearLisp.pdf https://www.cs.utexas.edu/users/hunt/research/hash-cons/hash...
- protomikron 5y agoThanks for the links. There's also this Reddit discussion [0] from 2 years ago (it mentions Carp btw.) and an explanation about how Carp manages memory [1]. [0] https://www.reddit.com/r/haskell/comments/d5d13i/is_it_possible_to_design_a_functional_language/ https://www.reddit.com/r/haskell/comments/d5d13i/is_it_possi... [1] https://github.com/carp-lang/Carp/blob/master/docs/Memory.md https://github.com/carp-lang/Carp/blob/master/docs/Memory.md
- alexisread 5y agoIn particular, the reddit discussion mentions ASAP, which is a set of static analysis algorithms that can work with mutability, generics (polymorphism) and linear types. http://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-908.pdf http://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-908.pdf As far as I'm aware, this really only applies to single threaded systems. However, if you implement threadsafe modules and keep the shared stuff internal (use the ASAP algos here), you can fit the majority of use-cases including hard-realtime constraints. Composita is the module system I'm referring to. http://www.composita.net/Composita.html http://www.composita.net/Composita.html It allows concurrency with managed memory and no GC, through static analysis of the module (component) interface queues.
- 5y ago
- timonoko 5y agoMe knows: "TN-tools in Nokia were automatically compiled into C-code to be run in VAX-computers. Compiled C-code did not have garbage collector, there was separate reclaim-command for discarding used data. If you managed to run your program without ever hearing the BEEP caused by garbage collector, your program was ready for VAXing." https://timonoko.github.io/Nokolisp.htm https://timonoko.github.io/Nokolisp.htm
- mlang23 5y agoLisp is definitely not as functional as for instance Haskell is. Side-effect-freeness was never really a topic for Lispers.
- medo-bear 5y agoYou are right, Lisp is far more versatile. There is even a statically-typed language Coalton [1] embedded into Lisp. [1] https://coalton-lang.github.io/20211010-introducing-coalton/ https://coalton-lang.github.io/20211010-introducing-coalton/
- cmrdporcupine 5y agoFrom the Carp docs: Memory management is handled by static analysis, a value is owned by the function where it was created. When a value is returned or passed to another function the initial function will give up ownership of it and any subsequent use will lead to a compiler error. To temporarily lend a value to another function (for example to print it) a reference must be created, using the ref special form (or the & reader macro). and achieved through a linear type system where memory is owned by the function or let-scope that allocated it. When the scope is exited the memory is deleted, unless it was returned to its outer scope or handed off to another function (passed as an argument).
- andi999 5y agoSo how is memory fragmentation avoided?
- pjc50 5y agoThat's a question for the underlying allocator, surely? (Quite often the answer is "it isn't")
- andi999 5y agoNot just for the allocator. I always thought a main point of a garbage collector was heap compactification (shuffling things around so there is more space), but maybe I am wrong.
- xxs 5y agoNot every GC has compaction phase though, but generational ones do by design.
- cmrdporcupine 5y agoNah, only copying / generational collectors do heap compactification. A simple Mark&Sweep collector doesn't, for example. Nor does reference counting. Both of which are used by many Lisp or Lisp-like languages. Nothing can substitute for a really good allocator.
- mumblemumble 5y agoIn general, most lisps are imperative, or support multiple paradigms including imperative. First-class functions are a necessary feature of FP, but the mere presence of the feature does not make a language functional. Some counterexamples include Fortran and Smalltalk. It's an easy misconception because most the well-known newer entries to the lisp family - Scheme, Racket, and Clojure - are all mostly functional, and because most of the major non-functional dialects of lisp died out 30 or 40 years ago.
- RobertKerans 5y ago& Rust is surely a highly imperative language that has absorbed functional idioms (where appropriate), rather than something that falls under the banner of "functional language"?
- amelius 5y agoThere's a reason why functional languages all use a GC. And that reason makes Rust not such a good language for functional idioms unless you stay within very strict lines.
- fuzzythinker 5y agoAnyone who had used or tried Carp and Janet (that was on frontpage the other day)? What are some strong points on Carp vs. Janet?
- pgt 5y agoJanet is dynamic with a garbage collector. Carp is a GC-less static Lisp with deterministic memory allocation via a Rust-like borrow checker. I only wish Carp had stayed nearer Clojure's syntax. A more familiar syntax would make it more accessible.
- rcarmo 5y agoI've been reading through the examples and it's readable enough. What is it that you find odd?
- kbd 5y agoAs someone who doesn’t know any lisp well, it’s odd to hear you highlighting significant differences in syntax between them. I thought the character of a lisp is that it doesn’t have much syntax. I’d be interested in an example.
- pjmlp 5y agoClojure adds [], {} and #{} as additional syntax for arrays, hashmaps and sets.
- lf-non 5y agoI have not used carp, and janet only briefly. However, other than both using lisp syntax, there are very little similarities between the two. Janet has a garbage collector, no static types, no ownership tracking - the perf. is similar to lua, so is not be ideal for low-level/realtime systems, which carp is targeting.
- fuzzythinker 5y agoThank you and @pgt. I thought Janet compiles to C or native bytecode due to its strong interop with C.
- xvilka 5y agoThere is also interesting CL implementation that is based on the LLVM framework - Clasp[1]. It can be natively compiled and designed for performance. [1] https://github.com/clasp-developers/clasp https://github.com/clasp-developers/clasp
- simiones 5y agoCLASP is a really interesting project. For one, it's created and written by a Chemistry PhD researcher (Christian Schafmeister), not someone with a traditional CS background. For another, it's one of the few languages that has ever attempted to interface with C++ at the template level - you can instantiate C++ template classes from CL, and catch C++ exceptions etc. For yet another, he does compacting garbage collection for the C++ objects used in the CL implementation, with pointer patching and everything else. There's a nice Google Tech Talk about it [0], that goes into both why he did this, and how he implemented this. [0] https://www.youtube.com/watch?v=8X69_42Mj-g https://www.youtube.com/watch?v=8X69_42Mj-g
- pjmlp 5y agoI guess it helps that it is pretty much a Lisp for the research work that they are doing, instead of trying to cater to everyone.
- gavinray 5y agoDr Schafmeister is occasionally present on the LLVM Discord. The CLASP project is something else. That hour-long talk he gives on Youtube about it blew my mind.
- aidenn0 5y agoLast I checked SBCL and CCL (both open source native compiled CL implementations) are quite a bit faster than Clasp. However, if you are primarily e.g. calling computational chemistry libraries written in C++, Clasp is the way to go. It's the only non-C++ language implementation I know of with actually usable C++ support.
- 5y ago
- romesmoke 5y agoWas it always the case that, on a weekly basis (if not more often), new languages would sprout? It seems to me like considerable amounts of energy are invested on re-inventing-the-wheel instead of solving real problems with existing tools.
- ducktective 5y ago"Real-time" has a specific meaning in embedded and computing context. Does it mean that programs written in Carp have any guarantee on their order or duration of execution?
- wahern 5y agoUnless it has a scheduler for a concurrency or threading framework, what other characteristics beyond memory management would be relevant? I guess maybe certain types of built-in data structures--you'd probably want a map/dictionary based on red-black or AVL trees rather than a hash table.
- xxs 5y agoAny shared datastructure needs some kind of forward gurantess; e.g. being lock-free might not be sufficient.
- KMag 5y ago... or a hash table using RB/AVL trees rather than linked lists for hash buckets.
- xxs 5y agothe doubling of the sizes is an issue. Yet, I'd consider all single threaded datastructures a non-issue. The hard part is multithreading. Flip note: java's hashmap uses red/black tree for nodes when there are too many collisions (and the keys are Comparable)
- hawk_ 5y agobut java's hashmap still resizes when breaching the loadfactor. so any similar implementation, even for singlethreaded cases can't achieve (soft)realtime. I am not aware of any linear hashing or similar approach for in memory hash tables to mitigate such latency spikes.
- 5y ago
- invincivlepvt 5y ago<a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Graphic Designing</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Digital Marketing</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Digital Marketing Jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Graphic Designing Jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Digital Marketing Punjab</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Designing Punjab</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Development Punjab</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Designing Jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Designing Jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Development Jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Designing</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Development</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Graphic Designing Agency jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Graphic Designing Company jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Digital marketing Company jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Digital marketing Agency jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Graphic Designing Agency Punjab</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Graphic Designing Company Punjab</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Designing company jalandhar</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Designing company Punjab</a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow"> Website Development company Punjab </a> <a href="https://invincivlepvt.com/ https://invincivlepvt.com/" rel="nofollow">Website Development company Jalandhar</a>
- invincivlepvt 5y ago<a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Web Designing Jalandhar</a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Web Designer Jalandhar</a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Website Designing Jalandhar</a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Website Designer Jalandhar</a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Website Designing </a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Web Designing </a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Website Designer </a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Web Designer </a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Web Designing agency jalandhar </a> <a href="https://invincivlepvt.com/website-designing-jalandhar-2/">Best https://invincivlepvt.com/website-designing-jalandhar-2/">Be... Website Designing agency jalandhar </a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Web Development Jalandhar</a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Website Development Jalandhar</a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Web Development </a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Website Development </a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Web Development agency Jalandhar</a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Website Development agency Jalandhar</a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Website Developer Jalandhar</a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Web Developer Jalandhar</a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Website Developer Punjab</a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Best https://invincivlepvt.com/website-development-jalandhar/">Be... Web Developer Punjab</a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Website https://invincivlepvt.com/website-development-jalandhar/">We... Developer </a> <a href="https://invincivlepvt.com/website-development-jalandhar/">Web https://invincivlepvt.com/website-development-jalandhar/">We... Developer </a>
- DeathArrow 5y agoWhat's the difference between it and Common Lisp? Isn't Common Lisp also AOT compiled?
- baq 5y agoAOT doesn't necessarily mean GC-less, right?
- brabel 5y agoMaybe they actually mean VM-less, which would probably imply GC-less because if you have a GC, you pretty much have a VM doing the GC (unless it's simple ref-count). For embedded, you need VM-less, I think, as VMs tend to be too heavy.
- bitwize 5y agoGambit has a VM and a GC, and is still AOT-compiled to C. (The Gambit VM is an intermediate representation of Scheme code which is then compiled down to C code.)
- white-flame 5y agoVMs imply a non-native bytecode execution. Garbage collection doesn't require any of that. It's just normal library code usually called by the allocator, and well-specified memory object/pointer layouts.
- jdc 5y agoFirst of all, Common Lisp is a language with several implementations, some of which offer AOT compilation. Secondly, a garbage-collection (aka automatic memory management) does not exclude AOT.
- jdc 5y agoSee also the Boehm GC, a garbage collector for C and C++. https://en.wikipedia.org/wiki/Boehm_garbage_collector https://en.wikipedia.org/wiki/Boehm_garbage_collector
- guerrilla 5y ago> (the Int x) I like the cute syntax for type annotations.
- aidenn0 5y agoI had to double-take because CL also has a THE also for declaring types, but it's a bit different; THE declares the type of an expression, not a variable (there is a separate type declaration for variables). so e.g. (the fixnum (+ x 1)) would assert that (+ x 1) produces a fixnum.
- timdeve 5y agoThat is also the case in Carp, x being an expression here.
- aidenn0 5y agoAh, okay. So is there a way to declare that a variable will always be of a given type in Carp?
- timdeve 5y agoCarp is statically-typed with type inference so writing (the Int x) would be enough for the compiler to forbid any usage of x as another type. Writing (Int.+ x 1) would accomplish the same as Int.+ only accepts Int. You can also annotate function with a type signature. (sig add (Fn [Int Int] Int)) (defn add [x y] (+ x y)) Is the same as: (defn add [x y] (the Int (+ (the Int x) (the Int y))))
- billpg 5y agoI was thinking of building my own LISP-like language, but seeing so many pop up on here I don't think I'll bother.
- jstx1 5y agoYou probably should anyway - most of it is for learning and personal satisfaction. It's not like any of these projects are competing for actual marketshare in the programming language landscape.
- tonyg 5y agoTry building a Smalltalk-like language. It throws a different set of concerns into relief, and besides, it's a better design.
- pjmlp 5y agoMillions of CS students build their own language for compiler classes every year. As learning exercise of everything that goes into making a compiler/interpreter is very worthwhile endevour. As means to make the next big thing, maybe not.
- brabel 5y ago> Millions of CS students... Are there millions of CS students in the world?? I would guess a few hundred thousand, at most.
- deleted 5y ago[deleted]
- pjmlp 5y agoMight be, I don't have the numbers. > A figure of speech is a deviation from the ordinary use of words in order to increase their effectiveness. Basically, it is a figurative language that may consist of a single word or phrase. It may be a simile, a metaphor or personification to convey the meaning other than the literal meaning. https://en.wikipedia.org/wiki/Figure_of_speech https://en.wikipedia.org/wiki/Figure_of_speech
- mlang23 5y agoThe name is strange. Reminds me of a product-naming story I heard years ago. Papenmeier from Germany was once planning to create a small notetaker with built-in braille display. They originally planned to name it "Braille Assistant", but the US distributors objected on the ground that they can already see users shortening the product name to "Braille Ass". I have a similar feeling with Carp, isn't the obvious transposition an issue? :-)
- 1500100900 5y agoDoesn't seem to happen to the Common Address Redundancy Protocol too much.
- rcarmo 5y agoGiven the kind of niche, self-deprecating humor often found in our ecosystem, it was probably seen as a plus :)
- kortex 5y agoIt'll be good company with git, GIMP, LISP, ploopy.co, etc.
- bjoli 5y agoThe creator was interveiwed in the podcast "Functional geekery": https://www.functionalgeekery.com/episode-96-erik-svedang/ https://www.functionalgeekery.com/episode-96-erik-svedang/
- soegaard 5y agoFor the history buffs: Pre-Scheme: A Scheme Dialect for Systems Programming Richard A. Kelsey, 1997 Abstract Pre-Scheme is a statically typed dialect of Scheme that gives the programmer the eciency and low-level machine access of C while retaining many of the desirable features of Scheme. The PreScheme compiler makes use of type inference, partial evaluation and Scheme and Lisp compiler technology to compile the problematic features of Scheme, such as closures, into C code without signi cant run-time overhead. Use of such features in Pre-Scheme programs is restricted to those cases that can be compiled into ecient code. Type reconstruction is done using a modi ed Hindley/Milner algorithm that allows overloaded user-de ned functions. All top-level forms in Pre-Scheme programs are evaluated at compile time, which gives the user additional control over the compiler's partial evaluation of a program. Pre-Scheme has been implemented and used to write a byte-code interpeter and associated support code for a complete Scheme implementation. https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.3.4031&rep=rep1&type=pdf https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.3....
- stan_rogers 5y agoThe letter combination "fi" seems to have been deleted throughout your quote, there. Perhaps it was a ligature in the original.
- NoGravitas 5y agoThis seems like fun. I could never get into Rust because of the syntax (there's so much of it), but this seems doable. I don't need it for anything, though; I don't do anything where SBCL isn't plenty fast enough.
- kortex 5y agoWhat's the difference between `let` and `the`? Skimmed the language guide and docs but it wasn't clear. `the` seems to be the typical type inference variable declaration. I'm not really familiar with lisps so this might be a documentation oversight. Looks really neat overall.
- timdeve 5y ago`let` is for declaring variables while `the` is a noop at runtime and only give type information to the compiler.
- rcarmo 5y agoSpent my lunch break investigating this a bit and it is quite nice, with the only caveat (for my use case) being that networking is handled by a third-party socket library that, alas, does not handle multicast sockets (don't ask...). Otherwise, examples are interesting, and certainly seem to cover most gamedev scenarios (haven't found any audio or MIDI ones yet).
- hcarvalhoalves 5y agoThis is interesting, but I believe a big point of LISP is actually having a live system that can be introspected, and GC is part of making that work. In the end isn’t this just <insert sys prog language> but with s-expressions?
- TeMPOraL 5y agoS-expressions also enable proper macros, as long as it has them, it's already ahead of <insert sys prog language>.
- hcarvalhoalves 5y agoI guess so, I think my point is: are s-expression enough to qualify as a LISP?
- TeMPOraL 5y agoDepends who you ask, really. For me, s-expressions and macros are enough, though it would feel very weird without a REPL and image-based development.
- kragen 5y agoOf course the obvious question is "What kind of memory management does it use?" It uses a "linear" (actually affine) type system for memory management, with borrowed refs similar to Rust, but evidently without tracking mutability: https://github.com/carp-lang/Carp/blob/master/docs/Memory.md https://github.com/carp-lang/Carp/blob/master/docs/Memory.md The omission of the kind of mutability tracking that eases multithreading seems like a significant drawback for its target application domain.
- p_l 5y agoIf the target is "real-time systems with low enough latency bounds to make GC an issue", the question starts to be "does it have predictable pause times" (Rust, afaik, doesn't due to backing mechanisms behind some of the lower level aspects of memory management and/or use of Rc/Arc, though of course someone could get things better there)
- doppioandante 5y agoDo you mind posting some reference on the unpredictability of pause times in rust? I'm interested in real-time systems and I'd love to know more.
- p_l 5y agoThis is more specifically about any reference counted system, though it also includes unique owner approaches and others. Namely, when you free an object, whether it involves manually written code to release anything it holds recursively, or through some form of reference counter, you do not know the size of object graph you're freeing. If you add any custom release logic to the mix (destructors, any kind of shutdown logic, etc), you also don't know how much extra work unrelated to simple memory management will be also involved. This means that naive manual memory management, or reference counting systems, have usually unbounded and unpredictable pause times (in addition to various costs involved in implementation details, whether it's malloc()/free() or refcounting). You do not know if object X going out of scope isn't the sole owner of a huge object graph. This is one of (though not only) reason manual memory management and refcounting aren't considered good options in real-time compared to static allocation of everything (object pools, static stack analysis & limits) or RT Garbage Collector algorithms, though of course it depends on how deep into the rabbit hole you go. Garbage Collector systems tend to have more control over pauses, but majority of algorithms used optimise for throughput, not latency or predictability. Thus you have "huge GC pause" as GC uses fastest space/time algorithm and "pays down the debt" for making allocation stupidly fast (often single Compare-And-Swap operation, sometimes not even that if each thread uses separate nursery and can keep local heap-end pointer). However you can also setup environment towards low latency and predictability, probably the most famous example being IBM Metronome (available in J9 and recently open sourced), which uses a static quanta of time for GC and minor variability is the noise of multiple threads of execution synchronizing. This works by dividing available time between mutator (your "work" code) and collector (GC) statically, so that GC will for example always run for 30ms then mutator for 70ms then GC for 30ms and so on. Similar techniques exist for amortizing pathological performance of reference counting by pushing actual deallocation into separate collector thread or similarly scheduled slice (depends on whether you're fine with possibly unpredictable contention between two threads or want more strict timing). A lot of very hard real time is more about predictability in the end.
- savant_penguin 5y agoI wonder if this deterministic memory management instead of a garbage collection would have helped discord with their spiking latencies https://blog.discord.com/why-discord-is-switching-from-go-to-rust-a190bbca2b1f https://blog.discord.com/why-discord-is-switching-from-go-to...
- TheDesolate0 5y agoFFS! No more fucking LISP!
- dragontamer 5y agoSo "cons", and the associated "car" and "cdr" functions are innately the "thing" that needs to be garbage collected in Lisp-like languages. So I immediately went to the manual, and CTRL+F'd for cons. Carp has the following restriction: https://github.com/carp-lang/Carp/blob/master/docs/Manual.md https://github.com/carp-lang/Carp/blob/master/docs/Manual.md > If you're calling a dynamic function (something defined with defndynamic, or a built in command) it will be executed right away. This works very much like a classic, dynamically typed Lisp interpreter. The dynamic functions are not available in compiled code! Their main usage is in macros and to programatically control your build settings. cons, car, and cdr are all "Dynamic" functions that can only run _DURING COMPILE TIME_. Which means the GC is not needed during runtime: all garbage-collection occurs in the compiler.
- kazinator 5y agoThat's a Lisp preprocessor for a non-Lisp language. If you program in C using the Common Lisp c-mera preprocessor, or any of the other similar systems, it's the same thing. You're writing everything in S-exps, and the expansions use conses, but the output is C; so that of course that cannot call cons at run time. https://github.com/kiselgra/c-mera https://github.com/kiselgra/c-mera