Fibers in Guile Scheme
github.com
github.com
I only know Scheme from reading SICP and enjoyed Clojure but hated the java/JVM part of it. I currently use Erlang for when I need concurrency/performant backends. But I'm not totally satisfied with it (for ex: the weak type system and records).
Edit: oh looks two programs I use all the time are written in Guile: GNU Make and WeeChat https://en.wikipedia.org/wiki/GNU_Guile#Programs_using_Guile
GNU Make supports Guile as an embedded extension language [0] and WeeChat supports Guile as a scripting language for writing plugins [1].
There are a few other apps mentioned on the Guile website [2] and more on their Libraries page [3].
[0]: http://git.savannah.gnu.org/cgit/make.git/commit/?id=c992c4d...
[1]: http://dev.weechat.org/post/2011/10/27/New-plugin-Guile
Guile is cool, if possibly immature.
To this day, the largest project I've done in Guile was the entirety of the exercises short of Chapter 5 in SICP, wrote unit tests for the interpreter and the 'Prolog' implementation, the whole lot. All told I generated approximately 10KLOC of Guile code, some 20% of it using features like GOOPs, threading, dynamic-unwind and so on. It was largely a positive experience and I am really glad I read ahead and implemented a few things as GOOPs classes rather than used the OOP system described in the Book (particularly for the Constraint Solver!)
As part of this, I did run into some faulty code generation (inappropriate optimization) on the master branch while completing an early Chapter 4 exercise: "This code could do multiple things if we apply different models of an idealized computer language (each of which was advocated by 'Susan' and 'Bob' in typical SICP fashion)", I wrote an implementation inside my guile interpreter that got an unusual answer and asked the channel about it and everyone got to the bottom of it fairly quickly.
Speaking of which, Guile has a community of absolutely rabid fans all over the world and so the support in #guile is absolutely phenomenal, people like ijp and mark_weaver are both true 31337s and always can be relied on to offer sage advice.
You've brought up it's utility as a GNU extension language, and although I feel it's public documentation is not given a fair shake in the important arenas like GDB scripting, it is tremendously useful in this capacity. Of course, as an extension language itself, it excels. Excellent exposure and interaction with the bare-metal, good parallel & concurrent primitives (although they are more 'traditional', taking after the proud line of Pthreads than `link' or send/recieve in Erlang). It is quite large to statically link into your binary in comparison to other languages however, so be careful there.
Weechat itself is written in C, but it does have Guile extensions (and unfortunately I may be the only person in the world to take advantage of this while writing an extension however https://github.com/zv/weechat-gateway-replacer ).
It's been a generally good experience. Scheme is fun, and Guile is a fine implementation. I'm not experienced enough to be pushing its limits – the only unusual corner I've explored is the C FFI, which is quite nice.
My only complaint is the consistency of Guile's documentation. It's generally of high quality, but there are corners that are completely undocumented – I've had a few cases where I had to dig into the implementation to figure out how to do something.
They do, however, use Guile as an extension language.
I contribute to Guix, but I also have my own projects[2] written in Guile. The only software that other people actually use, however, is Haunt, the static site generator that renders my blog (everyone needs to roll their own, right?)
I prototype loads of small tools in guile, and some of the prototypes "stick" since they exceed expectations. The biggest one is a macro system for pascal that expands recursive macros and unrolls loops, generating _lots and lots_ of code.
My scheme implementation of choice is chicken, since they have a package manager with quite a lot of packages, but I really enjoy using guile. Really looking forward to the new 2.2 branch. We are using that in production, and we probably hit a sweet spot where the magic optimization dust gathered the most. We got almost 2x improvement just by switching.
It's nice to be able to use a flexible and simple language like Scheme for tools like this. The HTML documents are written in SXML, so it's all S-expressions.
(I'm not a fan of Python, the obvious alternative for things like this.)
"But if your typey spidey senses are tingling, it’s for good reason: with promises, your whole program has to be transformed to return promises-for-values instead of values anywhere it would block."
(Or lifted into a monad).
To me, that's the big issue with a lot of the concurrency/react abstractions en-vogue now: you are programming indirectly, or more precisely you are programming in a specific (async) architectural style, but trying to express this in a call/return architectural style (that includes methods and FP functions).
Depending on where you are, that often means your actual domain code is hidden inside a lot of maps() or flatMaps(). The first problem is that your domain code really should be primary, and your architectural support code as hidden as possible. The second (but probably not last) problem is that you can easily have multiple of these "lifts", for example another for error handling with Maybe. At some point, it just piles up and the actual domain code is completely swamped.
async/await is sort of the high (or low depending on your POV) point of this approach of mapping other architectural styles to call/return: you just write your code as normal call/return, with normal control flow, and just two little annotations lift everything to a completely different architectural style.
On the one hand, it is truly brilliant, hiding almost all the mechanics of the more asynchronous architectural style so that you can just keep writing procedural code as is. On the other hand, maybe it would be better to make it easier to express those alternate architectural styles directly in code.
This seems like another great move in the direction of the latter.
That's my problem with most scheme implementations, they are great for single-threaded concurrency but require nasty hacks like Racket's 'places' for using all available CPU cores. The only fast multicore scheme I'm aware of is Chez, which has other problems, though.
Does Guile do better than Racket with that respect?
This one. I've read about various efforts over the years like this one (https://wingolog.org/archives/2009/02/22/ecmascript-for-guil...) for javascript and others for python etc.
>Why would you want to run Guile if you don't like Lisp?
It's the nicest way to embed a high level language in a program I've come across this tutorial is really cool (https://www.gnu.org/software/guile/docs/guile-tut/tutorial.h...). Other there any others that are so simple?
I think the Lua language itself is designed for the implementation to be easy to embed.
I'm not sure where that came from. Lisp advocates are (perhaps stereotypically more than in reality) known for citing that since any language can supposedly be easily expressed in Lisp, why isn't everyone running everything in Lisp and simply using hypothetical Lisp front ends to their language of choice? This line of reasoning featured heavily in Internet discussions about Guile in the '90s. "Guile should be the universal extension language because Guile can be any language" was a very common perception, at least among many vocal Guile advocates.
In the last decade or so, I have not heard much along these lines WRT Guile. But in the '90s the idea that "every language can be a Guile front-end" was very much front and center in many stupid, pointless flamewars about why everyone should drop what they're doing and use Guile for everything.
Just to be clear, I like Lisp very very much (and Scheme, and Guile), I'm just super allergic to hyperbole, tribalism, and wishful thinking.
Ironically, thanks to Web Assembly, etc., Javascript may turn into the universal backend language that Guile always claimed to be. This is ironic because I don't think even the staunchest Javascript advocates would argue that Javascript is a better language than Scheme in any sort of idealistic, ivory tower sort of totally objective sense.
Javascript isn't everywhere because everyone wants to use it, rather Javascript is everywhere because Javascript is everywhere, so that's what everyone uses. Javascript is the programming language equivalent of people who are famous for being famous. It has many admirable and interesting qualities, but it was very much a language born out of necessity than design, that lives on because it was in the right place at the right time. I say that not as a Javascript hater (I'm not) but rather as an aspiring language historian.
Would WebAssembly boost JavaScript's value as a "backend language" (I assume you mean a compiler target, rather than a server-side language?)?
I thought the point of WebAssembly was to stop people compiling to JS, by offering an alternative standard language/bytecode which is specifically designed to be a compiler target, rather than a human readable/writable language.
Also, what is it that you find so repulsive about Lisps?
I suppose that might not help since you "hate lisp", but Emacs Lisp is actually very different from Scheme. In many ways I'd say Emacs Lisp is actually closer to scripting languages like Python or PHP than it is to Scheme, since it has all of those classic Worse Is Better anti-features common to scripting languages from the 80s and 90s: dependence on imperative execution order, heavy reliance on side-effects, emphasising mutation over copying, making awkward distinctions between named and anonymous functions (it's a "2-lisp"), very poor encapsulation and modularity, extensive support for, and use of, monkey-patching, etc.
If you only "hate lisp" due to s-expression syntax, then keep in mind that the best feature of s-expressions is how easy they are to generate programmatically, e.g. from alternative syntaxes, such as
http://srfi.schemers.org/srfi-49/srfi-49.html
http://breuleux.net/blog/liso.html
http://lambda-the-ultimate.org/node/1646
https://en.wikipedia.org/wiki/M-expression
http://readable.sourceforge.net/
When a fiber would block, it suspends to the scheduler from the current thread. The scheduler will arrange to re-start the fiber when the port or channel becomes readable or writable, as appropriate. For ports, the scheduler adds the file descriptor associated with the port to an epoll set. In either case, the scheduler remembers which fibers are waiting and for what, so that the user can inspect the state of their system.
If no scheduler has been installed in the current thread, the fiber will... well, we don’t know yet! Either it blocks its thread, or it aborts. We don’t know.
In fact it is pretty clear there is zero control user has over any scheduling activity other than suspending and resuming. It is all driven by polling events internal to the implementation.