Note that Chicken has a very interesting garbage-collection algorithm called "Cheney on the MTA". Basically, the stack is the heap, and no function ever returns. The compiler converts every program to continuation-passing style, where instead of a function returning, it tail-calls a continuation. When the stack exhausts its limit, the runtime longjmps back to a trampoline. Variables captured by the current continuation form the roots of a copying generational GC - the runtime traces every pointer from them and copies the live objects to the heap. The stack then unwinds, with every uncopied object being garbage that gets re-used the next time the stack grows.
It's pretty amazing that it works, particularly in relatively portable C. Also gets fairly decent performance, too: as Schemes go Chicken is one of the faster ones.
> as Schemes go Chicken is one of the faster ones.
If you believe ecraven's benchmarks it's pretty exactly middle of the pack. Chez Scheme, Racket, Gerbil, MIT, Bigloo Guile, Loko, Cyclone, and Bones all are more performant.
And the ones where it does better are almost all not very popular implementations.
I think its speed is totally fine and I like the language and community but I don't think it's relatively fast among Schemes.
No, Cheney on the MTA uses the stack as the nursery of a generational collector; the live objects are evacuated using Chris Cheney’s copying algorithm (developed for the Cambridge ALGOL 68 compiler).
Chicken’s last generation GC might be mark-sweep, but that isn’t the MTA part.
Well, I have a hunch the scheme world is moving towards delimited continuations, so virtually free call/cc isn't that interesting anymore.
And the continuations are only cheap in the chicken context. Other schemes with other GC strategies have continuations with a large overhead, but still manage to be faster than chicken in benchmarks that are very continuation heavy.
Chicken is a very nice scheme, with probably the nicest Devs of any open source project, but cheney on the MTA is not magic by any stretch.
To my knowledge nobody has recorded a version of the song about Cheney, but it may be enjoyable to listen the more popular version about Charlie: https://www.youtube.com/watch?v=7Tc1GUXxr2o
I would love to be able to use chicken on a regular basis, but unfortunately it is an enormous pain to get it install on a system at the same time as mono because the mono c# compiler and the chicken scheme compiler have the same name [0].
True this is a big problem, i have faced the same eventually i uninstalled Chicken, though i really love the size of Binaries and how fast they are. On several tests i did Chicken Scheme outperforms Go lang for a similar implementation.
Similar issue applies on Windows with Visual Studio's C# compiler; Tho in that case it's a terminal with a non-default starting script that adds the C# compiler, so default and that non-default terminal point CSI or CSC at different languages.
I have never really been exposed to the likes of Scheme, Lisp, Smalltalk etc. and I'm curious if anyone without an academic background actually got in to any of that by themselves.
Generally, it's just a bunch of JS, C#, Java, Python, and some Scala that runs everywhere I look, which often also has a large "I came across it and I got to work" type of developer or engineer using it. Maybe it's just the type of ecosystem I keep hopping around it but it seems that it's much less prominent than you'd expect.
There are always novel compilers, transpilers and showcases, but the amount of widespread use eludes me. (Only ErLang comes to mind with RabbitMQ, and maybe OCaml with Xen)
I got into it myself. Scheme is how I self-learned programming. Through a copy of SICP found in a local university's book store specifically. I found the minimal syntax very conducive to learning. I was working in a call center at the time, but even while on calls it was possible to do the exercises in a different part of my head, since there was no real language to worry about. I don't think I would have had the same success with K&R, or God forbid: one of those 1,000 page OOP tomes.
Chicken Scheme was the specific implementation I started with too. I always found it fast/solid and saw no reason to switch. The abstractness of Lisp and the direct access to memory/C FFI were a nice mix. It suited my interest in music, where composition and DSP fell into those two respective domains.
I don't have an appetite for dynamic languages these days, but I might still reach for Chicken if I had to put together a dozen line script or something.
I got in to it myself. And, early on, it was a real struggle. Like many, books like SICP, Little Schemer, On Lisp, were all powerful testaments to the family of languages. But those all came later.
I poked around Lisp, very casually, for many years. But early on I really struggled with `lambda`.
It was a meaningless word to me. The classic complaints with CAR and CDR et al didn't help. More meaningless words.
Finally, I managed to stumble across the book "Simply Scheme". And the first thing it did was rename everything. It didn't take long to realize that `lambda` was a function. And then, the light clicked on.
"Oh."
During my learning of computer concepts, etc. there were a few events of true "epiphany", and learning what lambda really was, and how it worked, closures, that was one of them.
The secret for picking it up is to just use it.
Not for some huge project, not for bolting together a bunch of pre-built libraries. But for some actual processing. Something that needs little more than to read some file, do something to it, and write it back out. Baby steps.
And, certainly, don't get intimidated by the development environments. I use emacs for my work simply because it paren matches and auto-indents. All of the integration, I don't bother with. My projects aren't that big. A few thousand lines of code. I'm spoiled by auto-indent (and re-indent), so that's my crutch.
The key point being it takes very little to get started.
Working the problems in Little Schemer is fun. Doing SICP exercises is fun. On Lisp is an inspiring, opinionated book, and fun to read because of it. So, you can start there.
Go "write Fortran in Lisp", as they say. All of the stuff about macros and lambdas and functional or not etc. doesn't do you much good when you're searching and staring at an 8 page document on LOOP. Just write some simple stuff to get familiar with the things every piece of code has to do: input data, calculate on it, iterate on it, and print it out. Looking up the stuff that's muscle memory for your other languages kills momentum and motivation. So, work some simple stuff first. Write some crummy code first, then work on idiomatic code. Work on using new concepts later.
I’m interested to know what are common epiphanies for developers.
For me, I can remember:
- objects are closures and closures are objects
- properly getting the JS asynchrony model
- pointers and the whole memory addressing model
- HTTP being stateless
I must have had an early epiphany with function return values, since I remember not writing functions correctly at first, but I don’t remember the actual epiphany.
I don't remember specifically what it was as I started quite young, but especially starting out there were a couple of major "lightswitch flipped on" a-ha moments like that.
I think realizing that execution in imperative languages was one after the other and that there's a sort of "cursor" that goes through the code (execution flow/instruction pointer/whatever) was one of the first things that made things click.
I miss them, as they were incredibly endorphin-releasing moments.
For me the big 3 were arrays, dynamic memory, and lambda/closures.
But I must admit, the day I saw a guy run, essentially, "cpio ... | rsh otherhost cat > /dev/tape", that was a very "aha" moment in terms of overall system design and what networking brought to the table.
I picked up Common Lisp mostly because it intrigued me and there’s a decent market for Clojure and Haskell. Google Flights is still based on a CL flight search engine. Walmart processes all their receipts with Clojure. Target does a bunch of data sciency stuff in Haskell.
Sure. I tried out Clojure on a whim, realized it's nice, later switched to Scheme because the JVM made it hard to interact with native. Also touched a bit of elisp, but more out of necessity, since it's the only way to configure emacs. Not at all academic, I just do stuff, though I did have a bit of Haskell experience which made these languages feel more natural.
academicity~ is not necessary, it's more a matter of personal taste to me. I was utterly digusted with java in the 2000s and found lisp / scheme to be so much more interesting, consistent, small .. so I got into them.
Their history is tied to academic / research and concepts but it's not necessarily a barrier.. if you like hacking, and learning you'll find pleasure there too. Also a lot of what you're using these days have been pioneered in these fields so you might connect both past and present nicely.
I got into Common Lisp > 9 years ago with being exposed to it in academia, or really even from social/pop-culture influences. I was looking for a language that had relatively good performance that was easy to prototype code interactively for and Common Lisp + SLIME fit that need perfectly.
From there I learned how easy it was to make your own Lisp and learned a lot about how programming languages work and had a lot fun with that for a while.
I (academic background in physics, but visited only few courses in CS) got into it myself late in life. As an autodidact it's all too easy to miss some relevant background information. E.g. Perl's "local" variables made sense to me only after learning (much later) Common Lisp with its dynamic variables (partly because documentation around CL tends to be more thorough).
... then we could write a domain specific language for building web pages and another one for managing additional features, thanks to the power of lisp macro.
I generally like RSR6, but Chicken opted to stick with RSR5 for a long time, which honestly was a deterrent for me. They are in the process of implementing RSR7 which is strangely incompatible with RSR6. Racket has been my go-to scheme for awhile. The only time I would consider Chicken over Racket is if I needed tight integration into an existing C project and had size constraints. Is there something else I'm missing out on?
> Chicken opted to stick with RSR5 for a long time [...] implementing RSR7 [...] Is there something else I'm missing out on?
As an outsider (I admire Scheme, but don't really use it day to day), I got the impression R6RS was very divisive. Some people really wanted to make a "batteries included" revision to the standard so that Scheme could be used the way Python/Java is. However, this meant that the standard was prohibitively complicated for small/research implementations, and it lost some of the R5RS elegance and philosophy. In response, R7RS tried to tie things back together by having two versions (I think they call them Small and Large), where Small is a subset of Large, and both pretty much disregard R6RS.
Anyways, I believe Chicken was firmly in the "disagrees with the design of R6RS" camp. And for what it's worth, I think the decision to create the name "Racket" (and associated design changes) also came about because of this schism. Even though they have an R6RS language/implementation, I don't believe the Racket language conforms to any of the RnRS standards.
I'm certain someone here can do the history more justice if they wanted.
1) R6RS isn't really all that "batteries included", though it has some really basic features like hash tables that weren't in R5RS (but were in most Schemes anyway). The emphasis was on portability and safety. All R6RS implementations, if they don't have bugs, behave the same as all the rest at least as far as the standard extends, and the standard defines pretty closely what arguments are accepted, what values are returned, and what exceptions are signaled (the last was controversial even within the closed R6RS committee).
What wasn't considered was interoperability with common practice in other Schemes. In pursuit of this, R7RS favors interoperability over portability: the standard is less constraining, which makes it easier to integrate with existing Schemes. So R6RS hashtables (things that can be hashted, eh?) are incompatible at the procedure name level and some of the semantics with almost everybody else's hash tables. R7RS-large made them as compatible as possible. (Granted, we took more time to think about it.) R7RS-large also favors big-enough-ism over minimalism within each library, though it won't have as many libraries as people from other languages might like.
2) The current plan for R7RS-large will provide many parts of R6RS (a little bit R7RS-ified in some cases), provided they are voted in by the R7RS-large working group.
3) The rename of PLT Scheme to Racket had nothing to do with RnRS. PLT supported R6RS before and supports it R6RS today, though its use is not particularly encouraged by the Racketeers, who want you to use their own main dialect of Scheme, also called Racket. The change had more to do with PLT's multilingual capabilities: it supports many dialects of Scheme plus completely non-Scheme languages like Python and Algol 60, and it would be straightforward, if tedious, to provide Fortran, Cobol, and even C. In addition, PLT had no real link with the various university programming-language theory groups any more.
On participating in the Working Group:
Any Schemer can join the Working Group at any time: subscribe to scheme-reports-wg2@googlegroups.com and listen for CFVs. (If you have never voted before on anything Scheme-related, send a message after you subscribe giving your name, a little bit about yourself, and a bit more about your interest in Scheme. This is primarily to discourage sockpuppets.) There are long spells of inactivity followed by intense discussion when a new ballot comes up. All discussions and votes are public. Behind-the-scenes work is also done in public using the SRFI process at srfi.schemers.org, which produces specs and sample
I didn't do much work in Chicken, but I chose it as a language for ops scripts that were to run on any old Unix box whose installed software I couldn't control, e.g. AIX, Solaris, HP-UX, RHEL 5.
Couldn't even count on Python 2 being there. It was either POSIX shell or statically linked native, and Chicken (with a few modifications) allowed me to do that on all of the above platforms.
Fortunately (in retrospect), none of my code ever found much use. Learned a lot about Scheme, though :)
We usually write RnRS. If you're into Unicode or markup languages like TeX and HTML, you can write R⁴RS, R⁵RS, R⁶RS, R⁷RS, or generally RⁿRS.
And yes, I think that "The Revised Revised Revised Revised Revised Revised Revised Report on the Algorithmic Language Scheme" is pushing the joke rather too far, but R⁷RS is what name got consensus. It's modeled on "The {,Revised|Modified} Report on the Algorithmic Language Algol 60", where the usual abbreviations were R, RR, MR, but I like to write R⁰RA60, R¹A60, R²RA60 instead. Ditto with R⁰RA68, R¹A68 for the distinct language Algol 68. Finally, the incomplete report on the Scheme offshoot Kernel is R⁻¹RK.
I'm wondering: are there any RXRS compliant scheme implementations that are competitively fast? say comparable to js or lua, or even C/rust? If not, is the reason coming from scheme itself, or is it more a lack of effort in this direction?
I would say the reason it beats Chicken and Gambit is that it has a Scheme-specific compiler to machine code that has been worked on for a long time with performance in mind.
Dybvig's talk on Macro Writers' Bill of Rights explains some of the optimizations Chez does: https://www.youtube.com/watch?v=LIEX3tUliHw (Why macro writers? Because the compiler will handle superfluous generated code so macros doesn't have to)
Would having (optional) type annotation, or even a relatively coercitive type system help much in the way of performance?
Admittedly, this wouldn't be scheme anymore, but are there example of this done in the wild with profitable impact? E.g. even as an extension to RXRS.
I'd guess if you're sure your `fib` function handles only integers, you should get a lot of easy inlining/specialization at your disposition.
Chez instead provides typed/unchecked arithmetic functions, like fx+, flround and so on. In my experience, those sometimes make a big impact on performance(though realistically in some of those cases it would be better to ask C to do it for you).
How does the C ffi in Chez (or guile if anyone is familiar) compare with Chicken? I’ve heard good things about all three but have only used guile a bit, but never the C ffi. I’ve heard Chicken proponents speak highly of the ffi but have not seen any comparisons between the three implementations.
Developed by Kent Dybvig, sold to Chez which did who-knows-what with it (hiring Dybvig as well) but never commercialized it directly, and then open-sourced by Cisco.
"Cadence Research Systems" (CRS) was Kent's company. The system was "Chez", and was a commercial product of CRS since the '80s. Kent sold CRS (and thus Chez) to Cisco in 2011, and they didn't commercialize it directly, but happily it was open-sourced in 2016.
We built a server backend using Chicken in six months, it held up under significant load, and as normal the database connection was where we had to put most of the engineering effort.
We used a few macros to remove overhead in a few places where you'd use generic functions, and that saved us a little performance.
All in all - I'd happily use it in production again. I like it when the tech stack is boring and does what is expected of it.
I was using Sublime Text, a couple others were using Atom. The only one with a CLI editor used vim.
Just about everything out there will have decent Scheme support. It's a lisp, and it's a well-defined lisp. Scheme being well-specified makes everything simple. (Even the SRFIs are well specified.)
Our deploys were via Jenkins, but through Chicken's egg system it wasn't exactly a complicated process.
I hear a lot about “repl-driven” development with Clojure and CL, but anytime I get experimental with it I find myself neck-deep in editor configuration, or simply wrestling with emacs keybindings.
Because load was a primary concern, we mostly used a test-driven cycle where we'd spin up the server and then attempt to DOS it for every change. Not something you want happening much on your dev machine.
However, for the simpler tests, if the test system hit a failure, it would then drop into a REPL (not on the production server). So it was sort of like a nicer debugger.
The test system was developed in-house, but if I remember, it was something like a 100 lines of code. That's one of the things that Scheme guides you towards - if you don't have a wheel, it's generally five minutes to make one.
I wouldn't generally bother fighting with emacs or configuration for anything. If you're fighting your tools, you're not being productive. Fine to do if you're not being paid, not so fine in a workplace. Keep things simple, and you'll do better than if you try and be clever. Rainbow braces and documentation lookup will get you 99% of the way to where you want to be.
That being said, one of our devs wrote their code with Wisp (SRFI-119), and had a git pre-commit hook that automatically rewrote it back to normal Scheme, and another hook in their editor to turn it into Wisp code when they opened a file. Nobody noticed for over a month.
Scheme makes it easy to write the way that you want to, using the tools that you like.
My experience in taking to Schemers is that Schemers tend to think more in terms of a more normal “put code in a file and load the file” mindset. (Matthew Flatt of Racket fame is known for “the toplevel is hopeless” which has implications for the sorts of features necessary for truly interactive development.) CL, Clojure, Smalltalk are more on the REPL-driven development side of things.
Discovering this philosophical division was a bit surprising to me when I first started talking to Lispers outside of my CL bubble.
I'd distinguish between REPL driven and Image driven, the latter a subset of the former. I cherish the REPL, but Image based programming reminds me to much of bad old days in FORTH. That might be the approach to get a working solution by a single excellent programmer for problems of modest difficulty the soonest when no one cares how one got there and how to replicate that success and whether one can learn from missteps along the way, but for all else the file based approach with version control is IMHO the safer bet. There one still can use the REPL to experiment with ideas and test small steps.
That’s not the distinction I’m making: my CL workflow is to always start from a clean image that has been restored from source control (although, I think the ideal here is a system like Pharo that integrates VC into the image itself). What I mean is that Scheme users seem to have a workflow that’s more along the lines of what people do in Python, Ruby or JS, running the interpreter/compiler as a “batch” process whereas CL/Clojure/Smalltalk pursue a more interactive development experience.
Python devs use both styles depending on preferences and app type, IME. The notebook tooling is also great for sharing already set up REPL environments with state.
Sort of: when I wrote a lot of Python, I used REPLs pretty heavily and I’ve also used notebooks a bit. The issue is that Python isn’t designed in a principled fashion for interactive development: reloading imports and other objects doesn’t always work the way you’d expect.
Reloading cross depending modules with identical semantics (vs aappcold startup) is just as fraught in other languages I think. Upgrading existing instances of objects is a bit more automatic in some but then results in surprises and bugs if not anticipated in code.
I know what you mean. A few months back I started playing with GNU Guile and wanted some of that nice repl integration. It took me more hours than I would have liked, first because I wanted to use vim instead of Emacs, and second, because vim for parenthesis language programming is frowned upon and harder to find examples for. In the end I wrote my editor config in a gist to make it easier to discover https://gist.github.com/mhitza/a00d7900571e9f13bac2bbf4a203d...
When I get more free time I'm definitely eager to jump back to Guile programming. But on my first test drive, I definitely had good experience with the repl driven approach. No matter how barebones of a setup it is, it's better than my past Haskell repl experience, where it almost felt like a tool you need to use no matter what.
To begin with, but as half of the devs, myself included, were sight-impaired, the symbol-heavy syntax became a real drag and we transitioned away from it.
In the end, what we ended up with was our own library written around libevent, which could interface with awful's plugins. As a bonus, it was much, much faster than awful. It even beat out nginx in some situations.
I have a multiple-choice quizzing system written in Chicken that's been running at our uni for the past 15 years. It was meant to be a throw-away, to be used for a semester until the bugs in our learning-management system were fixed. But it still gets some use, and has clocked ~350,000 test submissions over the years. Not too shabby for a throw-away. It just runs, and I never think about it... until someone asks a Chicken Scheme question!
I used Chicken successfully in an embedded Linux system where C interop was a high priority. It's a great compiler and one of my go-to Schemes to this day, though obviously the library ecosystem is nowhere near as complete as e.g. Python's.
I found the documentation to be good. I remember looking at it and finding whatever I was looking for, thinking: "It's all here!" Even stuff, that I do not fully understand like CK-macros (http://wiki.call-cc.org/eggref/5/ck-macros).
There was one issue though, which stopped my hobby project: Support for UTF-8 in display seems to be broken: http://bugs.call-cc.org/ticket/1374 As I tried to build a vocabulary trainer, I had to switch to another Scheme.
We had to write a lot of our own stuff but it fits fairly neatly into the scheme-way of doing things: you can get a remarkable amount done with just a few simple lines of code.
I'd probably want to write about as much in any other language as a lot of what we built were domain level abstractions.
We had a very talented web designer and we also built a "Widgets and forms" toolkit. I gave a talk at FrOSCon quite early in the development and it was saved for posterity: https://media.ccc.de/v/c116_lisp_-_2013-08-25_11:15_-_buildi... The first few minutes of audio are broken but it sorts itself out.
There's a tradition of skullduggery-related names: Guile, Gambit, Gauche, Heist, Larceny (with variants Petit Larceny and Common Larceny), Racket, and Stalin (it optimizes your code -- brutally). "Chicken" is I believe related to an actual rubber chicken (which of course is also unreal).
I don't mean this comment to be critical of the OP, who is undoubtedly acting in good faith, but how after all this time is this submission not somehow flagged as a duplicate?
It's pretty amazing that it works, particularly in relatively portable C. Also gets fairly decent performance, too: as Schemes go Chicken is one of the faster ones.
https://www.more-magic.net/posts/internals-gc.html
https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.54....