10 ways GNU Guile is 10x better

#4 will shock you! :-)

In Rust at Facebook by Fitzhardinge of the Mercurial team, Jeremy says that a new language must be 10x better at something than one of the (other) incumbent languages.

So I asked on IRC: what’s the 10x advantage of Guile?

This is not „which Scheme to choose“ (aside from one specific feature). For that question, see the opinionated guide to scheme implementations. For Guile's 10x advantages (some due to being Scheme), read on.

PDF (drucken)

1. powerful core

Macros (define-syntax) and delimited continuations enable creation of high level concepts like fibers without having to change the core.

Thanks to the efficient compiler, there is rarely a need to use macros for performance instead of for semantics, so your code stays cleaner.

thanks to stis.

“Delimited continuations are superior to Python's yield, the macrology is superior to any language except Scheme, the hackability is better then essentially all closed sorurce solutions of program languages.

And the efficient inlining of lambdas is perhaps matched by C, but not many higher languages. The design of Scheme really shines here compared to e.g. Python.” — stis who is building Python on Guile

2. runtime introspection and modification

Compared to C and Go, runtime access to running code is very useful. You can jump into a module and modify anything during runtime.

thanks to str1ngs for this point.

While you even get a subset of this with Java using incremental compilation and hot reloading of code in IntelliJ, at work we’re always dancing around changes that change some method arguments or streams, because those break hot reloading so you have to restart.

And for Javascript we can in theory replace every function, but in practice at work we transpile everything with babel and webpack and that breaks hot reloading, so we have to reload after every change.

In Guile you can either start in a REPL, or create a dedicated REPL in the running program, or create a REPL socket for your development environment and connect to that to hack on the running server.

Then you can re-define all top-level definitions in all modules.

As example str1ngs usually develops the Nomad web browser like that.

And if you need a game loop as main thread, you can use it to drive the cooperative repl server.

3. s-expressions and homoiconicity

Compared to non-lisp languages, the regularity of s-expressions and being able to treat code as data and the other way round (homoiconicity) is a big advantage.

thanks to pinoaffe for this point.

This is an essential elegance I want to conserve in wisp.

Wikipedia notes as advantage that

extending the language with new concepts typically becomes simpler, as data representing code can be passed between the meta and base layer of the program. — Homoiconicity: Uses and Advantages


It can be much easier to understand how to manipulate the code since it can be more easily understood as simple data (since the format of the language itself is a data format). — Homoiconicity: Uses and Advantages

For Wisp I use this a lot, because it allows me to do a first simple pass over the code, add incremental improvements and finally have the cleaned up code that I can pass to the language spec definition:

define : wisp-scheme-read-chunk port
         . "Read and parse one chunk of wisp-code"
     let : :  lines : wisp-scheme-read-chunk-lines port
                    wisp-scheme-indentation-to-parens lines

Also this enables me to write a Question-Asking macro for dryads wake without going totally insane. Usage:

    : new game
    : load game
    : show prologue
      ,(prologue) ,(welcome-screen)
    : exit
      We hope you enjoyed our game!


define-syntax-rule : Choose . choices
   . "Ask questions, apply consequences"
     say-lines : ("") ;; newline before question
     let loop :
       ;; Get the response via the Ask macro 
       ;; to evaluate inline-code incrementally
       define resp : string->number : Ask choices
           : equal? resp 1
             Respond1 choices
           : equal? resp 2
             Respond2 choices
           : equal? resp 3
             Respond3 choices
           : equal? resp 4
             Respond4 choices
           : equal? resp 5
             Respond5 choices
           : equal? resp 6
             Respond6 choices
             . #f

4. interfacing with C and access from C

Most of Guile procedures can be called from C (for example when embedding Guile) and it is easy to interoperate with C from Guile Scheme.

thanks to str1ngs for this points, too.

I did not embed Guile in a C-program myself yet, but Guile provides detailed examples and tutorials for this in its Documentation, with C interfaces explicitly documented for most of its procedures.

This is the shocking number 4: Guile is better for writing C-Programs than C itself. Consider yourself shocked :-) — and no, this argumentation is not complete. But if you’re here, the title led you here. #legitbait.

If you want to be seriously shocked, look at c-indent. Yes, THAT is Guile.

5. fibers

Fibers provide lightweight threads in Guile without having to change anything in the core of Guile. They are reasonably performant and provide concurrency as with Go-channels.

thanks to stis for this point.

With the name giving fibers and channels they provide an efficient and scalable model for coordinated concurrency. See the manual for details.

You can test their raw efficiency using either the webserver-benchmark or the guile-fibers entry in the skynet benchmark.

fibers is better than kludges like marking procedures and what not and it is matched by very few languages. — stis

6. embedded natural script writing

For me, one 10x advantage over every other language is that I could integrate wisp and get an embedded script writing language for dryads wake (as embedded domain specific language eDSL). There’s a talk that compares this to other approaches (including ones I tried before): Natural script writing with Guile. Here’s a real example:

define : first-encounter
    Enter : Juli Fin :profile juli
            Melter Lark :profile melter
            Rooted Breeze :profile dryad
            Old One

        Please choose your name
    game-state-name-set! : read-line
    game-state-id-set! : name->id : game-state-name
    game-state-scene-set! first-encounter
    save-state : game-state-id
        Welcome ,(string-append (game-state-name) "!")

    Juli Fin
        Finally we have our own home!

    Melter Lark
        It took long enough.

    Juli Fin
        And it is moist for sure.

    Melter Lark
        I will dry it out.

    Rooted Breeze :eerie
        My slumber breaks
        my mind awakes
        who are you strangers
        in my home?

    Old One
        How do you answer?
        Juli is ,(score->description (profile-ability-score (game-state) 'juli 'explain))
            . at explaining
        and ,(score->description (profile-ability-score (game-state) 'juli 'fast-talk))
            . at fast-talk.
        : explain your situation to appease the dryad
        : fast-talk the dryad to get her to leave and risk her anger

7. hackability

The language tower and infrastructure make it enjoyable to hack on and extend Guile itself.

thanks to stis for this point.

language tower and effective syntax extensions (define-syntax, etc.) - without that, lokke might well not exist (such as it is), at least not by now. — rlb (lokke is Clojure on top of Guile)

8. complete info-manual

Guile comes with a complete and very readable manual in info-format. If you’ve ever tried to program Python without internet access (or just without Google), you’ll know to deeply appreciate this.

You can find most answers by running

info guile

in the shell, or calling

C-h i m Guile Reference

in Emacs and starting a full-text search with C-s {search terms} C-s.

9. prototyping and creativity

Compared to Python and C++ Guile removes barriers to abstraction. This is also possible with R, but Guile provides good enough performance for these abstractions to make them practical to use.

The low startup time helps for this, too.

thanks to vijaymarupudi for this point.

“Guile is particularly great for prototyping and creativity, and its performance allows for such experiments to be deployed to the world with minimal changes.

I've been using it a lot lately for data cleaning and modeling, and it's been great” — vijaymarupudi

10. lots of fun

Hacking in Guile/Scheme is just lots of fun.

thanks to dsmith for this. Even though this sounds small and gets only a single line in this article, looking at the enthusiasm of people who hack on Guix shows that dsmith clearly has a point!

11. More 10x advantages

After I wrote this article, people noted more advantages. I might work them into the article sometime later, but for now they live here:

  • named lets, I could be without map reduce and all that, just let me have a named let construct — stis
  • python-on-guile has copyable generators and yield as an actual function that can be passed to other functions — stis writing about Python on Guile
  • Purely Functional Datastructures and fectors.

ArneBab 2021-08-25 Mi 00:00 - Impressum - GPLv3 or later (code), cc by-sa (rest)