<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Red Nose Hacker</title>
    <description>The latest articles on DEV Community by Red Nose Hacker (@jeremykorwin).</description>
    <link>https://dev.to/jeremykorwin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F459049%2Fe7b51724-7ede-4f6a-b6c3-d2dd7a08b249.jpg</url>
      <title>DEV Community: Red Nose Hacker</title>
      <link>https://dev.to/jeremykorwin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jeremykorwin"/>
    <language>en</language>
    <item>
      <title>First steps toward Guix Home</title>
      <dc:creator>Red Nose Hacker</dc:creator>
      <pubDate>Sat, 12 Nov 2022 14:20:55 +0000</pubDate>
      <link>https://dev.to/jeremykorwin/first-steps-toward-guix-home-3daa</link>
      <guid>https://dev.to/jeremykorwin/first-steps-toward-guix-home-3daa</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hPMG9u4N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://guix.gnu.org/static/base/img/Guix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hPMG9u4N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://guix.gnu.org/static/base/img/Guix.png" alt="Guix logo" width="200" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, I will show you, step by step, how one can simply install and configure software they use with &lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html"&gt;Guix Home&lt;/a&gt;. For the demonstration, I will focus on a single package and a single service.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I'm not an experienced &lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html"&gt;Guix Home&lt;/a&gt; user. So don't take my words for granted. Read manuals, ask questions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So far, to install a software, say Emacs, for my user, I could simply :&lt;br&gt;
&lt;code&gt;$ guix install emacs&lt;/code&gt;&lt;br&gt;
Or, I could write a manifest and use it to populate my default user profile (or a custom one) :&lt;br&gt;
&lt;code&gt;$ guix package --manifest=$HOME/manifest.scm&lt;/code&gt;&lt;br&gt;
Where &lt;code&gt;manifest.scm&lt;/code&gt; contains the following :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;specifications-&amp;gt;manifest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="s"&gt;"emacs"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the configuration for the new software had to be edited separately.&lt;br&gt;
Here is a dummy &lt;code&gt;~/.config/emacs/init.el&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;initial-scratch-message&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's use &lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html"&gt;Guix Home&lt;/a&gt; to start managing the whole !&lt;/p&gt;

&lt;h2&gt;
  
  
  The blank home
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html"&gt;Guix Home&lt;/a&gt; ask you for two things : a list of packages and a list of home services.&lt;br&gt;
So a blank &lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html"&gt;Guix Home&lt;/a&gt; configuration file (which installs and configures nothing) would look like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-modules&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gnu&lt;/span&gt; &lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;home-environment&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;services&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can save this expressions in a file named &lt;code&gt;home-configuration.scm&lt;/code&gt;. So you now can invoke &lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html"&gt;Guix Home&lt;/a&gt; to generate a home environment from this blank configuration :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ guix home container home-configuration.scm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No worries, this won't affect your current environment. &lt;br&gt;
Take a few seconds to see how empty this shell is and move on !&lt;/p&gt;

&lt;p&gt;Oops, you need to leave the empty shell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing the software
&lt;/h2&gt;

&lt;p&gt;To tell &lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html"&gt;Guix Home&lt;/a&gt; to add a software package to the generated home environment, you have to edit &lt;code&gt;home-configuration.scm&lt;/code&gt; and add its name to the package list :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-modules&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gnu&lt;/span&gt; &lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gnu&lt;/span&gt; &lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="nv"&gt;emacs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;home-environment&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;packages&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;emacs&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now try it out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ guix home container home-configuration.scm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this shell, you can run Emacs, proof that Emacs has been added to the generated home environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ emacs -nw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can quit the shell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the software's configuration
&lt;/h2&gt;

&lt;p&gt;From &lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html"&gt;Guix Home&lt;/a&gt; perspective, things are packages or services. It's time to look for services. Especially one that can handle the process to configure Emacs. Simply put, a service capable of installing the &lt;code&gt;init.el&lt;/code&gt; file on the right place : &lt;code&gt;home-xdg-configuration-files-service-type&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;home-configuration.scm&lt;/code&gt; to be like :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-modules&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gnu&lt;/span&gt; &lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gnu&lt;/span&gt; &lt;span class="nv"&gt;home&lt;/span&gt; &lt;span class="nv"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gnu&lt;/span&gt; &lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="nv"&gt;emacs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gnu&lt;/span&gt; &lt;span class="nv"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;guix&lt;/span&gt; &lt;span class="nv"&gt;gexp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;home-environment&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;packages&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="nv"&gt;emacs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;services&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;service&lt;/span&gt; &lt;span class="nv"&gt;home-xdg-configuration-files-service-type&lt;/span&gt;
         &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"emacs/init.el"&lt;/span&gt; &lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;local-file&lt;/span&gt; &lt;span class="s"&gt;"init.el"&lt;/span&gt;&lt;span class="p"&gt;)))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a &lt;code&gt;init.el&lt;/code&gt; file, with your Emacs configuration, next to the &lt;code&gt;home-configuration.scm&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;initial-scratch-message&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try it with :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ guix home container home-configuration.scm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you can see there is the &lt;code&gt;init.el&lt;/code&gt; file at &lt;code&gt;~/.config/emacs/init.el&lt;/code&gt; !&lt;br&gt;
So the Emacs in this environment will use this configuration file at startup… Ok, maybe not in the container, but trust me, it will when running (careful, it will have an effect to your current environment this time) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ guix home reconfigure home-configuration.scm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Warning :&lt;/strong&gt; because there is no shell configuration in the &lt;code&gt;home-configuration.scm&lt;/code&gt; (yet), you will need to &lt;a href="https://guix.gnu.org/manual/devel/en/html_node/Configuring-the-Shell.html"&gt;manually configure&lt;/a&gt; your shell to make it benefits from the generated home environment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thank you very much for reading this article!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't hesitate to give me your opinion, suggest an idea for improvement, report an error, or ask a question ! I would be so glad to discuss about the topic covered here with you ! You can reach me &lt;a href="https://linktr.ee/jeko"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't miss out on the next ones ! Either via &lt;a href="https://rednosehacker.com/feed/"&gt;RSS&lt;/a&gt; or via e-mail !&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And more importantly, share this blog and tell your friends why they should read this post!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gnu</category>
      <category>guix</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Send an SMS with Guile and Twilio API</title>
      <dc:creator>Red Nose Hacker</dc:creator>
      <pubDate>Mon, 13 Dec 2021 20:36:29 +0000</pubDate>
      <link>https://dev.to/jeremykorwin/send-an-sms-with-guile-and-twilio-api-4eba</link>
      <guid>https://dev.to/jeremykorwin/send-an-sms-with-guile-and-twilio-api-4eba</guid>
      <description>&lt;p&gt;These last days, I tried to send an SMS with a Guile script.&lt;br&gt;
TL;DR: I succeeded!&lt;/p&gt;

&lt;p&gt;Since the code is just a simple HTTP POST request, the longest part should have been the creation of the Twilio account (with a Regulatory Bundle and a phone number).&lt;/p&gt;

&lt;p&gt;But in the end, it took me about one evening[1] to set up a development environment with the right dependencies, and then two more evenings to figure out which HTTP headers were needed.&lt;/p&gt;

&lt;p&gt;Anyway, here is the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="c1"&gt;;; send-happiness.scm&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-modules&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;web&lt;/span&gt; &lt;span class="nv"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;web&lt;/span&gt; &lt;span class="nv"&gt;http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ice-9&lt;/span&gt; &lt;span class="nv"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ice-9&lt;/span&gt; &lt;span class="nv"&gt;iconv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;gcrypt&lt;/span&gt; &lt;span class="nv"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;TWILIO_ACCOUNT_SID&lt;/span&gt; &lt;span class="s"&gt;"your-account-sid"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;TWILIO_ACCOUNT_TOKEN&lt;/span&gt; &lt;span class="s"&gt;"your-account-token"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;TWILIO_PHONE_NUMBER&lt;/span&gt; &lt;span class="s"&gt;"your-twilio-phone-number"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;TWILIO_CREDENTIALS&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;base64-encode&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;string-&amp;gt;bytevector&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;simple-format&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt; &lt;span class="s"&gt;"~A:~A"&lt;/span&gt; &lt;span class="nv"&gt;TWILIO_ACCOUNT_SID&lt;/span&gt; &lt;span class="nv"&gt;TWILIO_ACCOUNT_TOKEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;RECIPIENT_PHONE_NUMBER&lt;/span&gt; &lt;span class="s"&gt;"a-phone-number"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;TEXT_MESSAGE&lt;/span&gt; &lt;span class="s"&gt;"Wish you so much happyness !"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;http-post&lt;/span&gt;
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;simple-format&lt;/span&gt;
  &lt;span class="no"&gt;#f&lt;/span&gt; 
  &lt;span class="s"&gt;"https://api.twilio.com/2010-04-01/Accounts/~A/Messages"&lt;/span&gt;
  &lt;span class="nv"&gt;TWILIO_ACCOUNT_SID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:headers&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;content-type&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;application/x-www-form-urlencoded&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;charset&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;authorization&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;basic&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;TWILIO_CREDENTIALS&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
 &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:body&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;simple-format&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt; &lt;span class="s"&gt;"Body=~A&amp;amp;To=~A&amp;amp;From=~A"&lt;/span&gt;
                       &lt;span class="nv"&gt;TEXT_MESSAGE&lt;/span&gt;
                       &lt;span class="nv"&gt;RECIPIENT_PHONE_NUMBER&lt;/span&gt;
                       &lt;span class="nv"&gt;TWILIO_PHONE_NUMBER&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And how to execute it :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ guix shell guile gnutls guile-gcrypt -- guile send-happiness.scm&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;All phone numbers must start with the country indicator. For example +33 for a French number.&lt;/p&gt;

&lt;p&gt;[1] the time unit of my Guile tinkering&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thank you very much for reading this article!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't hesitate to give me your opinion, suggest an idea for improvement, or ask a question! To do so : contact me.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't miss out on the next ones...&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;articles via Mastodon @&lt;a href="mailto:jeko@write.as"&gt;jeko@write.as&lt;/a&gt; and RSS&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;screencasts via Peertube &lt;a href="mailto:jeko@video.tedomum.net"&gt;jeko@video.tedomum.net&lt;/a&gt; and RSS&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;And more importantly, share this blog and tell your friends it's the best blog in the history of Free Software! No kidding!&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Code Kata with SRFI-64</title>
      <dc:creator>Red Nose Hacker</dc:creator>
      <pubDate>Wed, 07 Oct 2020 16:34:31 +0000</pubDate>
      <link>https://dev.to/jeremykorwin/code-kata-with-srfi-64-285p</link>
      <guid>https://dev.to/jeremykorwin/code-kata-with-srfi-64-285p</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uH3lAPEV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fxrf0fd45bxu9zztv6yx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uH3lAPEV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fxrf0fd45bxu9zztv6yx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I got into the habit of doing about 30 minutes of Code Kata every morning. I practice these Kata following the test-driven development (TDD) approach.&lt;/p&gt;

&lt;p&gt;Guile distribution includes the SRFI-64 module: a unit testing framework. In this article, I explain how to use it and how to configure it in order to practice code kata.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic usage
&lt;/h2&gt;

&lt;p&gt;The SRFI-64 module has a default configuration. Let me show you what it looks like here.&lt;/p&gt;

&lt;p&gt;Below is a Guile program that creates a test suite with only one test (doomed to fail) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-modules&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;srfi&lt;/span&gt; &lt;span class="nv"&gt;srfi-64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-begin&lt;/span&gt; &lt;span class="s"&gt;"demo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt; &lt;span class="s"&gt;"Hookup"&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-end&lt;/span&gt; &lt;span class="s"&gt;"demo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Explanation of the program :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;line 1 : load the module named (srfi srfi-64).&lt;/li&gt;
&lt;li&gt;line 2 : indicate the beginning of the test group demo.&lt;/li&gt;
&lt;li&gt;line 3: define a test, named “Hookup”, with the procedure test-equal whose first parameter is the result expected by the test (here, #t ) and the second parameter is the tested expression (here, #t).&lt;/li&gt;
&lt;li&gt;line 4: indicate the end of the &lt;code&gt;demo&lt;/code&gt; test group.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is relatively simple, there are few frills.&lt;/p&gt;

&lt;p&gt;This is the result of the execution of this suite if you save it in a /tmp/tests.scm file and execute the :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ guile --no-auto-compile test.scm 
%%%% Starting test demo (Writing full log to "demo.log")
/tmp/test.scm:3: FAIL Hookup
# of unexpected failures 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The console displays only a summary of the result: line 3 shows an unexpected failure from the “Hookup” test. It's very brief but it gives a quick idea of the state of the program.&lt;/p&gt;

&lt;p&gt;The complete detail is in the /tmp/demo.log file:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat demo.log
%%%% Starting test demo
Group begin: demo
Test begin:
  test-name: "Hookup"
  source-file: "/tmp/test.scm".
  source-line: 3
  source-form: (test-equal "Hookup" #f #t)
Test end:
  result-kind: fail
  actual-value: #t
  expected-value: #f
Group end: demo
# of unexpected failures 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This report gives me two pieces of information that I use a lot : &lt;code&gt;actual-value&lt;/code&gt; and &lt;code&gt;expected-value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This default configuration, although ready to use, has the disadvantage of providing informations in two places : in the console (list of tests and their states) and in a file (test results). Not very practical...&lt;/p&gt;

&lt;p&gt;Fortunately, the test framework is easily configurable. In the following article, I present you my configuration dedicated to code kata.&lt;/p&gt;

&lt;p&gt;Configuration for Code Kata&lt;/p&gt;

&lt;p&gt;The idea here is to configure the SRFI-64 module to display all the information I need directly in the console (and I don't need to report in a file). I want to see at a glance :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the list of executed tests ;&lt;/li&gt;
&lt;li&gt;the status of each of these tests;&lt;/li&gt;
&lt;li&gt;for failed tests, display the expected value and the value obtained.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;According to the SRFI-64 reference, the objects that maintain the statistics on the test suite (total number of tests, number of successful, failed, passed, ...) are the test-runners.&lt;/p&gt;

&lt;p&gt;Thanks to the section Writing a new test-runner and some examples gleaned from the web, you should be able to create the test-runner that suits you!&lt;/p&gt;

&lt;p&gt;Here is the one I made for myself (based on the work of Mathieu Lirzin and Alex Sassmannshausen) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="c1"&gt;;;;; kata-driver.scm - Guile test driver for code kata practice&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="nv"&gt;script-version&lt;/span&gt; &lt;span class="s"&gt;"2020-10-04"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;;UTC&lt;/span&gt;

&lt;span class="c1"&gt;;;; Copyright © 2015, 2016 Mathieu Lirzin &amp;lt;mthl@gnu.org&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;;;; Copyright © 2019 Alex Sassmannshausen &amp;lt;alex@pompo.co&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;;;; Copyright © 2019 Jérémy Korwin-Zmijowski &amp;lt;jeremy@korwin-zmijowski.fr&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;;;;&lt;/span&gt;
&lt;span class="c1"&gt;;;; This program is free software; you can redistribute it and/or modify it&lt;/span&gt;
&lt;span class="c1"&gt;;;; under the terms of the GNU General Public License as published by&lt;/span&gt;
&lt;span class="c1"&gt;;;; the Free Software Foundation; either version 3 of the License, or (at&lt;/span&gt;
&lt;span class="c1"&gt;;;; your option) any later version.&lt;/span&gt;
&lt;span class="c1"&gt;;;;&lt;/span&gt;
&lt;span class="c1"&gt;;;; This program is distributed in the hope that it will be useful, but&lt;/span&gt;
&lt;span class="c1"&gt;;;; WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/span&gt;
&lt;span class="c1"&gt;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;/span&gt;
&lt;span class="c1"&gt;;;; GNU General Public License for more details.&lt;/span&gt;
&lt;span class="c1"&gt;;;;&lt;/span&gt;
&lt;span class="c1"&gt;;;; You should have received a copy of the GNU General Public License&lt;/span&gt;
&lt;span class="c1"&gt;;;; along with this program.  If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;/span&gt;

&lt;span class="c1"&gt;;;;; Commentary:&lt;/span&gt;
&lt;span class="c1"&gt;;;;&lt;/span&gt;
&lt;span class="c1"&gt;;;; This script provides a Guile test driver using the SRFI-64 Scheme API for&lt;/span&gt;
&lt;span class="c1"&gt;;;; test suites.  SRFI-64 is distributed with Guile since version 2.0.9.&lt;/span&gt;
&lt;span class="c1"&gt;;;;&lt;/span&gt;
&lt;span class="c1"&gt;;;; This script is a very cleaned up version of the Alex Sassmannshausen 's &lt;/span&gt;
&lt;span class="c1"&gt;;;; version. The changes make it suitable for use in a code kata practice.&lt;/span&gt;
&lt;span class="c1"&gt;;;;&lt;/span&gt;
&lt;span class="c1"&gt;;;;; Code:&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define-module&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;runner-kata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:export&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-runner-kata&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-modules&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;srfi&lt;/span&gt; &lt;span class="nv"&gt;srfi-64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ice-9&lt;/span&gt; &lt;span class="nv"&gt;pretty-print&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;srfi&lt;/span&gt; &lt;span class="nv"&gt;srfi-26&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-display&lt;/span&gt; &lt;span class="nv"&gt;field&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt;  &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:optional&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;port&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;current-output-port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                       &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:key&lt;/span&gt; &lt;span class="nv"&gt;pretty?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s"&gt;"Display 'FIELD: VALUE\n' on PORT."&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;pretty?&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;port&lt;/span&gt; &lt;span class="s"&gt;"~A:~%"&lt;/span&gt; &lt;span class="nv"&gt;field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pretty-print&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt; &lt;span class="nv"&gt;port&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:per-line-prefix&lt;/span&gt; &lt;span class="s"&gt;"+ "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;port&lt;/span&gt; &lt;span class="s"&gt;"~A: ~S~%"&lt;/span&gt; &lt;span class="nv"&gt;field&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result-&amp;gt;string&lt;/span&gt; &lt;span class="nv"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s"&gt;"Return SYMBOL as an upper case string.  Use colors when COLORIZE is #t."&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;string-upcase&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;symbol-&amp;gt;string&lt;/span&gt; &lt;span class="nv"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string-append&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;symbol&lt;/span&gt;
                     &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;;green&lt;/span&gt;
                     &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;xfail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;;light green&lt;/span&gt;
                     &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;;blue&lt;/span&gt;
                     &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;fail&lt;/span&gt; &lt;span class="nv"&gt;xpass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;;red&lt;/span&gt;
                     &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;;magenta&lt;/span&gt;
                   &lt;span class="nv"&gt;result&lt;/span&gt;
                   &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;define*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-runner-kata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-on-test-end-kata&lt;/span&gt; &lt;span class="nv"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let*&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;results&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-result-alist&lt;/span&gt; &lt;span class="nv"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cut&lt;/span&gt; &lt;span class="nv"&gt;assq&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;results&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
           &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cut&lt;/span&gt; &lt;span class="nv"&gt;assq-ref&lt;/span&gt; &lt;span class="nv"&gt;results&lt;/span&gt; &lt;span class="nv"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;equal?&lt;/span&gt; &lt;span class="ss"&gt;'fail&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="ss"&gt;'result-kind&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;newline&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="s"&gt;"~a ~A~%"&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result-&amp;gt;string&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="ss"&gt;'result-kind&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="ss"&gt;'test-name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result?&lt;/span&gt; &lt;span class="ss"&gt;'expected-value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-display&lt;/span&gt; &lt;span class="s"&gt;"expected-value"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="ss"&gt;'expected-value&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result?&lt;/span&gt; &lt;span class="ss"&gt;'expected-error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-display&lt;/span&gt; &lt;span class="s"&gt;"expected-error"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="ss"&gt;'expected-error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:pretty?&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result?&lt;/span&gt; &lt;span class="ss"&gt;'actual-value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-display&lt;/span&gt; &lt;span class="s"&gt;"actual-value"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="ss"&gt;'actual-value&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;newline&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="s"&gt;"~a ~A~%"&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result-&amp;gt;string&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="ss"&gt;'result-kind&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt; &lt;span class="ss"&gt;'test-name&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;

  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;runner&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-runner-null&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-runner-on-test-end!&lt;/span&gt; &lt;span class="nv"&gt;runner&lt;/span&gt; &lt;span class="nv"&gt;test-on-test-end-kata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I created a git repository which contains a project template for a code kata. Just follow the README instructions and code !&lt;/p&gt;

&lt;p&gt;Here is an example of feedback from your terminal while the watch.sh script is running :&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FAIL Hookup
expected-value: #f
actual-value: #t
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;No more need to look at the content of the report (which is no longer generated) to find out what the problem is. So I can execute this script in a dedicated emacs buffer, every time I save, and act according to the test results.&lt;/p&gt;

&lt;p&gt;Now it's up to you!&lt;/p&gt;

&lt;p&gt;Choose a code kata exercise, work on it for about 30 minutes, share the link to your code and your tests in comments below!&lt;/p&gt;

&lt;p&gt;Then, I give you my 2 cents for your next session!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Thank you so much for reading this article!&lt;/p&gt;

&lt;p&gt;Don't hesitate to give me your opinion or ask a question !&lt;br&gt;
To do so, please leave a comment below or &lt;a href="https://linktr.ee/jeko"&gt;contact me&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And most importantly, share the blog and tell your friends it's the best blog in the history of Free Software! No shit!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>guile</category>
      <category>scheme</category>
      <category>kata</category>
      <category>tdd</category>
    </item>
    <item>
      <title>Learning Guile - Booleans</title>
      <dc:creator>Red Nose Hacker</dc:creator>
      <pubDate>Sun, 13 Sep 2020 21:29:27 +0000</pubDate>
      <link>https://dev.to/jeremykorwin/learning-guile-booleans-18d8</link>
      <guid>https://dev.to/jeremykorwin/learning-guile-booleans-18d8</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xA5NzuO9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/GNU-Guile-logo.svg/220px-GNU-Guile-logo.svg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xA5NzuO9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/GNU-Guile-logo.svg/220px-GNU-Guile-logo.svg.png" alt="Guile Logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two boolean values are: "true" and "false". Respectively &lt;code&gt;#t&lt;/code&gt; or &lt;code&gt;#true&lt;/code&gt; and &lt;code&gt;#f&lt;/code&gt; or &lt;code&gt;#false&lt;/code&gt; in Guile.&lt;/p&gt;

&lt;p&gt;In a conditional test context, "true" means any expression other than &lt;code&gt;#f&lt;/code&gt; or &lt;code&gt;#false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is a small test suite that illustrates all this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-modules&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;srfi&lt;/span&gt; &lt;span class="nv"&gt;srfi-64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-begin&lt;/span&gt; &lt;span class="s"&gt;"test-suite"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-equal&lt;/span&gt; &lt;span class="s"&gt;"Truth"&lt;/span&gt;
  &lt;span class="no"&gt;#t&lt;/span&gt;
  &lt;span class="no"&gt;#t&lt;/span&gt;&lt;span class="nv"&gt;rue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-equal&lt;/span&gt; &lt;span class="s"&gt;"Falsness"&lt;/span&gt;
  &lt;span class="no"&gt;#f&lt;/span&gt;
  &lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="nv"&gt;alse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-equal&lt;/span&gt; &lt;span class="s"&gt;"Numbers are true"&lt;/span&gt;
  &lt;span class="no"&gt;#t&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="mi"&gt;12547&lt;/span&gt;
      &lt;span class="no"&gt;#t&lt;/span&gt;
      &lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-equal&lt;/span&gt; &lt;span class="s"&gt;"Strings are true"&lt;/span&gt;
  &lt;span class="no"&gt;#t&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;"I am not false"&lt;/span&gt;
      &lt;span class="no"&gt;#t&lt;/span&gt;
      &lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-equal&lt;/span&gt; &lt;span class="s"&gt;"Lists - even empty - are true"&lt;/span&gt;
  &lt;span class="no"&gt;#t&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="no"&gt;#t&lt;/span&gt;
      &lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-equal&lt;/span&gt; &lt;span class="s"&gt;"Symbols are not false"&lt;/span&gt;
  &lt;span class="no"&gt;#f&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;not&lt;/span&gt; &lt;span class="ss"&gt;'i-am-not-false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test-end&lt;/span&gt; &lt;span class="s"&gt;"test-suite"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;/tmp/bool.scm&lt;/code&gt; file with the code below. Run the tests and if everything goes well, you should see the following result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ guile bool.scm 
;;;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;; or pass the --no-auto-compile argument to disable.
;;;; compiling /tmp/bool.scm
compiled /home/jeko/.cache/guile/ccache/3.0-LE-8-4.3/tmp/bool.scm.go
%%%% Starting test-suite (Writing full log to "test-suite.log")
# of expected passes 6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you feel like it, you can tweak this file to experiment!&lt;/p&gt;

</description>
      <category>learn</category>
      <category>gnu</category>
      <category>guile</category>
      <category>scheme</category>
    </item>
  </channel>
</rss>
