<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>UNDLTD</title>
    <description>Unless otherwise noted, the content on this site is licensed under &lt;a href=&quot;https://creativecommons.org/licenses/by/4.0/&quot;&gt;Creative Commons Attribution 4.0 International License&lt;/a&gt;.
</description>
    <link>https://xn--w5d.cc/</link>
    <atom:link href="https://xn--w5d.cc/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 18 Dec 2025 21:03:42 +0200</pubDate>
    <lastBuildDate>Thu, 18 Dec 2025 21:03:42 +0200</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Announcing om, a command line mounter for removable devices</title>
        <description>&lt;p&gt;I just published &lt;a href=&quot;https://codeberg.org/undltd/om&quot;&gt;a new opensource project&lt;/a&gt;. It is a small program I wrote to solve an inconvenience I experienced with my computer use:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mounting &amp;amp; unmounting removable devices from command line (on Linux).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here’s an example of using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;om&lt;/code&gt; to mount a recently attached device:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ om
Activate device:

1) /dev/sda1                 My USB                  (12.5G)
2) /dev/mmcblk0              My memory card          (116.5G)

Device [1]: ⏎

/dev/sda1: mounted at `/run/media/user/My USB`.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Most of the time, in order to mount a device, one only needs to type the short command and hit Return. Unmounting is analogously simple.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;https://codeberg.org/undltd/om#usage&quot;&gt;README for more examples&lt;/a&gt;, including encrypted devices and powering off.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Whatever DE I use, I tend to work mostly with the keyboard. So I wanted a short command that would do this for me with as little typing and interaction as possible.&lt;/p&gt;

&lt;p&gt;That includes mounting / unmounting at the right place, unlocking / locking encrypted volumes, as well as doing anything necessary to safely remove the device (powering off when supported, locking encrypted volumes after unmount, unmounting other partitions on the same device if present, etc).&lt;/p&gt;

&lt;p&gt;It uses &lt;a href=&quot;https://www.freedesktop.org/wiki/Software/udisks/&quot;&gt;UDisks&lt;/a&gt; as its backend (but multiple backends can be implemented if desired).&lt;/p&gt;

&lt;p&gt;Before I wrote this tool, I was using &lt;a href=&quot;https://github.com/jamielinux/bashmount&quot;&gt;bashmount&lt;/a&gt;, which provided inspiration, but I wanted something a bit more ergonomic for my day to day use.&lt;/p&gt;

&lt;p&gt;I decided to release it early, as soon as I started using it myself and felt it does the job. If circumstances permit, I’ll be able to add niceties and further smooth out the UX, maybe even add features (see the Roadmap for ideas I have at the moment), but I hope it won’t become “big and professional” 😉 Maybe I can port it to *BSD at some point🤔&lt;/p&gt;

&lt;p&gt;Also, this is my first “real” program in Rust.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;p&gt;(P.S. This program was written during and despite russian war.)&lt;/p&gt;
</description>
        <pubDate>Mon, 18 Nov 2024 00:00:00 +0200</pubDate>
        <link>https://xn--w5d.cc/2024/11/18/announcing-om-mounter.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2024/11/18/announcing-om-mounter.html</guid>
        
        <category>udisks, rust</category>
        
        
        <category>technical</category>
        
      </item>
    
      <item>
        <title>Highlight evaluated SuperCollider code in Emacs</title>
        <description>&lt;p&gt;Someone on the Fediverse asked if it’s possible to have Emacs visually
highlight / flash the fragment of code that is currently evaluated in
SuperCollider (via scel). It is! Here’s the code I use in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init.el&lt;/code&gt;
to implement this, based on some example from some since-forgotten
corner of the Net:&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;undltd/sclang-highlight-defun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;amp;optional&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;silent-p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cl-multiple-value-bind&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beg&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sclang-point-in-defun-p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;beg&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pulse-momentary-highlight-region&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;beg&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;undltd/sclang-highlight-region-or-line&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;amp;optional&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;silent-p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;transient-mark-mode&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mark-active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pulse-momentary-highlight-region&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;region-beginning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;region-end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pulse-momentary-highlight-one-line&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;advice-add&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;sclang-eval-defun&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:before&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#&apos;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;undltd/sclang-highlight-defun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;advice-add&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;sclang-eval-region-or-line&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:before&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#&apos;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;undltd/sclang-highlight-region-or-line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(I tend to prefix all my custom functions with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undltd/&lt;/code&gt; to avoid
potential name clashes with other libraries in the future).&lt;/p&gt;
</description>
        <pubDate>Sun, 28 Jul 2024 00:00:00 +0300</pubDate>
        <link>https://xn--w5d.cc/2024/07/28/supercollider-emacs-highlight-eval.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2024/07/28/supercollider-emacs-highlight-eval.html</guid>
        
        <category>supercollider, emacs</category>
        
        
        <category>technical</category>
        
      </item>
    
      <item>
        <title>HUK MISTA 2.0 @ House of Sound</title>
        <description>&lt;p&gt;An interactive work for House of Sound (&lt;a href=&quot;https://www.facebook.com/DimZvukuLviv&quot;&gt;Дім Звуку&lt;/a&gt;) in Lviv, Ukraine, installed in 2023.&lt;/p&gt;

&lt;p&gt;A joystick-operated 2d soundscape “map” where a visitor “wanders” between sounds, thereby mixing field recordings into a composition of their own.&lt;/p&gt;

&lt;p&gt;Built using the &lt;a href=&quot;https://racket-lang.org/&quot;&gt;beautiful Racket programming language&lt;/a&gt; with the &lt;a href=&quot;https://r-cade.io/&quot;&gt;minimalist r-cade&lt;/a&gt; game engine&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; along with &lt;a href=&quot;https://supercollider.github.io/&quot;&gt;SuperCollider for sound&lt;/a&gt; (communicating over OSC).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Video &amp;amp; photos &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0/&quot;&gt;cc by-sa 4.0&lt;/a&gt; Volodymyr Mysan-Miliasevych.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/photos/huk-mista-2.0-01.jpg&quot;&gt;&lt;img src=&quot;/assets/photos/huk-mista-2.0-01.jpg&quot; alt=&quot;Fragment of a screen, displaying pixelated colored circles on a dotted background, some of the circles are connected by lines (indicated sounds currently being mixed). The central, bigger circle represents the listener.&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/massung/r-cade/commits/main/&quot;&gt;appears to be unmaintained&lt;/a&gt; since some time now 😢 &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 15 Jan 2024 00:00:00 +0200</pubDate>
        <link>https://xn--w5d.cc/2024/01/15/huk-mista-2.0.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2024/01/15/huk-mista-2.0.html</guid>
        
        <category>installation, supercollider, racket, soundscape</category>
        
        
        <category>artistic</category>
        
      </item>
    
      <item>
        <title>Live @ Lviv Art Center</title>
        <description>&lt;p&gt;A meditative ambient performance using livecoding techniques in SuperCollider.&lt;/p&gt;

&lt;p&gt;Performed as part of an artist talk at Lviv Art Palace in 2022.&lt;/p&gt;

&lt;p&gt;The full event recording can be found &lt;a href=&quot;https://www.youtube.com/watch?v=yPDjaIrl87M&quot;&gt;on Lviv Art Center’s youtube channel&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sat, 30 Sep 2023 00:00:00 +0300</pubDate>
        <link>https://xn--w5d.cc/2023/09/30/live-lviv-art-center.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2023/09/30/live-lviv-art-center.html</guid>
        
        <category>supercollider, livecoding</category>
        
        
        <category>artistic</category>
        
      </item>
    
      <item>
        <title>nannou on NixOS</title>
        <description>&lt;p&gt;A very quick note: here’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shell.nix&lt;/code&gt; I use to build a basic &lt;a href=&quot;https://nannou.cc/&quot;&gt;nannou&lt;/a&gt; app on NixOS and run it:&lt;/p&gt;

&lt;div class=&quot;language-nix highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nixpkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mkShell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;buildInputs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;pkg-config&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;cargo&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;rustc&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;xorg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;libxcb&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;xorg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;libX11&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;xorg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;libXcursor&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;xorg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;libXrandr&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;xorg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;libXi&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;alsa-lib&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;vulkan-loader&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;LD_LIBRARY_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;vulkan-loader&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/lib&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With this, I can launch a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nix-shell&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo run&lt;/code&gt; the &lt;a href=&quot;https://guide.nannou.cc/getting_started/create_a_project.html&quot;&gt;example nannou project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LD_LIBRARY_PATH&lt;/code&gt; line is required to make the app find vulkan
libraries at runtime; otherwise it would fail to run with the
following error: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;could not build default app window:
NoAvailableAdapter&lt;/code&gt;).&lt;/p&gt;

</description>
        <pubDate>Sat, 06 Aug 2022 00:00:00 +0300</pubDate>
        <link>https://xn--w5d.cc/2022/08/06/nannou-nixos.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2022/08/06/nannou-nixos.html</guid>
        
        <category>nixos, rust</category>
        
        
        <category>technical</category>
        
      </item>
    
      <item>
        <title>Live audio visualization using ffmpeg</title>
        <description>&lt;p&gt;ffmpeg &lt;a href=&quot;https://lukaprincic.si/development-log/ffmpeg-audio-visualization-tricks&quot;&gt;can turn&lt;/a&gt; audio files into videos with nice
visualizations, for instance displaying a scrolling spectrogram using
the &lt;a href=&quot;https://ffmpeg.org/ffmpeg-filters.html#showspectrum-1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;showspectrum&lt;/code&gt;&lt;/a&gt; filter.&lt;/p&gt;

&lt;p&gt;It turns out you can also use it to do visualization of live audio
signal onto the screen. On Linux I used the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f jack&lt;/code&gt; input option to
route live audio from any jack application into ffmpeg, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f sdl&lt;/code&gt;
output option to display the result as a window on the screen.&lt;/p&gt;

&lt;p&gt;Assuming you have jack server running, you can do:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ffmpeg &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; jack &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; ffmpeg &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-filter_complex&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[0:a]showspectrum=s=1980x500:mode=combined:slide=scroll:fps=30:scale=sqrt:gain=5,format=yuv420p[v]&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-map&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[v]&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; sdl &lt;span class=&quot;s2&quot;&gt;&quot;ffmpeg visualization&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then connect the desired audio signal to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ffmpeg&lt;/code&gt; jack ports and
enjoy. For more elaborate examples of ffmpeg visualizations see &lt;a href=&quot;https://lukaprincic.si/development-log/ffmpeg-audio-visualization-tricks&quot;&gt;Luka Prinčič’s post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/ffmpeg-viz.jpg&quot; alt=&quot;A screen shot displaying three windows: a wide window with spectrogram from ffmpeg, a jack patchbay window (Catia), connecting system ports to ffmpeg, and a terminal window showing the output of ffmpeg.&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Sun, 08 May 2022 00:00:00 +0300</pubDate>
        <link>https://xn--w5d.cc/2022/05/08/ffmpeg-visualization.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2022/05/08/ffmpeg-visualization.html</guid>
        
        <category>audio, visualization</category>
        
        
        <category>technical</category>
        
      </item>
    
      <item>
        <title>Thoughts on Lisp #0: what is code?</title>
        <description>&lt;p&gt;Programming languages are not only tools for commanding computers, but
also for communicating and structuring our own thinking; and they
shape our reasoning about certain problems in their own way.&lt;/p&gt;

&lt;p&gt;In this post I reflect on a few characteristics of Lisp (and
specifically &lt;a href=&quot;https://racket-lang.org/&quot;&gt;Racket&lt;/a&gt;) that capture my mind again and again.&lt;/p&gt;

&lt;h2 id=&quot;syntax-vs-data&quot;&gt;Syntax vs data&lt;/h2&gt;

&lt;p&gt;When I write, say, Python (which is a great language!), I tend to have
this mental image of writing a certain syntax that’s then &lt;em&gt;parsed
into&lt;/em&gt; the actual logical structure (the abstract syntax tree or
&lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_syntax_tree&quot;&gt;AST&lt;/a&gt;) of the program by the interpreter / compiler, similar to
how HTML is translated into the DOM in memory. Of course, I rarely
consciously think about that distinction, but when switching to/from
Racket I notice this nuance. The syntax is just an arbitrary set of
rules to write out the program in this specific form, and &lt;a href=&quot;https://docs.hylang.org/en/alpha/#&quot;&gt;alternative
syntaxes for Python exist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In contrast, when I write Racket, conceptually it feels like I’m
typing out a data structure that represents the algorithm(s) of the
program (very close to the AST). Obviously there are still many
translation steps between the input I provide and the result (a
running program) inside the runtime; but the relationship between the
source code and the actual program is somewhat special.&lt;/p&gt;

&lt;p&gt;The famous parentheses in a Lisp program map directly to its logical
tree-like structure.&lt;/p&gt;

&lt;p&gt;Let’s take a very primitive example:&lt;/p&gt;

&lt;p&gt;Python:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Racket:&lt;/p&gt;
&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expt&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A few things to note in the Racket example:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The computation is directly dictated by the structure of the
expression, delimited by pairs of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(...)&lt;/code&gt;, and not some other
factor like operator precedence - i.e., the way it is written
expresses how it is computed;&lt;/li&gt;
  &lt;li&gt;Most expressions follow the pattern: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&amp;lt;OPERATION&amp;gt; [&amp;lt;ARGUMENT&amp;gt;
...])&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;Arithmetic operators like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expt&lt;/code&gt; are not special syntax
but regular functions: the expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(+ 1 2 3)&lt;/code&gt; means apply the
function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; to arguments &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thus, there is a symmetry in Racket between writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(+ 1 2 3)&lt;/code&gt; and,
say, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(build-path &quot;/&quot; &quot;tmp&quot; &quot;somefolder&quot; &quot;somefile.json&quot;)&lt;/code&gt; - both are
expressions applying functions to values, and returning values.&lt;/p&gt;

&lt;p&gt;Also, just like any function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; can be passed to other function as
an argument. The following expression:&lt;/p&gt;

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;results in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;(10 15 20)&lt;/code&gt;. The single quote before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt; is a shorthand
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(quote ...)&lt;/code&gt; and means that what follows is &lt;em&gt;not&lt;/em&gt; evaluated as a
function call, but returned as a list instead (we will talk about this
more below).&lt;/p&gt;

&lt;h1 id=&quot;code-as-a-tree&quot;&gt;Code as a tree&lt;/h1&gt;

&lt;p&gt;Let’s look at another example, say, computing whether a given number &lt;a href=&quot;http://web.archive.org/web/20210506204804/https://stackoverflow.com/a/2432699&quot;&gt;is a
fibonacci number&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Python:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;math&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isqrt&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_fibonacci&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_integer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;intermediate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# save some repetition
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intermediate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intermediate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Racket:&lt;/p&gt;
&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fibonacci?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cond&lt;/span&gt;                                        &lt;span class=&quot;c1&quot;&gt;; conditional&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;integer?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;; clause&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;intermediate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expt&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;square?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;intermediate&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;square?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;intermediate&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;                                &lt;span class=&quot;c1&quot;&gt;; clause&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;square?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;equal?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expt&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;integer-sqrt&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again, in the Racket program nested parentheses define the “shape” of
the computation. Pairs of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[...]&lt;/code&gt; are syntactically equivalent to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(...)&lt;/code&gt; and used only by convention.&lt;/p&gt;

&lt;p&gt;Conditionals like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cond&lt;/code&gt; (a generalized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;or&lt;/code&gt;, etc,
follow the same pattern: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&amp;lt;OPERATION&amp;gt; &amp;lt;INPUTS&amp;gt;)&lt;/code&gt;, and &lt;em&gt;also&lt;/em&gt; produce
a value. However, specific conditionals have specific shape of their
inputs, for instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cond&lt;/code&gt; takes &lt;a href=&quot;https://docs.racket-lang.org/reference/if.html#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._cond%29%29&quot;&gt;one or more clauses&lt;/a&gt; mapping tests to
values.&lt;/p&gt;

&lt;p&gt;Since conditionals are expressions that evaluate to values, there is
no need for explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; - the evaluated expression &lt;em&gt;is the
value&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(and ...)&lt;/code&gt; tests if none of its subexpressions are false (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#f&lt;/code&gt;) and
returns the value of the last one or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#f&lt;/code&gt; otherwise;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(or ...)&lt;/code&gt; returns the first non-false subexpression or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#f&lt;/code&gt; if
none;&lt;/li&gt;
  &lt;li&gt;and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cond&lt;/code&gt; returns whatever the last expression of the
matching clause returns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Functions return their last (outermost) value.&lt;/p&gt;

&lt;p&gt;Overall, the program looks more like a tree of expressions that
produce values to give the final answer, rather than a chain of
actions or commands. This mental attitude is something I admine in
Lisp.&lt;/p&gt;

&lt;h2 id=&quot;code-as-data-data-as-code&quot;&gt;Code as data, data as code&lt;/h2&gt;

&lt;p&gt;One last bit I’d like to touch on here. The source code in Lisp &lt;em&gt;is
actually&lt;/em&gt; a data structure, not just a particularly shaped long
string.&lt;/p&gt;

&lt;p&gt;For instance, with this command (executed in unix shell):&lt;/p&gt;

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;racket&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…I have just parsed a chunk of source code &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;(+ 1 2 3)&quot;&lt;/code&gt; into data -
a list consisting of the symbol &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; and there numbers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt;, but &lt;em&gt;have not executed it&lt;/em&gt;, just printed it back as data
again. This small data structure can also be executed:&lt;/p&gt;

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;racket&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;what&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;happens&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;normally&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice how, conceptually, it’s not the source code that is executed,
but the data structure - a list of items - that is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; from the
source code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reading is a separate, distinct operation from executing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nothing stops you from doing something with the data before executing
it. For instance, running the following program would produce the
familiar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;hello world&quot;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-program&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; the single quote before the list means `read` that thing&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; as data but do not `eval` it yet.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string-append&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;world&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-program&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reverse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-program&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the above example I reversed all but the first element of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my-program&lt;/code&gt; before executing it.&lt;/p&gt;

&lt;p&gt;Now, this is obviously not what most Lisp programmers would normally
do. But the fact that your program is a data structure changes how you
think about it.&lt;/p&gt;

&lt;p&gt;You can also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; things you don’t plan executing at
all. For instance, you can point the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt;ing machinery of the
interpreter at a configuration file without ever executing what’s
inside, just using it as passive data.&lt;/p&gt;

&lt;p&gt;Nevertheless, writing programs that &lt;em&gt;transfrom themselves&lt;/em&gt; before
being executed is very common in the Racket world, although this is
done in a much cleaner and more declarative way using macros.&lt;/p&gt;

&lt;p&gt;But why, you ask? Because programmers love abstractions and macros
provide a way to abstract out patterns of code that emerge in this or
that specific domain (or accross domains!).&lt;/p&gt;

&lt;p&gt;I’ll end this post with a final example: a quite popular instance of
macro use in Racket, providing a nice way to “pipe” values
sequentially through a chain of operations:&lt;/p&gt;

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;racket&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; selecting the main Racket dialect&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;threading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;~&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;world hello&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string-split&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string-join&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string-append&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;💜&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(~&amp;gt; ...)&lt;/code&gt; fragment actually translates to:&lt;/p&gt;

&lt;div class=&quot;language-racket highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string-append&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string-join&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reverse&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string-split&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;world hello&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;s&quot;&gt;&quot;💜&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&amp;gt;&lt;/code&gt; form is not a language feature or special built-in syntax - it
is a macro coming from a &lt;a href=&quot;https://docs.racket-lang.org/threading/index.html&quot;&gt;a third-party package&lt;/a&gt;. Macros
are Lisp functions that transform Lisp code before it will be executed.&lt;/p&gt;

&lt;p&gt;As you can see, the language allows great creativity and flexibility
in applying itself (code) to itself (data), so to speak.&lt;/p&gt;

&lt;p&gt;(Recursion in general is also practiced quite often by Lispers, but
that is a topic for a dedicated blog post).&lt;/p&gt;

</description>
        <pubDate>Tue, 08 Feb 2022 00:00:00 +0200</pubDate>
        <link>https://xn--w5d.cc/2022/02/08/lisp-what-is-code.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2022/02/08/lisp-what-is-code.html</guid>
        
        <category>lisp</category>
        
        <category>racket</category>
        
        <category>programming meta</category>
        
        
        <category>technical</category>
        
      </item>
    
      <item>
        <title>Live @ Contrasts Festival 2021</title>
        <description>&lt;p&gt;I was invited to perform at the CONTRASTS International Contemporary
Music Festival in Lviv, Ukraine.&lt;/p&gt;

&lt;p&gt;The performance was done in SuperCollider, but with very little live
coding - instead I used a midi controller to manipulate the sound most
of the time. Hence the picture is not very eventful, but I thought I’d
share the screen anyway.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/photos/cntrsts.jpg&quot; alt=&quot;Grayscale photo; person performing sitting in front of a laptop, turning knobs on a midi controller, in a dark concert hall. Empty chairs visible in background. Screen glow light the performer&apos;s face.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Photo &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0/&quot;&gt;cc by-sa 4.0&lt;/a&gt; Danylo Bedriy / Contrasts Festival.&lt;/p&gt;
</description>
        <pubDate>Wed, 13 Oct 2021 00:00:00 +0300</pubDate>
        <link>https://xn--w5d.cc/2021/10/13/cntrsts.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2021/10/13/cntrsts.html</guid>
        
        <category>supercollider</category>
        
        
        <category>artistic</category>
        
      </item>
    
      <item>
        <title>Music for &quot;Відчинені вікна&quot;</title>
        <description>&lt;p&gt;I’m glad to share “&lt;a href=&quot;https://www.youtube.com/watch?v=-u3Kqi8oZCM&quot;&gt;Відчинені вікна&lt;/a&gt;” (“Opened windows”), an art /
poetry film by Olha Povoroznyk and Ostap Slyvynskyi, to which I
composed the music track. The film is published on &lt;a href=&quot;https://www.youtube.com/watch?v=-u3Kqi8oZCM&quot;&gt;youtube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The sound material for the soundtrack is mostly layers of clarinet
multiphonics and “solos”.&lt;/p&gt;

</description>
        <pubDate>Sun, 10 Oct 2021 00:00:00 +0300</pubDate>
        <link>https://xn--w5d.cc/2021/10/10/vidchyneni-vikna.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2021/10/10/vidchyneni-vikna.html</guid>
        
        <category>soundtrack</category>
        
        
        <category>artistic</category>
        
      </item>
    
      <item>
        <title>Sonic memories from MC6</title>
        <description>&lt;p&gt;I was recently invited to join a diverse art-focused gathering at
&lt;a href=&quot;https://drive.google.com/file/d/1ThLwkQA39z3duQXjLPmavKBuX0Iyt8i1/view&quot;&gt;Creative Residence MC6&lt;/a&gt; in Slavsko (yay!); I brought a few
recorders and invited others to experiment with them and make their
own recordings. I recorded too. This is a short collage of what ended
up on the memory cards afterward.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/media/artnarysy.flac&quot;&gt;flac download&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#ArtNarysy #АртНариси&lt;/p&gt;

</description>
        <pubDate>Mon, 20 Sep 2021 00:00:00 +0300</pubDate>
        <link>https://xn--w5d.cc/2021/09/20/artnarysy.html</link>
        <guid isPermaLink="true">https://xn--w5d.cc/2021/09/20/artnarysy.html</guid>
        
        <category>field recording</category>
        
        <category>voice</category>
        
        <category>collaborative</category>
        
        
        <category>artistic</category>
        
      </item>
    
  </channel>
</rss>
