<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Functional Programming with PicoLisp]]></title><description><![CDATA[A blog about the ecosystem of PicoLisp - tutorials, real-world projects, functional programming theory.]]></description><link>https://picolisp-explored.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1629024076892/zfSSY6xW4.png</url><title>Functional Programming with PicoLisp</title><link>https://picolisp-explored.com</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 20 May 2026 22:06:48 GMT</lastBuildDate><atom:link href="https://picolisp-explored.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[A Railroad Simulation with DES]]></title><description><![CDATA[In our previous post, we introduced how to utilize Discrete Event Simulation (DES) in PicoLisp. Now, let's explore another application: a railroad model simulation that includes tracks and trains. The visualization is ASCII-based, so feel free to unl...]]></description><link>https://picolisp-explored.com/a-railroad-simulation-with-des</link><guid isPermaLink="true">https://picolisp-explored.com/a-railroad-simulation-with-des</guid><category><![CDATA[picolisp]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[discrete event simulation]]></category><category><![CDATA[railway]]></category><category><![CDATA[simulation]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Sun, 12 May 2024 19:16:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1715249051682/160d4d2a-a763-47e4-80e9-b1d8516a2f16.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In our <a target="_blank" href="https://picolisp-explored.com/picolisp-explored-discrete-event-simulation">previous post</a>, we introduced how to utilize Discrete Event Simulation (DES) in PicoLisp. Now, let's explore another application: a railroad model simulation that includes tracks and trains. The visualization is ASCII-based, so feel free to unleash your imagination to transform it into a comprehensive mini railway experience! 😊</p>
<p>You can create a sort of "model of a model railroad" with the program, and it serves no other purpose than having fun.</p>
<hr />
<p>The sources can be found on <a target="_blank" href="https://gitlab.com/picolisp-blog/single-plage-scripts/-/tree/main/railroad">GitLab</a> or downloaded from <a target="_blank" href="https://software-lab.de/bahn.tgz">https://software-lab.de/bahn.tgz</a> (source code within the "misc/"-folder). PicoLisp version &gt;= 23.12 is required.</p>
<hr />
<h2 id="heading-concept">Concept</h2>
<p>The base of the simulation is a railroad network drawn in ASCII, with each line representing a track. The cyan lines represent switches that enable the trains to change tracks.</p>
<p>The trains are the simulated objects ("bots"). They are depicted as <code>@000</code> , where the <code>@</code> mark represents the locomotive and each <code>0</code> represents a wagon.</p>
<p>At any point in time, a train is either</p>
<ul>
<li><p>waiting, e.g. at a station,</p>
</li>
<li><p>moving from one position to another,</p>
</li>
<li><p>or shunting (rearranging locomotive and wagons).</p>
</li>
</ul>
<hr />
<p>Let's see it in action in the example below. There are 5 trains in operation - some with multiple wagons, some with a locomotive at each end, and one solitary locomotive without any wagons.</p>
<p>For each train an individual schedule has been defined based on a specified order of positions. However, the precise movements of the trains are determined dynamically using Discrete Event Simulation.</p>
<p>The GIF below is showing the first 30 seconds of the simulation running at 8x speed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715542067487/5b63063b-0cf4-470f-8822-2af30bdac866.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-running-the-simulation">Running the simulation</h3>
<p>The source code is split into two files:</p>
<ul>
<li><p><code>bahn.l</code>, containing the fundamental logic for the train and network simulation.</p>
</li>
<li><p><code>plan.l</code>, containing the railway network layout and driving parameters, such as the number and specifications of trains, schedule, speed, etc.</p>
</li>
</ul>
<p><em>Note: if you are confused about the wording - "bahn" is the German word for train :)</em></p>
<p>To start the simulation, use the following command:</p>
<pre><code class="lang-clojure">$ pil bahn.l -bahn~main plan.l -go +
</code></pre>
<p>Typing "s" starts and stops the simulation, while the simulation speed doubles and halves with "+" and "-" respectively. <code>ESC</code> will drop you into the REPL, and calling <code>(go)</code> from the REPL will continue with the simulation. To exit the simulation, press <code>ESC</code> and then <code>Ctrl-D</code> or <code>(bye)</code>.</p>
<hr />
<h3 id="heading-train-simulation-in-detail">Train Simulation in Detail</h3>
<p>A train can be in three states: Waiting, moving and shunting.</p>
<p><em>Waiting</em> is realized using the <code>pause</code> function of the DES library.</p>
<p>More interesting is <em>moving</em>, which consists of several steps:</p>
<ol>
<li><p>Acceleration until reaching travel speed.</p>
</li>
<li><p>Continuous travel at the designated speed.</p>
</li>
<li><p>Deceleration upon reaching the destination.</p>
</li>
</ol>
<p>Discrete Event Simulation offers several advantages over continuous simulation, particularly when dealing with numerous bots with varying timings. For instance, <strong>continuous simulation</strong> will use a fixed time slice <code>dt</code> and the bot's current speed <code>v</code> to calculate their change in position, using the following differential equation:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715539172395/6967ce47-4862-4081-ad9a-2a4d01579d9a.png" alt class="image--center mx-auto" /></p>
<p>This calculation is performed for all bots, regardless of their individual speeds.</p>
<p>In contrast, <strong>discrete event simulation</strong> utilizes a spatial resolution <code>ds</code> (which may vary for each bot and scenario) and computes the time required to "pause" in the simulation until the bot has covered the distance:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719178142366/ba55f38b-5c0e-4631-a21b-89442221a631.png" alt class="image--center mx-auto" /></p>
<p>Now, all moving bots remain inactive for their scheduled amounts of time - longer if they move at slower speeds and/or coarser resolutions. This approach can significantly reduce processing time.</p>
<hr />
<p>Note that the equations above are valid only for moving at constant speed. For accelerated movement, a continuous simulation would calculate:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719178177519/9eee0519-d81f-457d-b1e0-b50f7a8eee5d.png" alt class="image--center mx-auto" /></p>
<p>For discrete event simulation, we can use:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719178201290/e14c815d-f077-4c36-931f-dba5966e1e54.png" alt class="image--center mx-auto" /></p>
<p>This behavior is implemented in the <code>drive</code> function in the file <code>bahn.l</code>. The function takes the following parameters: acceleration (in m/s², also utilized for deceleration during braking), travel speed (in m/s), and X and Y coordinates for the destination. Optionally, additional X and Y destination pairs can be provided to enforce intermediate stops.</p>
<p>For each destination, the function searches for a viable path through the track network and attempts to lock the path. If the path is unavailable, it enters a pause state until receiving a signal that another bot has released the locks. It also toggles all necessary switches as required for its route.</p>
<hr />
<p>Now the last train state, <em>shunting</em>, which is implemented in the <code>shunt</code> function in <code>bahn.l</code>. This function disconnects the locomotive from the first wagon, calls <code>drive</code> and <code>turn</code> repeatedly to navigate to the other end of the train, and connects to the previously last wagon.</p>
<hr />
<p>As an example, this is how the first locomotive is defined in <code>bahn.l</code>.</p>
<pre><code class="lang-clojure">(<span class="hljs-name"><span class="hljs-builtin-name">new</span></span> '(<span class="hljs-name">+Locomotive</span>) (<span class="hljs-name">pd</span> <span class="hljs-number">1</span> <span class="hljs-number">10</span> 'a) <span class="hljs-number">5</span>
   (<span class="hljs-name">pause</span>)
   (<span class="hljs-name"><span class="hljs-builtin-name">loop</span></span>
      (<span class="hljs-name">drive</span> <span class="hljs-number">0.2</span> <span class="hljs-number">40.0</span>  <span class="hljs-number">31</span> <span class="hljs-number">14</span>)
      (<span class="hljs-name">pause</span> <span class="hljs-number">12.0</span>)
      (<span class="hljs-name">drive</span> <span class="hljs-number">0.2</span> <span class="hljs-number">40.0</span>  <span class="hljs-number">45</span> <span class="hljs-number">34</span>)
      (<span class="hljs-name">shunt</span>
         (<span class="hljs-name">drive</span> <span class="hljs-number">0.1</span> <span class="hljs-number">10.0</span>  <span class="hljs-number">45</span> <span class="hljs-number">38</span>)
         (<span class="hljs-name">turn</span>)
         (<span class="hljs-name">drive</span> <span class="hljs-number">0.1</span> <span class="hljs-number">10.0</span>  <span class="hljs-number">48</span> <span class="hljs-number">32</span>  <span class="hljs-number">45</span> <span class="hljs-number">23</span>)
         (<span class="hljs-name">turn</span>)
         (<span class="hljs-name">drive</span> <span class="hljs-number">0.1</span> <span class="hljs-number">10.0</span>  <span class="hljs-number">45</span> <span class="hljs-number">28</span>) )
      (<span class="hljs-name">drive</span> <span class="hljs-number">0.2</span> <span class="hljs-number">40.0</span>  <span class="hljs-number">31</span> <span class="hljs-number">19</span>)
      ...  ) ) )
</code></pre>
<p>The <code>pd</code> method of the locomotive object defines that the locomotive starts at position <code>(x, y) = (1, 10)</code> and faces in direction of <code>a</code>, e. g. downwards. The last parameter of the first line, <code>5</code>, indicates the number of wagons.</p>
<p>As mentioned above, the <code>drive</code> method takes four parameters: acceleration, speed, and a target x-y-position. <code>drive</code> is also used within the <code>shunt</code> method to define the movement of the locomotive while the wagons stay at their current position.</p>
<hr />
<p>With this, we have covered all possible states of the train. Next we will see how the track network is implemented.</p>
<hr />
<h3 id="heading-track-simulation-in-detail">Track Simulation in Detail</h3>
<p>For the railway tracks to run the trains on, we use the track network library available in the PicoLisp distribution. The library has a <code>tracks</code> function in <code>@lib/simul.l</code>, which processes the ASCII representation of a railway layout from the current input stream and generates an appropriate data structure.</p>
<p>The idea is to have interconnected track elements where the bots can be positioned, along with a <code>cdr</code>-like operation to move a bot from one element to the next. Iterating this operation results in a continuous movement into one direction.</p>
<p>However, for a comprehensive track network, a simple linked list of track elements is insufficient. It must be possible to traverse it in both directions and accommodate switches (turnouts) and loops. Loops present a particular challenge. Consider this layout where a bot starts in the top-right position and moves leftwards:</p>
<pre><code class="lang-clojure">             &lt;--               &lt;--
       ---------------------------------
      /                 /      --&gt;
     /                 /
    /                 /
   |                 |
   |                 |
   |                 |
    \               /
     \             /
      \           /
       -----------
           --&gt;
</code></pre>
<p>After traversing the loop, it ends up in the top-right position again, but now moving in the opposite direction! The <code>cdr</code> operation would throw it back into the loop instead of continuing in the intended direction.</p>
<p>To address this, the <code>tracks</code> function generates what we call a "Networked Linked Lists" data structure. This structure is a form of indirect doubly linked list that accommodates branches, allowing for traversal in both directions and supporting complex track layouts such as loops.</p>
<p>The structure can be visualized with the built-in ASCII diagramming capabilities of the PicoLisp Vip editor. In the PicoLisp REPL (in debug mode!) enter</p>
<pre><code class="lang-clojure">: (<span class="hljs-name">vi</span> <span class="hljs-string">"@doc/Tracks"</span>)
</code></pre>
<p>and type "v" to view it in a new buffer. It will show:</p>
<pre><code class="lang-clojure">Connectors:

---------+                 +-------------&gt;   +-----------------------------&gt;
         |                 |                 |
         v                 |                 |
      +-----+-----+     +--+--+-----+     +--+--+-----+
  +--&gt;|  |  |  ---+----&gt;|  |  |  ---+----&gt;|  |  |  |  |
  |   +--+--+-----+     +-----+-----+     +-----+--+--+
  |      | ^                                       |
  |      | |                                       |
  |      | +---------------------------------------|-----------------+
  |      |                                         |                 |
  |      |                                         |                 |
  |      |      +----------+ +---------------------+                 |
  |      |      |          | |                                       |
  |      v      v          | v                                       |
  |   +------------+    +--+--+-----+     +-----+-----+     +-----+--+--+
  +---+- a      b -+---&gt;|  |  |  ---+----&gt;|  |  |  ---+----&gt;|  |  |  |  |
      |            |    +-----+-----+     +--+--+-----+     +--+--+-----+
      |   Track    |       ^                 |                 |
      |            |       |                 |                 |
      | x        y |       +-----------------|-----------------|------------
      +------------+                         |                 |
                                             |                 |
&lt;--------------------------------------------+   &lt;-------------+
</code></pre>
<p>As you can see, it is a rather complicated structure. The <code>Track</code> box is a symbol holding the actual track element. It stores information like the <code>x</code> and <code>y</code> coordinates and connectors to the neighboring track elements in <code>a</code> and <code>b</code>. Each connector consists of three cells for forward- and backward-links and optional switches in both directions.</p>
<hr />
<h3 id="heading-user-interface">User Interface</h3>
<p>Showing the animated ASCII drawing and handling user keyboard input is all done by a single function called <code>display</code>. It is called by <code>go</code> in a loop until <code>ESC</code> is typed, and allows to move around in the layout or along a rail track, and to toggle switches manually. Additionally, the following commands can be used in order to interact with the simulation:</p>
<ul>
<li><p><code>s</code> stops or continues the simulation.</p>
</li>
<li><p><code>+</code> and <code>-</code> double and halve the simulation speed respectively. Initially, the speed factor is 2. It is displayed at the bottom left.</p>
</li>
<li><p>A red `#` cursor (initially hidden on the left outside the layout) can be moved around on the screen with the following keystrokes:</p>
<ul>
<li><p><code>j</code> or <code>DOWN</code>, <code>k</code> or <code>UP</code>, <code>l</code> and <code>h</code> move by a single position</p>
</li>
<li><p><code>z</code> and <code>Z</code> move by eight positions right and left</p>
</li>
<li><p><code>w</code> and <code>b</code> move by a "word" (e.g. rail element) to the right and left</p>
</li>
<li><p><code>0</code> and <code>$</code> to go to left and right end of the layout</p>
</li>
<li><p><code>g</code> and <code>G</code> go to top and bottom of the layout</p>
</li>
<li><p><code>TAB</code> and <code>BACK</code> to jump to the next and previous switch</p>
</li>
<li><p><code>ENTER</code> to toggle a switch</p>
</li>
<li><p><code>SPACE</code> to move along the track</p>
</li>
<li><p><code>r</code> to toggle the move direction for the <code>SPACE</code> command.</p>
</li>
</ul>
</li>
</ul>
<hr />
<p>Now, with this information you should have a good understanding of how to create a railway model using discrete event simulation in PicoLisp. By referring to the examples on <a target="_blank" href="https://gitlab.com/picolisp-blog/single-plage-scripts/-/tree/main/railroad">GitLab</a>, tweaking it into your own railway model shouldn't be too challenging.</p>
<p>With some (considerable) effort, you could even replace the ASCII representation by something more visually appealing 😊</p>
<p><img src="https://cdn.pixabay.com/photo/2016/01/18/16/21/model-train-1146828_640.jpg" alt="Modelleisenbahn, Modell, Eisenbahn, Zug" /></p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li><p><a target="_blank" href="https://www.irasutoya.com/2013/05/blog-post_9988.html">https://www.irasutoya.com/2013/05/blog-post_9988.html</a></p>
</li>
<li><p><a target="_blank" href="https://software-lab.de/doc/des.html">https://software-lab.de/doc/des.html</a></p>
</li>
<li><p><a target="_blank" href="https://pixabay.com/de/photos/modelleisenbahn-modell-eisenbahn-1146828/">https://pixabay.com/de/photos/modelleisenbahn-modell-eisenbahn-1146828/</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[PicoLisp Explored: Discrete Event Simulation]]></title><description><![CDATA[The last post was about coroutines. Now we will show how these coroutines can be used for Discrete Event Simulation (DES).

Discrete Event Simulation in PicoLisp
As the name suggests, Discrete Event Simulation (DES) models systems by focusing on a se...]]></description><link>https://picolisp-explored.com/picolisp-explored-discrete-event-simulation</link><guid isPermaLink="true">https://picolisp-explored.com/picolisp-explored-discrete-event-simulation</guid><category><![CDATA[picolisp]]></category><category><![CDATA[coroutines]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[discrete event simulation]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Sat, 09 Sep 2023 09:31:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1694206264655/e402658d-edf2-4299-8816-a89f6fbcb74a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The last post was about <a target="_blank" href="https://hashnode.com/post/cll9dbbc4000a09ladzyw9tb2">coroutines</a>. Now we will show how these coroutines can be used for <strong>Discrete Event Simulation (DES)</strong>.</p>
<hr />
<h2 id="heading-discrete-event-simulation-in-picolisp">Discrete Event Simulation in PicoLisp</h2>
<p>As the name suggests, Discrete Event Simulation (DES) models systems by focusing on a sequence of distinct events. Instead of continuously tracking a system's state, DES jumps from one distinct event to another. This approach is frequently employed in gaming to simulate aspects like character behavior and crowd movements. By focusing on these key events, it gets much easier to understand and design complex behaviors without tracking every little detail.</p>
<p>Since pil21 version 22.1.18 (January 2022), PicoLisp has a DES library. You can find the code in <code>lib/simul.l</code> and the documentation in <code>doc/des.html</code>.</p>
<hr />
<p>Using the DES library, we can simulate the behavior of <strong>agents</strong> which are realized as coroutines. These coroutines are driven by <strong>events</strong>. To manage these coroutines, we have several control options:</p>
<ul>
<li><p><code>pause</code>: pauses the coroutine either for a set duration or until a designated event takes place.</p>
</li>
<li><p><code>event</code>: Sends a signal to all coroutines awaiting that specific event.</p>
</li>
<li><p><code>wake</code>: Resumes a previously suspended coroutine.</p>
</li>
<li><p><code>des</code>: enables the simulation to "jump" from one event to another.</p>
</li>
</ul>
<p>To understand how DES works, let's look at a famous programming problem: E. W. Dijkstra's "Dining Philosophers".</p>
<p><em>Note: The link to the final code can be found at the bottom of the page.</em></p>
<hr />
<h2 id="heading-the-dining-philosophers">The Dining Philosophers</h2>
<h3 id="heading-task-description">Task Description</h3>
<p>Five silent philosophers sit at a round table with bowls of spaghetti. Forks are placed between each pair of adjacent philosophers. Each philosopher thinks deeply and, intermittently, and interrupts their thoughts to eat from a bowl of spaghetti placed in front of them. However, to eat, they need two forks. A single fork is placed between each pair of adjacent philosophers. The crux of the problem is that each philosopher can only eat when they have both their left and right forks.</p>
<p>The problem was designed to illustrate the challenges of ensuring that several concurrent processes (e.g. the philosophers) can access shared resources (the forks) without conflict:</p>
<ol>
<li><p>No two philosophers should be able to pick up the same fork at the same time (preventing <strong>race conditions</strong>).</p>
</li>
<li><p>Philosophers should not <strong>starve</strong> (fairness in accessing resources).</p>
</li>
<li><p><strong>Deadlocks</strong> should be prevented (e.g. all philosophers having one fork in their left hand).</p>
</li>
</ol>
<hr />
<p>The Dining Philosophers is one of my favorite problem descriptions because it leaves so many questions hanging in the air: Why do they use two forks? Do the forks get cleaned in between? And which type of spaghetti is being served?</p>
<p>(Unfortunately, these questions will not be answered by the algorithm).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1693402958491/9072d4b3-026f-4cb2-ae2a-8ca7135d784e.png" alt class="image--center mx-auto" /></p>
<p>Because this is a modern blog, we will host a gender-parity party. Our dinner guests are <a target="_blank" href="https://en.wikipedia.org/wiki/Hannah_Arendt">Hannah Arendt</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Hildegard_of_Bingen">Hildegard v. Bingen</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Rosa_Luxemburg">Rosa Luxemburg</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Immanuel_Kant">Immanuel Kant</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Friedrich_Nietzsche">Friedrich Nietzsche</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Ludwig_Wittgenstein">Ludwig Wittgenstein</a>.</p>
<hr />
<h3 id="heading-loading-the-simull-library">Loading the simul.l library</h3>
<p>To use the DES functions, we need to load the library and declare the namespaces:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">load</span> <span class="hljs-string">"@lib/simul.l"</span>)
(<span class="hljs-name">symbols</span> 'dining-philosophers 'simul 'pico)
</code></pre>
<p>The <code>symbols</code> function defines the search hierarchy for symbols (e.g. variables, functions...). Initially, it searches within the local namespace, labeled <code>dining-philosophers</code>. If not found, it proceeds to the <code>simul</code> namespace specified in <code>simul.l</code>, and finally checks the pil21 namespace <code>pico</code>.</p>
<hr />
<h3 id="heading-defining-the-agents">Defining the agents</h3>
<p>Simply put, in our simulation each philosopher acts as an agent. And as previously mentioned, every agent operates as a coroutine. These agents have a singular task - dining - and to do so, they require two forks.</p>
<p>The forks are shared within all agents, e.g. they are <strong>globals</strong>. Following the PicoLisp conventions, we declare these global variables at the beginning and their name starts with an asterisk.</p>
<pre><code class="lang-clojure">(<span class="hljs-name">local</span>) (<span class="hljs-name">*ForkA</span> *ForkB *ForkC *ForkD *ForkE *ForkF)

(<span class="hljs-name">co</span> 'Arendt
   (<span class="hljs-name">dining</span> '*ForkA '*ForkB) )
(<span class="hljs-name">co</span> 'v.-Bingen
   (<span class="hljs-name">dining</span> '*ForkB '*ForkC) )
(<span class="hljs-name">co</span> 'Luxemburg
   (<span class="hljs-name">dining</span> '*ForkC '*ForkD) )
(<span class="hljs-name">co</span> 'Kant
   (<span class="hljs-name">dining</span> '*ForkD '*ForkE) )
(<span class="hljs-name">co</span> 'Nietzsche
   (<span class="hljs-name">dining</span> '*ForkE '*ForkF) )
(<span class="hljs-name">co</span> 'Wittgenstein
   (<span class="hljs-name">dining</span> '*ForkF '*ForkA) )
</code></pre>
<p>(Since it's a round table, Wittgenstein is sharing his fork with Hannah Arendt.)</p>
<hr />
<h3 id="heading-the-dining-function">The "dining" function</h3>
<p>Now to the heart of our program. We can define five stages for each agent:</p>
<ol>
<li><p><strong>Thinking:</strong> The philosopher is in a contemplative state and isn't looking to eat.</p>
</li>
<li><p><strong>Hungry:</strong> The philosopher feels the need to eat.</p>
</li>
<li><p><strong>Waiting for Forks:</strong> The philosopher waits to acquire the two forks if they're unavailable.</p>
</li>
<li><p><strong>Picking Up Forks and Eating:</strong> Once the forks are free, the philosopher picks them up and begins to eat.</p>
</li>
<li><p><strong>Putting Down the Forks:</strong> After eating, the philosopher releases the forks for others to use.</p>
</li>
</ol>
<p>These five stages are continuously looped throughout the simulation.</p>
<p>The initial stage is straightforward: We display "&lt;philosopher&gt; is hungry..." and then pause the simulation. Assuming our simulation time is measured in minutes, each pause duration ranges between 180 and 240 minutes.</p>
<pre><code class="lang-lisp">(<span class="hljs-name">de</span> dining (<span class="hljs-name">LeftFork</span> RightFork)
  (<span class="hljs-name">loop</span>
    (<span class="hljs-name">prinl</span> (<span class="hljs-name">pack</span> (<span class="hljs-name">co</span>) <span class="hljs-string">" is thinking... 💭"</span>))
    (<span class="hljs-name">pause</span> (<span class="hljs-name">rand</span> <span class="hljs-number">180</span> <span class="hljs-number">240</span>))
</code></pre>
<p><em>Note: To extract the coroutine tag we use</em> <code>(co)</code><em>, and the</em> <code>pack</code> <em>function converts all arguments to a single string.</em></p>
<hr />
<p>Now we can simulate 20 event steps by calling the <code>des</code> function 20 times.</p>
<pre><code class="lang-lisp">&lt;...&gt;
(<span class="hljs-name">co</span> 'Wittgenstein
   (<span class="hljs-name">dining</span> '*ForkE '*ForkA) ) 

(<span class="hljs-name">do</span> <span class="hljs-number">20</span> (<span class="hljs-name">des</span>))
</code></pre>
<p>Starting the script, we find all philosophers in deep thought.</p>
<pre><code class="lang-lisp">$ ~/pil21/pil dining-philosophers.l
Arendt is thinking... 💭
v.-Bingen is thinking... 💭
Luxemburg is thinking... 💭
Kant is thinking... 💭
Nietzsche is thinking... 💭
&lt;...&gt;
</code></pre>
<hr />
<p>After between 180 to 240 time units, the coroutine resumes. Now is the time to declare the next step: The philosopher is getting hungry. If both forks are available, they proceed to eat.</p>
<p>For our simulation, the act of "eating" involves setting the global fork values to a non-<code>NIL</code> value. It is convenient to set the value to the coroutine's tag, e.g. the philosopher's name:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">set</span> LeftFork (<span class="hljs-name">set</span> RightFork (<span class="hljs-name">co</span>)))
(<span class="hljs-name">prinl</span> (<span class="hljs-name">pack</span> (<span class="hljs-name">co</span>) <span class="hljs-string">" is eating! 🍝"</span>))
(<span class="hljs-name">pause</span> <span class="hljs-number">20</span>)
</code></pre>
<p>First, we need to check if both forks are free. If one or both forks are taken, our coroutine <strong>pauses</strong>. It will start again when it gets an <strong>event</strong> signal related to <code>LeftFork</code> or <code>RightFork</code>.</p>
<pre><code class="lang-lisp">(<span class="hljs-name">while</span> (<span class="hljs-name">or</span> (<span class="hljs-name">val</span> LeftFork) (<span class="hljs-name">val</span> RightFork))
   (<span class="hljs-name">prinl</span> (<span class="hljs-name">pack</span> (<span class="hljs-name">co</span>) <span class="hljs-string">" has no fork!! 🤬🤬🤬"</span> ) )
   (<span class="hljs-name">pause</span> LeftFork RightFork) )
</code></pre>
<p><em>Note: This part will be changed later to something more expressive.</em></p>
<hr />
<p>Fortunately for our hungry philosophers, each meal lasts only 20 minutes. After that, the philosopher releases the forks. This action sends an event signal for the paused coroutines to resume:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">prinl</span> (<span class="hljs-name">pack</span> (<span class="hljs-name">co</span>) <span class="hljs-string">" finished eating."</span>)) 
(<span class="hljs-name">set</span> LeftFork (<span class="hljs-name">set</span> RightFork NIL))
(<span class="hljs-name">event</span> LeftFork)
(<span class="hljs-name">event</span> RightFork)
</code></pre>
<p>This is all we need for a fully functional simulation:</p>
<pre><code class="lang-lisp">$ ~/pil21/pil dining-philosophers.l
Arendt is thinking... 💭
v.-Bingen is thinking... 💭
&lt;...&gt;
Nietzsche has no fork!! 🤬🤬🤬
Arendt finished eating.
Arendt is thinking... 💭
</code></pre>
<p>This simulation avoids deadlocks by two factors: both forks are always handled simultaneously, and coroutines waiting for forks are consistently queued behind others that are already waiting.</p>
<hr />
<h3 id="heading-managing-the-time">Managing the time</h3>
<p>We've outlined the basic program structure but have yet to address an important aspect: Time simulation.</p>
<p>Within DES, there are two modes: <strong>Realtime</strong> and <strong>Simulated</strong> <strong>Time</strong>. These modes are determined by the <code>*Rt</code> global variable. If <code>*Rt</code> is set to <code>NIL</code>, it indicates simulated time. A value of <code>1</code> represents real-world clock speed, <code>2</code> double speed, and so on.</p>
<p>Since we do not want to wait 4 hours for all philosophers to finish thinking, let's stick with simulated time. To do so, we set <code>*Rt</code> to <code>NIL</code> at the beginning of our program:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">off</span> *Rt)
</code></pre>
<p>To provide better insights into our program's process, we want to include a timestamp in our output. For this we introduce a function called <code>now</code> that prints the current time in <code>HH:MM</code> format, followed by the coroutine tag and a specified string. We can utilize the built-in <code>tim$</code> function for this purpose.</p>
<pre><code class="lang-lisp">(<span class="hljs-name">de</span> now (<span class="hljs-name">Str</span>)
   (<span class="hljs-name">prinl</span> (<span class="hljs-name">tim</span>$ (<span class="hljs-name">*</span> <span class="hljs-number">60</span> *Time)) " " (co) " " Str) )
</code></pre>
<p>If we replace <code>prinl</code> with the <code>now</code> function in our code and run the program, the output will show timestamps. This makes it easy to verify that the thinking phase indeed lasts at least 3 "hours" and the eating phase takes exactly 20 "minutes".</p>
<pre><code class="lang-lisp">$ ~/pil21/pil dining-philosophers.l                                                                                                                                          
&lt;...&gt;
<span class="hljs-number">03</span>:<span class="hljs-number">18</span> Nietzsche is hungry... 😋
<span class="hljs-number">03</span>:<span class="hljs-number">18</span> Nietzsche has no fork!! 🤬🤬🤬
<span class="hljs-number">03</span>:<span class="hljs-number">20</span> Arendt finished eating.
<span class="hljs-number">03</span>:<span class="hljs-number">20</span> Arendt is thinking... 💭
<span class="hljs-number">03</span>:<span class="hljs-number">20</span> Wittgenstein has no fork!! 🤬🤬🤬
</code></pre>
<p>As a last little gimmick, let's also add which fork is missing and who is using it:</p>
<pre><code class="lang-lisp"> &lt;...&gt;   
    (<span class="hljs-name">use</span> (<span class="hljs-name">L</span> R)
      (<span class="hljs-name">while</span>
        (<span class="hljs-name">or</span>
          (<span class="hljs-name">setq</span> L (<span class="hljs-name">val</span> LeftFork))
          (<span class="hljs-name">setq</span> R (<span class="hljs-name">val</span> RightFork)) )
        (<span class="hljs-name">now</span> (<span class="hljs-name">pack</span> <span class="hljs-string">"waiting for "</span> L (<span class="hljs-name">and</span> L R <span class="hljs-string">" and "</span>) R <span class="hljs-string">" 🤬🤬🤬 "</span>))
      (<span class="hljs-name">pause</span> LeftFork RightFork) ) )
</code></pre>
<p>Which adds quite some drama to the dinner table!</p>
<pre><code class="lang-lisp"><span class="hljs-number">11</span>:<span class="hljs-number">05</span> Luxemburg is hungry... 😋
<span class="hljs-number">11</span>:<span class="hljs-number">05</span> Luxemburg waiting for Kant 🤬🤬🤬 
<span class="hljs-number">11</span>:<span class="hljs-number">21</span> Nietzsche is hungry... 😋
<span class="hljs-number">11</span>:<span class="hljs-number">21</span> Nietzsche waiting for Kant 🤬🤬🤬
</code></pre>
<hr />
<h3 id="heading-adding-the-main-function">Adding the main function</h3>
<p>Having a main function is not a must, but it makes debugging the program easier. To set it up, we start by defining the <code>main</code> symbol. Next, we set up the namespace search order, and then we add the rest of our code.</p>
<pre><code class="lang-lisp">(<span class="hljs-name">local</span>) (<span class="hljs-name">main</span>)

(<span class="hljs-name">de</span> main()
  (<span class="hljs-name">symbols</span> '(dining-philosophers simul pico))
  (<span class="hljs-name">co</span> 'Arendt 
     &lt;...&gt;
</code></pre>
<p>Now we can start the script like this:</p>
<pre><code class="lang-lisp">$ ~/pil21/pil dining-philosophers.l -dining-philosophers~main +  

<span class="hljs-number">00</span>:<span class="hljs-number">00</span> Arendt is thinking... 💭                                                                                                                                      
<span class="hljs-number">00</span>:<span class="hljs-number">00</span> v.-Bingen is thinking... 💭                                                                                                                                   
<span class="hljs-number">00</span>:<span class="hljs-number">00</span> Luxemburg is thinking... 💭                                                                                                                                   
<span class="hljs-number">00</span>:<span class="hljs-number">00</span> Kant is thinking... 💭                                                                                                                                        
<span class="hljs-number">00</span>:<span class="hljs-number">00</span> Nietzsche is thinking... 💭                                                                                                                                   
<span class="hljs-number">00</span>:<span class="hljs-number">00</span> Wittgenstein is thinking... 💭                                                                                                                                
dining-philosophers:
</code></pre>
<p>This will directly open a PicoLisp REPL in the correct namespace for debugging. Now you can verify the stack or run some more simulation steps with <code>(des)</code>.</p>
<p><img src="https://4.bp.blogspot.com/-eyflJhzyFkQ/U82w2kak9iI/AAAAAAAAjEc/QTbxOUpmccI/s400/pasta_penne.png" alt="ペンネのイラスト（パスタ）" /></p>
<hr />
<p>You can find the final code <a target="_blank" href="https://gitlab.com/picolisp-blog/single-plage-scripts/-/raw/main/picolisp-explored/dining-philosophers.l?ref_type=heads">here</a>.</p>
<hr />
<h2 id="heading-sources">Sources</h2>
<ul>
<li><p><a target="_blank" href="https://software-lab.de/doc/des.html">https://software-lab.de/doc/des.html</a></p>
</li>
<li><p><a target="_blank" href="https://www.irasutoya.com/">https://www.irasutoya.com/</a></p>
</li>
<li><p><a target="_blank" href="https://software-lab.de/doc/index.html">https://software-lab.de/doc/index.html</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[PicoLixp Explored: On Coroutines]]></title><description><![CDATA[In this post, we will introduce the concept of co-routines and how they are handled in PicoLisp. This will be the foundation for the subsequent posts on Discrete Event Simulation and finally a couple of examples, including an ASCII model railway simu...]]></description><link>https://picolisp-explored.com/picolixp-explored-on-coroutines</link><guid isPermaLink="true">https://picolisp-explored.com/picolixp-explored-on-coroutines</guid><category><![CDATA[picolisp]]></category><category><![CDATA[coroutines]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Sun, 13 Aug 2023 11:33:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1691922895205/ed5b3ae9-3469-40b1-a03e-551b10dabbfb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, we will introduce the concept of co-routines and how they are handled in PicoLisp. This will be the foundation for the subsequent posts on Discrete Event Simulation and finally a couple of examples, including an ASCII model railway simulation written in PicoLisp, so stay tuned 🤗</p>
<h3 id="heading-what-are-coroutines">What are Coroutines?</h3>
<p>Coroutines are a type of programming construct that aim to achieve concurrency in programming without using threads or processes. The key idea of coroutines is that their execution can be paused and resumed at specific points during their execution, allowing other coroutines to run in the meantime. This requires that the local environment as well as the state of control of the function are preserved while the coroutines are stopped.</p>
<p>One of the benefits of coroutines is that they can be used to write asynchronous code in a more sequential and readable manner, compared to other concurrency models such as threads or callbacks. Coroutines can be used to write code that looks like synchronous code, while still taking advantage of asynchronous behavior and avoiding some of the pitfalls of concurrent programming, such as race conditions and deadlocks.</p>
<hr />
<h3 id="heading-co-routines-in-picolisp">Co-Routines in PicoLisp</h3>
<p>We need two functions to create a coroutine in PicoLisp: <code>co</code> to initiate the coroutine, and <code>yield</code>, which controls when the function is stopped and resumed.</p>
<p>From the <a target="_blank" href="https://software-lab.de/doc/index.html">documentation</a>:</p>
<blockquote>
<p><code>(co ['any [. prg]]) -&gt; any</code></p>
<p>Starts, resumes or stops a coroutine with the tag given by <code>any</code>. (...) <code>prg</code> will be executed until it either terminates normally or until <code>yield</code> is called.</p>
</blockquote>
<p>Let's look at a very simple co-routine:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">co</span> 'a
    (<span class="hljs-name">let</span> N <span class="hljs-number">0</span>
        (<span class="hljs-name">loop</span>
            (<span class="hljs-name">yield</span>
                (<span class="hljs-name">inc</span> 'N) ) ) ) )
</code></pre>
<p>According to the definition, we have two parts: <code>a</code> is the <em>tag</em> of the coroutine, and <code>(let N 0 (loop (yield (inc 'N)))))</code> is its program body. If we call it for the first time, <code>N</code> will be set to zero and then increased by one in a loop. Then <code>yield</code> interrupts the coroutine and returns the value.</p>
<p>Let's test it in the REPL:</p>
<pre><code class="lang-lisp">: (<span class="hljs-name">co</span> 'a (<span class="hljs-name">let</span> N <span class="hljs-number">0</span> (<span class="hljs-name">loop</span> (<span class="hljs-name">yield</span> (<span class="hljs-name">inc</span> 'N))))) 
-&gt; <span class="hljs-number">1</span>
</code></pre>
<p>As expected, the return value is 1, because <code>N</code> has been increased once.</p>
<hr />
<p>Now comes the point: Next time we call the coroutine <code>a</code>, it will <strong>resume</strong> where we stopped. The syntax to resume is <code>(co &lt;tag&gt; &lt;anything&gt;)</code> , for example:</p>
<pre><code class="lang-lisp">: (<span class="hljs-name">co</span> 'a T) 
-&gt; <span class="hljs-number">2</span>
: (<span class="hljs-name">co</span> 'a T)
-&gt; <span class="hljs-number">3</span>
</code></pre>
<p><em>Note: The</em><code>anything</code><em>part can be literally anything as it does not get executed. For example, this one will also work but does not make sense:</em></p>
<pre><code class="lang-lisp">: (<span class="hljs-name">co</span> 'a (<span class="hljs-name">println</span> <span class="hljs-string">"this will not print anything"</span>))
-&gt; <span class="hljs-number">4</span>
</code></pre>
<hr />
<p>To <strong>stop</strong> the coroutine, we call <code>(co &lt;tag&gt;)</code> without any argument. If then the coroutine gets called again, it will start from the beginning.</p>
<pre><code class="lang-lisp">: (<span class="hljs-name">co</span> 'a) 
-&gt; a
: (<span class="hljs-name">co</span> 'a (<span class="hljs-name">let</span> N <span class="hljs-number">0</span> (<span class="hljs-name">loop</span> (<span class="hljs-name">yield</span> (<span class="hljs-name">inc</span> 'N))))) 
-&gt; <span class="hljs-number">1</span>
</code></pre>
<hr />
<h3 id="heading-managing-the-stack">Managing the Stack</h3>
<p>To keep the local environment for each coroutine, each one of them needs its own stack space to maintain its state. This means that for large and nested coroutines, it might be necessary to monitor the stack size. By default, the stack segment size is 64 kB for coroutines and 256 kB for the main stack segment.</p>
<p>The current stack can be viewed like this:</p>
<pre><code class="lang-lisp">: (<span class="hljs-name">stack</span>)
-&gt; ((<span class="hljs-name">a</span> . <span class="hljs-number">63</span>) (<span class="hljs-name">T</span> . <span class="hljs-number">250</span>) . <span class="hljs-number">64</span>)
</code></pre>
<p>In the output above we see our coroutine <code>a</code> and the main routine (which also maintains the REPL) <code>T</code>, with the respective unused stack space, plus the general coroutine stack size:</p>
<ul>
<li><p>coroutine <code>a</code> has unused stack space of 63 kB (out of 64),</p>
</li>
<li><p>the main routine <code>T</code> has unused stack space of 250 kB (out of 256 kB),</p>
</li>
<li><p>The allocated stack size of each coroutine is 64 kB.</p>
</li>
</ul>
<hr />
<p>In some situations, you might want to adjust the stack space. This is done by passing arguments to the <code>stack</code> function, where the first argument is the coroutine stack size and the second (optional) argument is the main stack size. The coroutine stack size can only be modified if no coroutine is running.</p>
<pre><code class="lang-lisp">: (<span class="hljs-name">co</span> 'a)   # stop current coroutine
-&gt; a
: (<span class="hljs-name">stack</span> <span class="hljs-number">128</span> <span class="hljs-number">512</span>)
-&gt; <span class="hljs-number">128</span>
</code></pre>
<p>If we then start the coroutine again, we will see the updated stack sizes:</p>
<pre><code class="lang-lisp">: (<span class="hljs-name">co</span> 'a (<span class="hljs-name">let</span> N <span class="hljs-number">0</span> (<span class="hljs-name">loop</span> (<span class="hljs-name">yield</span> (<span class="hljs-name">inc</span> 'N)))))   # restart coroutine
-&gt; <span class="hljs-number">1</span>
: (<span class="hljs-name">stack</span>)
-&gt; ((<span class="hljs-name">a</span> . <span class="hljs-number">127</span>) (<span class="hljs-name">T</span> . <span class="hljs-number">507</span>) . <span class="hljs-number">128</span>)
</code></pre>
<hr />
<p>Obviously we cannot allocate more stack space to a coroutine than is allocated by the system to the picolisp process. The default stack space settings can be checked with the <code>ulimit -s</code> command in Linux systems:</p>
<pre><code class="lang-bash">$ <span class="hljs-built_in">ulimit</span> -s
8192
</code></pre>
<p>In the example above, it is 8192 kB (8 MB). If we try to allocate more than 8 MB to the coroutines, we will get a segmentation fault error:</p>
<pre><code class="lang-lisp">: (<span class="hljs-name">stack</span> <span class="hljs-number">4200</span> <span class="hljs-number">4200</span>)
-&gt; <span class="hljs-number">4200</span>
: (<span class="hljs-name">co</span> 'a T)
[<span class="hljs-number">1</span>]    <span class="hljs-number">17524</span> segmentation fault (<span class="hljs-name">core</span> dumped)  ~/pil21/pil +
</code></pre>
<p>To prevent this, we can increase the stack space for the PicoLisp process with <code>ulimit -s &lt;stack space&gt;</code>:</p>
<pre><code class="lang-bash">$ <span class="hljs-built_in">ulimit</span> -s 16384   <span class="hljs-comment"># 16 MB</span>
$ <span class="hljs-built_in">ulimit</span> -s unlimited
</code></pre>
<p>Use with care, as allocating too many resources to a process might exhaust your system's resource limits and lead to unexpected behavior.</p>
<hr />
<p>If you find this "increase a number" example a little bit boring, wait for the next posts - we will see some more useful examples on how to use coroutines soon.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li><p>https://picolisp.com/wiki/?Coroutines</p>
</li>
<li><p><a target="_blank" href="http://software-lab.de/doc/ref.html#coroutines">http://software-lab.de/doc/ref.html#coroutines</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Data Visualization with D3.js and PicoLisp]]></title><description><![CDATA[One of the many nice things of PicoLisp is that it comes with a built-in database. This makes it easy to collect and store our own data, for example via a mobile app. But not all data is best represented in tables and lists: sometimes a colorful litt...]]></description><link>https://picolisp-explored.com/data-visualization-with-d3js-and-picolisp</link><guid isPermaLink="true">https://picolisp-explored.com/data-visualization-with-d3js-and-picolisp</guid><category><![CDATA[lisp]]></category><category><![CDATA[D3.js]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[picolisp]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 07 Jun 2022 09:02:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1654524673497/iHiIigU3u.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the many nice things of PicoLisp is that it comes with a <a target="_blank" href="https://picolisp-explored.com/series/database">built-in database</a>. This makes it easy to collect and store our own data, for example via a <a target="_blank" href="https://picolisp-explored.com/series/mobile">mobile app</a>. But not all data is best represented in tables and lists: sometimes a colorful little graph says more than 1000 numbers. </p>
<p>So how to transform the database output into this colorful graph? Luckily, we don't need to re-invent the wheel - data visualization can be very easy for example with a little help from the JavaScript <a target="_blank" href="https://d3js.org">D3.js library</a>. </p>
<p>In the following post, I will explain how I created the little demo page that you can also visit <a target="_blank" href="https://picolisp.com/blog/src/d3-demo.l">with this link</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654525274699/BgzPHGqTJ.png" alt="image.png" /></p>
<hr />
<h3 id="heading-about-d3js">About D3.js</h3>
<p><a target="_blank" href="https://d3js.org/">D3.js</a> is an open-source JavaScript library that makes it possible to create pretty and flexible graphs in quite an easy way. It is not the only data visualization library - alternatives are for example <a target="_blank" href="https://www.chartjs.org/">charts.js</a> or <a target="_blank" href="https://visjs.org/">vis.js</a>. But at the point of writing this post, D3.js the project with the largest community and it comes with a pretty good documentation.</p>
<p>With help of D3.js, we can keep the data separate from the visualization. For example, we can retrieve data dynamically from the PicoLisp database or from user input, and feed this data into the JavaScript function. All we need is to define the DOM object where the graph should be created.</p>
<hr />
<h3 id="heading-a-minimal-example">A minimal example</h3>
<p>Let's take a look at a truly minimal example (no PicoLisp). 
Let's assume we have a (JavaScript array) <code>var data = [90, 100, 30, 80]</code>. Then the corresponding bar plot will be defined like this:</p>
<pre><code><span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span>DOCTYPE html<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>html lang<span class="hljs-operator">=</span><span class="hljs-string">"en"</span><span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>head<span class="hljs-operator">&gt;</span>
   ...
<span class="hljs-operator">&lt;</span>script src<span class="hljs-operator">=</span><span class="hljs-string">"https://d3js.org/d3.v3.min.js"</span> charset<span class="hljs-operator">=</span><span class="hljs-string">"utf-8"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>style<span class="hljs-operator">&gt;</span> ... <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>style<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>head<span class="hljs-operator">&gt;</span>

<span class="hljs-operator">&lt;</span>body<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>script <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"text/javascript"</span><span class="hljs-operator">&gt;</span>
<span class="hljs-keyword">var</span> data <span class="hljs-operator">=</span> [<span class="hljs-number">150</span>, <span class="hljs-number">230</span>, <span class="hljs-number">180</span>, <span class="hljs-number">90</span>];
<span class="hljs-keyword">var</span> svg <span class="hljs-operator">=</span> d3.select(<span class="hljs-string">"body"</span>)
   .append(<span class="hljs-string">"svg"</span>)
   .attr(<span class="hljs-string">"width"</span>, <span class="hljs-number">300</span>)
   .attr(<span class="hljs-string">"height"</span>, <span class="hljs-number">200</span>);
svg.selectAll(<span class="hljs-string">".bar"</span>)
   .data(data)
   .enter()
   .append(<span class="hljs-string">"rect"</span>)
   .attr({
      class : <span class="hljs-string">"bar"</span>,
      width : <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{<span class="hljs-keyword">return</span> d;},
      height: <span class="hljs-string">"40"</span>,
      y : <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d, i</span>) </span>{<span class="hljs-keyword">return</span> i<span class="hljs-operator">*</span><span class="hljs-number">50</span> <span class="hljs-operator">+</span> <span class="hljs-number">10</span>;},
      x : <span class="hljs-string">"10"</span>
   });
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>body<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>html<span class="hljs-operator">&gt;</span>
</code></pre><hr />
<p>And this is how it looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654526325437/E2vwfYp1e.png" alt="image.png" /></p>
<p>First of all, we need to include the D3.js source file in the header of our HTML page.</p>
<pre><code><span class="hljs-operator">&lt;</span>script src<span class="hljs-operator">=</span><span class="hljs-string">"https://d3js.org/d3.v7.min.js"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>
</code></pre><p>The actual graph is defined in the second <code>&lt;script&gt; &lt;/script&gt;</code> tag. There we create an SVG element with in the specified DOM object (in this case simply<code>&lt;body&gt;</code>). Then we append <code>rect</code> (rectangular) elements to it. The position and size of the rectangles is defined by the values of the <code>data</code> array.</p>
<hr />
<p>Since this is not supposed to be a JavaScript tutorial, we will not go into further depth with this topic. But there are plenty of great resources about D3.js - you only need to be careful to use the correct version, because the releases are partially not backwards-compatible. This post uses the most recent version <code>D3.v7.min.js</code>.</p>
<hr />
<h3 id="heading-calling-d3js-from-picolisp">Calling D3.js from PicoLisp</h3>
<p>Now let's recreate the same thing with PicoLisp. First we need to wrap the JavaScript code from above into a function and save it in an external file. As a reference, I created three graphs (click on the link to see the source code):</p>
<ul>
<li><a target="_blank" href="https://gitlab.com/picolisp-blog/web-applications/-/blob/main/d3-demo/js/barGraph.js">Bar graph example</a></li>
<li><a target="_blank" href="https://gitlab.com/picolisp-blog/web-applications/-/blob/main/d3-demo/js/pieGraph.js">Pie graph example</a></li>
<li><a target="_blank" href="https://gitlab.com/picolisp-blog/web-applications/-/blob/main/d3-demo/js/xyGraph.js">XY-graph example</a></li>
</ul>
<p>All three functions take four arguments: the data array, the DOM-id of the div where the graph should be created, and the width and height of the graph.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">drawXYGraph</span>(<span class="hljs-params">data, id, w, h</span>) </span>{

      <span class="hljs-keyword">var</span> svg <span class="hljs-operator">=</span> d3.select(id)
      .append(<span class="hljs-string">"svg"</span>)
      .attr(<span class="hljs-string">"width"</span>, w)
      .attr(<span class="hljs-string">"height"</span>, h);

...
</code></pre><hr />
<p>Then we create the PicoLisp main file and load these javascript functions, as well as the D3 library itself.</p>
<pre><code>(<span class="hljs-name"><span class="hljs-builtin-name">load</span></span> <span class="hljs-string">"@lib/http.l"</span> <span class="hljs-string">"@lib/xhtml.l"</span> <span class="hljs-string">"@lib/form.l"</span>)
(<span class="hljs-name">setq</span> *Css '(<span class="hljs-string">"@lib.css"</span> <span class="hljs-string">"css/bootstrap.css"</span> <span class="hljs-string">"css/custom.css"</span>))

(<span class="hljs-name">de</span> work ()
   (<span class="hljs-name"><span class="hljs-builtin-name">and</span></span> (<span class="hljs-name">app</span>) *Port% (<span class="hljs-name">redirect</span> (<span class="hljs-name">baseHRef</span>) *SesId *Url))
   (<span class="hljs-name">action</span>
      (<span class="hljs-name">html</span> <span class="hljs-number">0</span> <span class="hljs-string">"D3.JS in PicoLisp"</span> *Css NIL
         (<span class="hljs-name">javascript</span> <span class="hljs-string">"https://d3js.org/d3.v7.min.js"</span>)
         (<span class="hljs-name">javascript</span> <span class="hljs-string">"js/barGraph.js"</span>)
         (<span class="hljs-name">javascript</span> <span class="hljs-string">"js/xyGraph.js"</span>)
         (<span class="hljs-name">javascript</span> <span class="hljs-string">"js/pieGraph.js"</span>) ) ) )

(<span class="hljs-name">de</span> go ()
   (<span class="hljs-name">server</span> <span class="hljs-number">8080</span> <span class="hljs-string">"!work"</span>) )
</code></pre><p><em>Note: go back to the previous tutorials in the <a target="_blank" href="https://picolisp-explored.com/series/web-app">Web app series</a> if you don't understand this.</em></p>
<p>You can start the server with:</p>
<pre><code>pil <span class="hljs-operator">&lt;</span>filename<span class="hljs-operator">&gt;</span> <span class="hljs-operator">-</span>go
</code></pre><p>and should be able to see a blank HTML page on http://localhost:8080. With Ctrl+U (Firefox), you can view the page's source code and double-check that the JavaScript sources are included:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654529523974/pO4XRW3xO.png" alt="image.png" /></p>
<hr />
<p>Now, all we need to do is create the data array and call the Javascript function. First of all, we define a global variable <code>*Data</code> (eventually, this data could for example come from a database):</p>
<pre><code><span class="hljs-string">(setq</span> <span class="hljs-string">*Data</span> <span class="hljs-string">(90</span> <span class="hljs-number">230</span> <span class="hljs-number">180</span> <span class="hljs-number">300</span> <span class="hljs-number">110</span> <span class="hljs-number">195</span><span class="hljs-string">))</span>
</code></pre><p>Then we create a div with the id <code>xyGraph</code> within the HTML-body:</p>
<pre><code>(<span class="hljs-name">&lt;div&gt;</span> '(<span class="hljs-name">id</span> . <span class="hljs-string">"xyGraph"</span>))
</code></pre><hr />
<p>Then we call the JavaScript function we just included. Since JavaScript uses arrays, not list, we need to convert our list to a JavaScript array with help from the <code>glue</code> function. From the <a target="_blank" href="https://software-lab.de/doc/index.html">docs</a>:</p>
<blockquote>
<p> <code>(glue 'any 'lst) -&gt; sym</code><br />Builds a new transient symbol (string) by <code>pack</code>ing the <code>any</code> argument between the individual elements of <code>lst</code>.</p>
<pre><code>    : (glue <span class="hljs-string">","</span> '(a b <span class="hljs-built_in">c</span> d))
    -&gt; <span class="hljs-string">"a,b,c,d"</span>
</code></pre></blockquote>
<p>Applied to our example:</p>
<pre><code>(<span class="hljs-name">&lt;javascript&gt;</span>
   <span class="hljs-string">" var data = ["</span> (<span class="hljs-name">glue</span> <span class="hljs-string">", "</span> *Data) <span class="hljs-string">"]; "</span>
   <span class="hljs-string">"drawXYGraph(data, xyGraph, 400, 400); "</span> )
</code></pre><p>And we see the graph appearing:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654530093622/inCcQjX9O.png" alt="image.png" /></p>
<hr />
<h3 id="heading-the-finished-demo-page">The finished demo page</h3>
<p>I have expanded the example above by an input field that allows the user to add new data points to the list, which causes the graph to update automatically. You can test it out <a target="_blank" href="https://picolisp.com/blog/src/d3-demo.l">here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654530368422/DAQ-UWvZ1.gif" alt="d3demo.gif" /></p>
<p>The full source code can be viewed <a target="_blank" href="https://gitlab.com/picolisp-blog/web-applications/-/tree/main/d3-demo">here</a>.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>http://d3js.org</li>
<li>https://www.tutorialsteacher.com/d3js/create-pie-chart-using-d3js</li>
<li>https://bl.ocks.org/farazshuja/afd5e5f492fd00dd0ac4644d53716f4e</li>
<li>https://www.tutorialsteacher.com/d3js/create-bar-chart-using-d3js</li>
<li>https://software-lab.de/doc/index.html</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Improving User Experience with Server-Sent Events]]></title><description><![CDATA[In the last two posts, we have built a little app that shows the current location and displays the nearest ice cream shops:

https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1
https://picolisp-explored.com/an-openstreetmap-ap...]]></description><link>https://picolisp-explored.com/improving-user-experience-with-server-sent-events</link><guid isPermaLink="true">https://picolisp-explored.com/improving-user-experience-with-server-sent-events</guid><category><![CDATA[lisp]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[mobile app development]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 31 May 2022 10:42:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1653920109745/tantz3awm.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last two posts, we have built a little app that shows the current location and displays the nearest ice cream shops:</p>
<ul>
<li>https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1</li>
<li>https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-2</li>
</ul>
<p>The app gets the location data from the GPS module and the ice cream locations via the OpenStreetMap API. This means that there are a lot of external factors which can cause our app to slow down or even stop working. Now, in order to keep the user happy, let's add at least some small feedback which helps the user to understand what is currently going on.</p>
<p>In order to trigger this feedback we will use <strong>Server-Sent Events</strong>.</p>
<hr />
<h3 id="heading-what-are-server-sent-events">What are Server-Sent Events?</h3>
<p>In a typical website, the client (for example the front-end of our app) <em>requests</em> the server for content and receives data as <em>response</em>. However, there might be cases when the server needs to push updated data to the client without the client asking for it. For this purpose, <a target="_blank" href="https://en.wikipedia.org/wiki/Server-sent_events">server-sent events</a> have been standardized as part of HTML5 by the W3C in 2008. It is supported by all major browsers.</p>
<p>Basically, server-sent events establish a uni-directional connection from the server to the client. It allows to update a specific DOM component without having to reload the whole page. In PicoLisp, we can implement Server-Sent Events with just a couple of lines of code.</p>
<hr />
<h3 id="heading-specifying-the-dom-component-in-the-front-end">Specifying the DOM component in the front end</h3>
<p>In the first step, let's define the front end component that should update itself with help of server-sent events. In case of our app, we choose to add some text below the app title. For example, while the request to the OSM API is running, we want to display the text <em>"Fetching Ice Cafes..."</em>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653921982454/iBEPhWPK1.png" alt="image.png" /></p>
<p>By displaying this text, the user knows that our app is still waiting for data.</p>
<hr />
<p>First of all, let's define the DOM element that should receive dynamic updates.</p>
<pre><code>(&lt;h6&gt; '((id . <span class="hljs-string">"icecream"</span>) <span class="hljs-string">"red"</span>)) )
</code></pre><p>With this we define a h6-element with the id "icecream" and the CSS class "red" (which simply prints red text as defined in the pre-installed <code>lib.css</code>) using in-line CSS styling. (Read <a target="_blank" href="https://picolisp-explored.com/web-application-programming-in-picolisp-adding-css">here</a> for more on in-style CSS).</p>
<p>Now we connect this element to receive server-sent event updates, by using the <a target="_blank" href="https://picolisp.com/wiki/?ServerSentEvents"><code>serverSentEvent</code> function</a>:</p>
<blockquote>
<p><code>(serverSentEvent "id" 'var . prg)</code></p>
<p>The first argument should be the ID of a DOM component in the page. (...) The ID should be unique within this program session for all <code>serverSentEvent</code> use cases, as it is also used as a key to an internal association table.  </p>
<p>The second argument <code>var</code> is a variable which is automatically bound to a socket as soon as the client establishes the event stream connection, i.e. shortly after the page with the embedded call to serverSentEvent is displayed. In essence, this socket is then connected to the DOM component "id".</p>
<p>When that happened, the <code>prg</code> body is executed to set up everything needed for further event sending via the socket in <code>var</code>. <code>var</code> is automatically set to <code>NIL</code>, and the socket closed, when the client closes the connection. Then the server should clean up whatever is necessary.</p>
</blockquote>
<hr />
<p>Basically this means that we need to define a global variable for the <code>var</code> parameter which is used to establish the connection. Let's create a new global called <code>*Sse</code> and add it to our globals list:</p>
<pre><code>(local) (<span class="hljs-operator">*</span>Sse <span class="hljs-operator">*</span>IceCreamOsm <span class="hljs-operator">*</span>Latitude <span class="hljs-operator">*</span>Longitude <span class="hljs-operator">*</span>IceList <span class="hljs-operator">*</span>SupermarketList)
</code></pre><p>Now we can call <code>serverSentEvents</code> somewhere on our page. The position is not really relevant, but it might sense to keep it close to the connected DOM element to keep the code readable. Since we just want to pass-through some simple status text, we do not need to define any <code>prg</code>. So all we need is to add this line:</p>
<pre><code>(<span class="hljs-name">serverSentEvent</span> <span class="hljs-string">"icecream"</span> '*Sse)
</code></pre><hr />
<h3 id="heading-defining-the-server-side">Defining the server side</h3>
<p>The counter part to <code>serverSentEvent</code> is <code>serverSend</code>. As the name already says, <code>serverSend</code> defines when and which data is sent to the client.</p>
<blockquote>
<p> <code>serverSend</code> may be called anytime while the connection is open: </p>
<p><code>(serverSend 'sock . prg)</code></p>
<p> It sends all output (HTML text) generated by <code>prg</code> to the inner HTML of the component connected to the socket sock.</p>
</blockquote>
<hr />
<p>Let's use it to print out error messages if GPS is not enabled or available, and otherwise the GPS data of the current location. </p>
<p>The <code>task</code> function is checking the position every 6 seconds. Within this check, let's generate a string that is sent to the <code>*Sse</code> socket linked to the <code>icecream</code> component. This string is then pushed to the client and displayed without updating anything else. </p>
<pre><code>(task <span class="hljs-number">-6000</span> <span class="hljs-number">1000</span>
   (nond
      ((location?)
         (serverSend <span class="hljs-operator">*</span>Sse ,<span class="hljs-string">"Please enable \"Location\""</span>) )
      ((gps)
         (serverSend <span class="hljs-operator">*</span>Sse ,<span class="hljs-string">"Waiting for location"</span>) )
      (NIL
         (setq <span class="hljs-operator">*</span>Latitude (car @)  <span class="hljs-operator">*</span>Longitude (cdr @))
         (serverSend <span class="hljs-operator">*</span>Sse (prin (lat <span class="hljs-operator">*</span>Latitude) <span class="hljs-string">", "</span> (lon <span class="hljs-operator">*</span>Longitude))) ) ) ) )
</code></pre><p><em>Note: The comma <code>,</code> is a read-macro in case you want to add <a target="_blank" href="https://picolisp-explored.com/creating-a-todo-app-6-multi-language-support">multi-language support</a>. If you only use one language, it is not needed.</em></p>
<hr />
<p>Likewise, we can also add a server-sent update each time any of the buttons is pressed. Since the button press calls a function <code>icecream</code> (defined in <code>lib.l</code>), we can call <code>serverSend</code> there:</p>
<pre><code>(<span class="hljs-name">de</span> iceCream (<span class="hljs-name">Msg</span> Osm Category Type)
   (<span class="hljs-name">serverSend</span> *Sse Msg)
   (<span class="hljs-name">ssl</span> <span class="hljs-string">"overpass-api.de"</span>
      ...
</code></pre><p>where <code>Msg</code> is specified in the button press:</p>
<pre><code>(gui '(+Style +Button) <span class="hljs-string">"button-icon bg-white mb-5 mx-3"</span>
   T <span class="hljs-string">"icecream/img/supermarket.png"</span>
   '(setq *SupermarketList (iceCream ,<span class="hljs-string">"Fetching Supermarkets ..."</span> *IceCreamOsm <span class="hljs-string">"shop"</span> <span class="hljs-string">"supermarket"</span>)) ) )
</code></pre><p>With these small modifications, we receive a much more user-friendly app that gives a minimum of feedback of what is internally going on.</p>
<hr />
<h3 id="heading-wrap-up">Wrap-up</h3>
<p>With server-sent events, we have an elegant and light-weigth way to update some DOM components dynamically without any JavaScript.</p>
<p>Note that unfortunately the map itself cannot be updated this way, because it calls some more complex JavaScript functions that are not updated like this. So if you want to have a dynamic change on the OpenStreetMap (like required for navigation etc.), you have to reload the whole page, for example with the <a target="_blank" href="https://picolisp-explored.com/web-apps-an-animation"><code>auto</code> function</a>.</p>
<hr />
<p>The source code for this example can be found <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/tree/main/icecream">here</a> and <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/blob/main/icecream.zip">this is the zip file</a> for PilBox.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://picolisp.com/wiki/?ServerSentEvents</li>
<li>https://en.wikipedia.org/wiki/Server-sent_events</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[An OpenStreetMap App written in PicoLisp (Pt. 3)]]></title><description><![CDATA[This is the third part of a little series which explains how to write a small app in PicoLisp that shows the nearest ice cream shops nearby. You might want to read the first two parts first:

https://picolisp-explored.com/an-openstreetmap-app-written...]]></description><link>https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-3</link><guid isPermaLink="true">https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-3</guid><category><![CDATA[lisp]]></category><category><![CDATA[mobile app development]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 24 May 2022 10:09:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652865046510/Gebdwij7j.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the third part of a little series which explains how to write a small app in PicoLisp that shows the nearest ice cream shops nearby. You might want to read the first two parts first:</p>
<ul>
<li>https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1</li>
<li>https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-2</li>
</ul>
<hr />
<p>At the end of the last post, we had a little app that displays our current location on Open Street Maps. Now we want to find all icecream shops nearby with help of the <a target="_blank" href="https://overpass-turbo.eu/">Open Street Map API</a>.</p>
<hr />
<h3 id="heading-working-with-the-open-street-map-api">Working with the Open Street Map API</h3>
<p>OpenStreetMap has a convenient API that lets you search for specific facilities. There is also a frontend on https://overpass-turbo.eu/ to play around and understand how it works. For example, this query returns all drinking water positions:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652866148798/RuoRQarcK.png" alt="image.png" /></p>
<p>If you navigate to "Export", you can download the raw query data, which looks like this:</p>
<pre><code><span class="hljs-selector-tag">node</span>
  <span class="hljs-selector-attr">[amenity=drinking_water]</span>
  (52<span class="hljs-selector-class">.50882953708777</span>,13<span class="hljs-selector-class">.415980339050291</span>,52<span class="hljs-selector-class">.53089536100559</span>,13<span class="hljs-selector-class">.46125602722168</span>);
<span class="hljs-selector-tag">out</span>
</code></pre><p>The actual query is surrounded by <code>node</code> and <code>out</code>. The first parameter is <code>[amenity=drinking_water]</code>, where <code>amenity</code> is the "key" and <code>drinking_water</code> is the "value". Besides "drinking_water", there are of course also other amenities we can look for which are listed <a target="_blank" href="https://wiki.openstreetmap.org/wiki/Key:amenity">here</a>. There is also an amenity called "Ice Cream" - exactly what we are looking for! The second parameter in the example is the area we are searching, defined by the North, East, South and West borders.</p>
<hr />
<p>With this information, we can already form a little CURL request to play around with the queries:</p>
<pre><code> <span class="hljs-attribute">curl</span> 'https://overpass-api.de/api/interpreter?data=node%<span class="hljs-number">5</span>Bamenity=ice_cream%<span class="hljs-number">5</span>D(<span class="hljs-number">52</span>.<span class="hljs-number">559290421668074</span>,<span class="hljs-number">13</span>.<span class="hljs-number">387999534606934</span>,<span class="hljs-number">52</span>.<span class="hljs-number">580522509085554</span>,<span class="hljs-number">13</span>.<span class="hljs-number">416066169738768</span>);out;'
</code></pre><p>And we get back an xml-file with one ice cream shop per node:</p>
<pre><code><span class="hljs-operator">&lt;</span>?xml version<span class="hljs-operator">=</span><span class="hljs-string">"1.0"</span> encoding<span class="hljs-operator">=</span><span class="hljs-string">"UTF-8"</span>?<span class="hljs-operator">&gt;</span>                                                              
<span class="hljs-operator">&lt;</span>osm version<span class="hljs-operator">=</span><span class="hljs-string">"0.6"</span> generator<span class="hljs-operator">=</span><span class="hljs-string">"Overpass API 0.7.57 93a4d346"</span><span class="hljs-operator">&gt;</span>                                        
<span class="hljs-operator">&lt;</span>note<span class="hljs-operator">&gt;</span>The data included in <span class="hljs-built_in">this</span> document <span class="hljs-keyword">is</span> <span class="hljs-keyword">from</span> www.openstreetmap.org. The data <span class="hljs-keyword">is</span> made available u
nder ODbL.&lt;<span class="hljs-operator">/</span>note<span class="hljs-operator">&gt;</span>                                                                                   
<span class="hljs-operator">&lt;</span>meta osm_base<span class="hljs-operator">=</span><span class="hljs-string">"2022-05-18T09:40:07Z"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>                                                             

  <span class="hljs-operator">&lt;</span>node id<span class="hljs-operator">=</span><span class="hljs-string">"753361477"</span> lat<span class="hljs-operator">=</span><span class="hljs-string">"52.5699404"</span> lon<span class="hljs-operator">=</span><span class="hljs-string">"13.4106207"</span><span class="hljs-operator">&gt;</span>                                           
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:city"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Berlin"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>                                                                 
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:country"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"DE"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>                                                                  
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:housenumber"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"4"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>                                                               
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:postcode"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"13187"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:street"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Berliner Straße"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:suburb"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Pankow"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"amenity"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"ice_cream"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"contact:facebook"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"https://www.facebook.com/Eisspatz/"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"cuisine"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"ice_cream"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"name"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Eisspatz"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"opening_hours"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Sa-Mo 12:00-20:00; Tu-Fr 12:00-19:00"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
  <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>node<span class="hljs-operator">&gt;</span>
  <span class="hljs-operator">&lt;</span>node id<span class="hljs-operator">=</span><span class="hljs-string">"2936989595"</span> lat<span class="hljs-operator">=</span><span class="hljs-string">"52.5682129"</span> lon<span class="hljs-operator">=</span><span class="hljs-string">"13.3993821"</span><span class="hljs-operator">&gt;</span>
    ...
  <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>node<span class="hljs-operator">&gt;</span>
   ...
 <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>osm<span class="hljs-operator">&gt;</span>
</code></pre><p>Now we don't only want to find ice cream shops, but also supermarkets (because these might sell icecream, too). The key-value pair for supermarkets in the OpenStreetMap API is <code>[shop=supermarket]</code>. With this we can get the data we need, but there is still some work to do:</p>
<ol>
<li>Call the API from within PicoLisp,</li>
<li>Convert the XML data into a nicer data format.</li>
</ol>
<hr />
<h3 id="heading-calling-the-api-from-picolisp">Calling the API from PicoLisp</h3>
<p>This task could actually be easy - simply use the <code>call</code> function to invoke a system command and use <code>curl</code>: <code>(call "curl" "https://&lt;URL&gt;")</code>. Unfortunately, it doesn't work, because the Android system does not give our PilBox app permissions to execute <code>curl</code>.</p>
<p>Luckily we can use the built-in ``ssl``` function for this as well. The syntax is easy:</p>
<blockquote>
<p><code>(ssl 'host 'path . prg) -&gt; any</code><br />Executes <code>prg</code> in an input stream (using <code>in</code>) from "@bin/ssl"  requesting <code>path</code> from <code>host</code>. </p>
</blockquote>
<p>The host is "overpass-api.de" and the path is <code>/api/...</code>. So our request looks like this:</p>
<pre><code class="lang-none">(ssl "overpass-api.de"
   (pack 
      "/api/interpreter?data=node++[amenity=ice_cream]++("
      &lt;Location-Borders&gt;
      ");out;" )
   ( &lt;what to do with the data&gt; )
</code></pre>
<hr />
<p>How do we get the four borders of our map? This is actually easy because it is already tracked within the app. In order to use this data, let's define another global variable <code>*IceCreamOsm</code>:</p>
<pre><code class="lang-none">(local) (*IceCreamOsm *Latitude *Longitude)
</code></pre>
<p>and set the OpenStreetMap <code>*Osm</code> variable to it (for example within <code>start</code>):</p>
<pre><code class="lang-none">(start
   (scl 6)
   (setq *Osm '*IceCreamOsm)
   (task -6000 1000
      ...
</code></pre>
<p>If you now type <code>*IceCreamOsm</code> in the <a target="_blank" href="https://picolisp-explored.com/mobile-app-development-in-picolisp-v-getting-a-remote-shell-to-your-pc">pty</a> REPL, you will see a list with four values (representing North, South, West, East) and the map's zoom factor. </p>
<pre><code class="lang-none">icecream: *IceCreamOsm
-&gt; ((142536613 . 142609643) (193327006 . 193468454) . 12)
</code></pre>
<hr />
<p>Now all we need to do is to convert these data back to the format that the overpass API is expecting. This is simple math as explained in <a target="_blank" href="https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1">this post</a>: subtracting 90° from the latitude and 180° from the longitude, and format the output according to the scale. For example, we can get the formatted North coordinate with this:</p>
<pre><code class="lang-none">(format  (- (caar *IceCreamOsm) 90.0) *Scl )
</code></pre>
<p>However we should also catch the case that <code>*IceCreamOsm</code> is empty because the map is not drawn yet. Let's add a fallback solution so that we canstill fetch data in the background while the map is loading.</p>
<pre><code class="lang-none">(format
   (- (or (caar Osm) (- *Latitude 0.1)) 90.0)
   *Scl )
</code></pre>
<p>This sets the North boundary to 0.1° distance from the current location, which corresponds roughly to a 11 km radius around the current location.</p>
<hr />
<h3 id="heading-converting-from-xml-to-list-format">Converting from XML to list format</h3>
<p>Now we need to format the XML output on based on our needs. As we could see above, the output looks somewhat like this:</p>
<pre><code>  <span class="hljs-operator">&lt;</span>node id<span class="hljs-operator">=</span><span class="hljs-string">"753361477"</span> lat<span class="hljs-operator">=</span><span class="hljs-string">"52.5699404"</span> lon<span class="hljs-operator">=</span><span class="hljs-string">"13.4106207"</span><span class="hljs-operator">&gt;</span>                                           
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:city"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Berlin"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>                                                                 
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:country"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"DE"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>                                                                  
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:housenumber"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"4"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>                                                               
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:postcode"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"13187"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:street"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Berliner Straße"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"addr:suburb"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Pankow"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"amenity"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"ice_cream"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"contact:facebook"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"https://www.facebook.com/Eisspatz/"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"cuisine"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"ice_cream"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"name"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Eisspatz"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>tag k<span class="hljs-operator">=</span><span class="hljs-string">"opening_hours"</span> v<span class="hljs-operator">=</span><span class="hljs-string">"Sa-Mo 12:00-20:00; Tu-Fr 12:00-19:00"</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
  <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>node<span class="hljs-operator">&gt;</span>
</code></pre><p>This is a lot of information we don't actually need. Let's keep it simple and only extract the shop name and the GPS position in the following format: <code>(&lt;name&gt; &lt;latitude&gt; . &lt;longitude&gt;)</code>. This will form a list similar to this one:</p>
<pre><code class="lang-none">(("Delabuu" 142545086 . 193362049) ("Eiscafé Gelato degli Angeli" 142587148 . 193401989) ("Eisspatz" 142569940 . 193410621) ("Tribeca" 142537430 . 193421053) ("Eis Henri" 142545990 . 193390389) ("Hijís Gelateria" 142551831 . 193413717) ("Eis &amp; Back" 142551954 . 193366761) ("Eislabor" 142541762 . 193422135) ...)
</code></pre>
<hr />
<p>In order to work conveniently with XML data, we can import the <code>xm.l</code> library in the `once`` function. </p>
<pre><code class="lang-none">(once
   (load "@lib/xm.l") )
</code></pre>
<p>Similarly to the <a target="_blank" href="https://picolisp-explored.com/how-to-create-a-restful-api-to-the-picolisp-database">json</a>-library, the <code>xml</code> function takes XML data and provides some functions to transform it to a list. First we check if the xml output is valid (<code>xml?</code>), and if yes, we travel through the whole XML-tree and visit each valid node.</p>
<pre><code class="lang-none">(when (xml?)
   (for L (xml)
      (when (== 'node (car L))
</code></pre>
<p>For each valid node, we want to take the <code>lat</code> and <code>lon</code> attributes from the root as well as the <code>name</code> attribute, and <code>cons</code> these three items to a list. Then we form a final output list with <code>make</code>.</p>
<pre><code class="lang-none">(make 
   (cons
      (attr
         (find '((X) (= '(k . "name") (caadr X))) (cddr L))
         'v )
      (+ 90.0 (format (attr L 'lat) *Scl))
      (+ 180.0 (format (attr L 'lon) *Scl)) )
</code></pre>
<hr />
<h3 id="heading-fetching-the-data-on-button-press">Fetching the data on button press</h3>
<p>We still need to define when the data should actually be fetched. Let's put the <code>ssh</code> function from above into a function <code>iceCream</code> and define it in a separate file <code>lib.l</code> to keep our code more readable. Also we can replace the API variables by local variables:</p>
<pre><code class="lang-none">(de iceCream (Osm Category Type)
   (ssl "overpass-api.de"
</code></pre>
<p>where <code>Osm</code> is the current map data and <code>Category</code> and <code>Type</code> are the key/value pairs from the Overpass API. Then we load the <code>lib.l</code> file in the <code>once</code> function.</p>
<pre><code class="lang-none">(once
   (scl 6)
   (load "@lib/xm.l" "icecream/lib.l") )
</code></pre>
<p>Next, we define the output lists as <code>*IceList</code> (for ice cream shops) and <code>*SupermarketList</code> (for the supermarkets):</p>
<pre><code class="lang-none">(local) (*IceCreamOsm *Latitude *Longitude *IceList *SupermarketList)
</code></pre>
<p>Now we can add the <code>iceCream</code> function as action to our button and store the output in the global variables.</p>
<pre><code class="lang-none">(gui '(+Style +Button) "button-icon bg-white mb-5 mx-3"  T "icecream/img/ice.png"
   '(setq *IceList (iceCream *IceCreamOsm "amenity" "ice_cream")) )

(gui '(+Style +Button) "button-icon bg-white mb-5 mx-3" T "icecream/img/supermarket.png"
   '(setq *SupermarketList (iceCream IceCreamOsm "shop" "supermarket")) ) )
</code></pre>
<hr />
<h3 id="heading-displaying-the-data-on-the-map">Displaying the data on the map</h3>
<p>Finally we can display the data in our map by looping over the <code>*IceList</code> and <code>*SupermarketList</code> respectively and add a little icon and the shop name with the <code>&lt;poi&gt;</code> function.</p>
<pre><code class="lang-none">(for Ice *IceList
   (&lt;poi&gt; (cadr Ice) (cddr Ice)
      "icecream/img/ice-mini.png" "0.1" "1.0" (car Ice) 0 "red") )
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652881475823/5NVQ1quGb.png" alt="image.png" /></p>
<hr />
<p>Unfortunately the Overpass API sometimes seem a bit unreliable. It can take quite a long time to receive back the data, and sometimes there is no valid data at all.  In the last (and final) post of this series, we will add <a target="_blank" href="https://picolisp.com/wiki/?ServerSentEvents">Server-Side Events</a> to let the user know what is going on.</p>
<p>You can find the final code for this app (including server-sent events) under <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/tree/main/icecream">this link</a> and the <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/blob/main/icecream.zip">zip file here</a>.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://software-lab.de/doc/index.html</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[An OpenStreetMap App written in PicoLisp (Pt. 2)]]></title><description><![CDATA[Now it's almost summer and definitely time to finish the blog post about the PicoLisp Ice Cream Finder! This is a continuation of this post, where we explained how to work with Google Maps and OpenStreetView.
The app's purpose is simple: It should pi...]]></description><link>https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-2</link><guid isPermaLink="true">https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-2</guid><category><![CDATA[lisp]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[app development]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Wed, 18 May 2022 08:32:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652697794903/1ceZnhL-E.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Now it's almost summer and definitely time to finish the blog post about the PicoLisp Ice Cream Finder! This is a continuation of <a target="_blank" href="https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1">this post</a>, where we explained how to work with Google Maps and OpenStreetView.</p>
<p>The app's purpose is simple: It should pick up the current location via GPS and display all ice cream shops and supermarkets nearby, based on the results from the OpenStreetMap API.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647469007977/8O_8hYTnN.png" alt="grafik.png" /></p>
<hr />
<h3 id="heading-setting-up-the-working-environment">Setting up the Working Environment</h3>
<p>First of all, let's set up a working environment that allows us to test and modify our code in a fast and efficient way. In order to do this, we will use the <a target="_blank" href="https://picolisp-explored.com/mobile-app-development-in-picolisp-v-getting-a-remote-shell-to-your-pc">PilBox Pseudo-Terminal</a>.</p>
<p>First of all, let's create a simple template. It contains a file <code>App.l</code> which defines the app title as well as the app logo and some basic CSS files. You can find the template <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/blob/main/iceCreamApp-Template.zip">here</a> as a reference. Compress the template folder to a .zip-File and send it to the PilBox app on your phone, for example via termux share (or email).</p>
<p>After opening the zip-file in the app it should look like this: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652717719637/PQNsfX_IC.png" alt="image.png" /></p>
<hr />
<p>Next we expand the .zip-File in the working directory on our PC and start the pty from the same directory. This way we have the same relative paths and are able to use <code>pbPut</code> and <code>pbGet</code> to copy files.</p>
<pre><code class="lang-none">$ cd &lt;your favorite picolisp directory&gt;
$ unzip iceCreamApp-Template.zip
$ pil ~/pil21/bin/pty &lt;your phone's IP&gt;
android:
</code></pre>
<p><em>If you have trouble with the tty, read <a target="_blank" href="https://picolisp-explored.com/mobile-app-development-in-picolisp-v-getting-a-remote-shell-to-your-pc">here</a></em>.</p>
<p>Note that PilBox should be open on the phone for the tty to work. After we got the connection, we can check the app folder on the phone:</p>
<pre><code class="lang-none">android: (call "ls")
App.l    JAVA    PID      RPLY  Version  favicon.ico  lib      loc   src
BOSS     LISP    PIL-369  RQST  bin      icecreamPt1  lib.css  log   steps.rc
COPYING  Locale  Port     UUID  db       img          lib.l    log-  tls
</code></pre>
<p>This shows the folder <code>icecreamPt1</code> which includes the template files of the app, as well as <code>PIL-369</code> which is the internal  app's name on my phone (unfortunately my Samsung smartphone seems to rename .zip-files before opening them in external apps). </p>
<hr />
<p>Now for testing purposes, let's rename the app in <code>App.l</code> from "PicoLisp App Stub" to "Mia' Ice Cream Finder" on the PC and transfer it to the phone like this:</p>
<pre><code class="lang-none">android: (pbPut "&lt;appname&gt;/App.l")
</code></pre>
<p><em>In this example, the appname is "icecreamPt1" because this is how I called it in the repository (link in the end).</em></p>
<p>Now the app title should be changed on your smartphone as well.</p>
<hr />
<h3 id="heading-defining-the-general-app-layout">Defining the general app layout</h3>
<p>I like starting with the easy things, like setting the header and main layout features. Let's define a function <code>work</code> that gets called. Inside <code>work</code>, we call <code>pilbox</code>, which allows us to define the App header by ourselves instead of the pre-defined "PilBox" text.</p>
<pre><code class="lang-none">"Mias Ice Cream Finder (Pt. 1)" 

(de work ()
   (pilbox
      (&lt;h5&gt; "fh" "Mia's Ice Cream Finder") )
   (menu "Mia's Ice Cream Finder") )

(work)
</code></pre>
<p><em>Note: the CSS-class <code>fh</code> is defined in the pre-installed <code>@lib/phone.css</code>.</em></p>
<p>Next, we can define the background and styles with bootstrap (<a target="_blank" href="https://picolisp-explored.com/web-application-programming-in-picolisp-adding-css">here for more info</a>). We display a title called "Want ice cream?" and a search box with two buttons. The buttons can be pressed, but there is no function tied to it yet.</p>
<p>This is the PicoLisp code for that:</p>
<pre><code class="lang-none">(de work ()
   (pilbox
      (&lt;h5&gt; "fh" "Mia's Ice Cream Finder") )
   (menu "Mia's Ice Cream Finder"
      (form NIL
         (&lt;div&gt; "bg-light container-sm border"
            (&lt;div&gt; "d-flex flex-column "
               (&lt;h3&gt; "mt-5 mb-4 d-flex justify-content-center" "Want ice cream?" )
               (&lt;div&gt; "mb-3 d-flex justify-content-center"
                  (&lt;p&gt; NIL "Find ice cream near your current location!") )
               (&lt;div&gt; "d-flex justify-content-center"
                  # Search button for ice cafe
                  (gui '(+Style +Button) "button-icon bg-white mb-5 mx-3"
                     T "icecreamPt1/img/ice.png" NIL)
                  # Search button for supermarket
                  (gui '(+Style +Button) "button-icon bg-white mb-5 mx-3"
                     T "icecreamPt1/img/supermarket.png" NIL) ) ) ) ) ) )
</code></pre>
<p>and this is how it looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652713894879/H91qlRCmj.png" alt="image.png" /></p>
<hr />
<h3 id="heading-getting-the-current-location">Getting the current location</h3>
<p>Now comes the interesting point: Let's take our current position and display it on OpenStreetMap. First of all, we import the relevant name spaces, some global variables and the <code>gis.l</code> library:</p>
<pre><code class="lang-none">"Mias Ice Cream Finder (Pt. 1)" "@lib/gis.l"

(symbols 'icecream 'gis 'android 'pico)

(local) (*Latitude *Longitude)
</code></pre>
<p>Now we can fetch the current position with the <code>gps</code> function, just like in the <a target="_blank" href="https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1">previous post on GPS</a>. But this time we want to get the data in the background: let's refresh the location every 6 seconds. Periodic tasks can be realized with the <code>task</code> function (here you can <a target="_blank" href="https://picolisp-explored.com/picolisp-explored-the-task-function">more information on <code>task</code></a>).</p>
<pre><code class="lang-none">(start
   (scl 6)
   (task -6000 1000
      (nond
         ((location?) NIL )
         ((gps) NIL )
         (NIL
            (setq *Latitude (car @)  *Longitude (cdr @)) ) ) ) )
</code></pre>
<p>What does this do?</p>
<ol>
<li>First, it sets the scale for integer calculations to 6 (if you don't know the <code>scl</code> function, check out <a target="_blank" href="https://picolisp-explored.com/floating-point-vs-fixed-point-arithmetics">this post</a>).</li>
<li>Then we define a periodic task, executed every 6 seconds. The first time it is executed one second after starting the app.</li>
<li><code>nond</code> is a multi-way conditional which executes if the argument evaluates to <code>NIL</code>. We distinguish three cases: <ul>
<li><code>(location?)</code> is false, i. e. GPS permissions are not given,</li>
<li><code>(gps)</code> is <code>NIL</code>, i. e. GPS data is not (yet) available</li>
<li><code>NIL</code>: the exit condition - GPS data is available and stored in the global variables <code>*Latitude</code> and <code>*Longitude</code>. </li>
</ul>
</li>
</ol>
<hr />
<p>Let's test it: Now the app asks for GPS permissions at start up. If we confirm with "yes", we can execute <code>(gps)</code> in the tty and see the current location:</p>
<pre><code class="lang-none">icecream: (gps)
-&gt; (142520664 . 193401665)
</code></pre>
<p><em>side note: NOT my exact location 😄</em></p>
<hr />
<p>Nice! So let's use this data and display it on the map.</p>
<pre><code class="lang-none">(&lt;div&gt; "map"
   (&lt;osm&gt; *Latitude *Longitude 12)
   (&lt;poi&gt; *Latitude *Longitude
      "icecreamPt1/img/here.png" "0.1" "1.0"
      "" 0 "black" ) ) ) ) )
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652717498516/92i-i8VP5.png" alt="image.png" /></p>
<hr />
<p>In the next post, we will see how to use the OpenStreetMap API to fetch the supermarket and ice cream shop position and display them in the map. Also, we will use <code>ServerSideEvents</code> to display some information.</p>
<p>You can find the source code up to this point <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/tree/main/icecreamPt1">here</a> and the zip-File <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/blob/main/icecream-Pt1.zip">here</a>.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>Ice Cream Icon by https://www.irasutoya.com/2015/07/3.html</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[PicoLisp Explored: Writing your own little Chat App]]></title><description><![CDATA[In the last post, we saw how to use the task function to repeat tasks periodically or listen for asynchronous events. Now let's demonstrate it using a little example - a simple chat demo app. 
(This example was also included in the pil64-version of P...]]></description><link>https://picolisp-explored.com/picolisp-explored-writing-your-own-little-chat-app</link><guid isPermaLink="true">https://picolisp-explored.com/picolisp-explored-writing-your-own-little-chat-app</guid><category><![CDATA[Functional Programming]]></category><category><![CDATA[unix]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Fri, 29 Apr 2022 07:53:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1650821053874/abfKDgZoO.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last post, we saw how to use the <code>task</code> function to repeat tasks periodically or listen for asynchronous events. Now let's demonstrate it using a little example - a simple <strong>chat demo app</strong>. </p>
<p><em>(This example was also included in the pil64-version of PicoLisp - if you have it installed, you can find the source code in the <code>misc/</code> folder of your installation.)</em></p>
<hr />
<h3 id="heading-how-it-works">How it works</h3>
<p>The requirements to our app are very simple: We want to open a TCP port which is dedicated to communication. Any client can connect to this port, for example with <a target="_blank" href="https://en.wikipedia.org/wiki/Telnet">telnet</a>, and send and receive messages. </p>
<p>The little GIF below illustrates how the final app should work:</p>
<ul>
<li>All "chat users" are connecting to port 4004 in localhost.</li>
<li>If a new user joins the "room", the other users receive a notification.</li>
<li>If a user sends a message, the others receive it together with the name prompt.</li>
<li>If a user leaves the room, the other users are notified too.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650795918667/AXbdZHR7U.gif" alt="chatapp-demo.gif" /></p>
<hr />
<h3 id="heading-file-descriptors-and-forks-in-picolisp">File Descriptors and Forks in PicoLisp</h3>
<p>All users are connecting to the same port (localhost:4004), where each one is creating an individual socket to communicate with each other. So let's take a look at socket handling in PicoLisp now. </p>
<p>We want the port 4004 to stay open constantly for any client to connect. At the same time, everyone connecting to the port receives their own <strong>socket</strong> for communication. First, we create a new TCP port with the <code>port</code> function, which returns a <strong>file descriptor</strong> (read here for more on Unix file descriptors: <a target="_blank" href="https://en.wikipedia.org/wiki/Everything_is_a_file">Everything is a file</a>).</p>
<pre><code>(<span class="hljs-name">setq</span> *Port (<span class="hljs-name">port</span> <span class="hljs-number">4004</span>))
</code></pre><hr />
<p>Now that the port is open, the client can connect. However, we want to be able to handle <em>multiple</em> clients. How can we do this? We use another important Unix feature, which is <strong><a target="_blank" href="https://en.wikipedia.org/wiki/Fork_(system_call">forking</a>)</strong>.</p>
<p>A fork creates a copy of a process - a so-called <em>child-process</em>. Now we establish the following division of tasks: The <strong>parent process</strong> takes care of keeping the port open for clients to connect, while each <strong>child process</strong> inherits a socket for the client.</p>
<p>We realize this with a  <code>loop</code> function. The loop from the parent's process view looks like this:</p>
<ol>
<li>Waits until a client connects with <code>(listen *Port)</code>. If a client connects, a new file descriptor is created which is stored in the variable <code>*Sock</code>. </li>
<li>Then the process is forked and thus a child process is created.</li>
<li>The parent process closes the socked (<code>(close *Sock)</code>) as it is now handled by the <strong>child process</strong>.</li>
</ol>
<p>On the other hand, the <em>child process</em> as a copy of the parent is also stepping inside the loop, but instantly leaves the loop to take care of the socket handling. In PicoLisp, we can create a child process with <code>(fork)</code>. <code>fork</code> returns <code>NIL</code> in the child and the child's process ID in the parent.</p>
<p>These four lines take care of the parents/child process handling:</p>
<pre><code>(<span class="hljs-name"><span class="hljs-builtin-name">loop</span></span>
   (<span class="hljs-name">setq</span> *Sock (<span class="hljs-name">listen</span> *Port))
   (<span class="hljs-name">NIL</span> (<span class="hljs-name">fork</span>) (<span class="hljs-name">close</span> *Port))
   (<span class="hljs-name">close</span> *Sock) )
</code></pre><p>The line <code>(NIL (fork) (close *Port))</code> corresponds to the <strong>exit condition</strong> of the <code>for</code>-loop: If <code>for</code> is <code>NIL</code> (i. e., is a child), then the loop is left. If it is non-<code>NIL</code>, it means that we are in the parent process, so we will simply close the <code>*Sock</code> socket and start listening on the port again.</p>
<hr />
<h3 id="heading-registering-the-user-name">Registering the user name</h3>
<p>Now our child process has left the <code>loop</code> and is ready to interact with the user. First of all, we want to register the name. In order to print to the socket's output stream (like <code>telnet</code>), we use the <code>out &lt;FD&gt;</code> function, where  is the file descriptor of the socket.</p>
<pre><code>(<span class="hljs-name">out</span> *Sock
   (<span class="hljs-name">prin</span> <span class="hljs-string">"Please enter your name: "</span>)
   (<span class="hljs-name"><span class="hljs-builtin-name">flush</span></span>) )
</code></pre><p><em><code>(flush)</code> empties the buffered data by sending all to the output stream (= flushing). Alternatively, this can be triggered by a new line, i. e. by using <code>prinl</code> instead of <code>prin</code>.</em></p>
<p>Next, we read the username from the terminal with <code>(in &lt;FD&gt;)</code>. It takes the whole line as input.</p>
<pre><code>(<span class="hljs-name">in</span> *Sock (<span class="hljs-name">setq</span> *Name (<span class="hljs-name">line</span> T)))
</code></pre><p><em>Note: In a "real" app, you might want to add some input validation for the name variable.</em></p>
<hr />
<h3 id="heading-spreading-the-word-with-tell">Spreading the word with <code>tell</code></h3>
<p>Now let's announce to <strong>all connected clients</strong> that the new user has arrived. This kind of inter-process communication can be handled by <code>tell</code>.</p>
<p><code>tell</code> is a function that "knows" all process <em>family members</em> and can send them messages (family members are all children of the current process, as well as all other children of the parent process). It takes a symbol as argument specifying the exact message to be sent.</p>
<p>In our case, we want the message to print a text to the current output of the socket. In order to keep it flexible, let's maintain the text itself as a list.</p>
<pre><code>
(<span class="hljs-name">de</span> chat Lst
   (<span class="hljs-name">out</span> *Sock
      (<span class="hljs-name">mapc</span> prin Lst)
      (<span class="hljs-name">prinl</span>) ) )
</code></pre><p><code>chat</code> takes a list as argument, prints each list item and then a line feed. This can now be used within <code>tell</code>:</p>
<pre><code>(<span class="hljs-name">tell</span> 'chat <span class="hljs-string">"+++ "</span> *Name <span class="hljs-string">" arrived +++"</span>)
</code></pre><p>Everytime a new client connects to a port, all other connected clients will be informed with this text.</p>
<hr />
<h3 id="heading-handling-the-actual-chat-messages">Handling the actual chat messages</h3>
<p>Now finally, we come to use the <code>task</code> function that we've been talking about in the beginning. We create a task, i. e. waiting at the socket for user input. If there is input to this socket, we read it and directly hand it over to <code>tell</code>. Then we wait again for user input.</p>
<pre><code>(<span class="hljs-name">task</span> *Sock
   (<span class="hljs-name">in</span> @
      (<span class="hljs-name">tell</span> 'chat *Name <span class="hljs-string">"&gt; "</span> (<span class="hljs-name">line</span> T))
</code></pre><p>However, there is one exception: If the client ends the connection (for example with <code>Ctrl-]</code> in telnet), we spread this information with <code>tell</code> and then close the task. So, the complete <code>task</code> looks like this:</p>
<pre><code>(<span class="hljs-name">task</span> *Sock
   (<span class="hljs-name">in</span> @
      (<span class="hljs-name">ifn</span> (<span class="hljs-name">eof</span>)
         (<span class="hljs-name">tell</span> 'chat *Name <span class="hljs-string">"&gt; "</span> (<span class="hljs-name">line</span> T))
         (<span class="hljs-name">tell</span> 'chat <span class="hljs-string">"--- "</span> *Name <span class="hljs-string">" left ---"</span>)
         (<span class="hljs-name">bye</span>) ) ) )
</code></pre><hr />
<p>With this, we have already everything we need for our little chat app. As a last (rather cosmetic) action, we call <code>(wait)</code> in order to surpress the PicoLisp prompt when the chat function gets called.</p>
<hr />
<p>You can download the full source code of this example <a target="_blank" href="https://gitlab.com/picolisp-blog/single-plage-scripts/-/blob/main/simple-chat-app/chat.l">here</a>.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://en.wikipedia.org/wiki/Fork_(system_call)</li>
<li>https://en.wikipedia.org/wiki/Everything_is_a_file</li>
<li>https://software-lab.de/doc/index.html</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[PicoLisp Explored: The task function]]></title><description><![CDATA[Before continuing with the "Mobile Development" series, I decided to write about the task function, because it is a very useful function as we will see in the mobile app series.

Realizing repetitive tasks with task
With help of task, we can schedule...]]></description><link>https://picolisp-explored.com/picolisp-explored-the-task-function</link><guid isPermaLink="true">https://picolisp-explored.com/picolisp-explored-the-task-function</guid><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 26 Apr 2022 10:36:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1650735030038/TAkuAyVM3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Before continuing with the <a target="_blank" href="https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1">"Mobile Development"</a> series, I decided to write about the <code>task</code> function, because it is a very useful function as we will see in the mobile app series.</p>
<hr />
<h3 id="heading-realizing-repetitive-tasks-with-task">Realizing repetitive tasks with <code>task</code></h3>
<p>With help of <code>task</code>, we can schedule tasks to be executed. This can be useful in many situations, like when we want to fetch data periodically from the server, or if we are waiting for an input stream via a socket.</p>
<p>We check the <a target="_blank" href="https://software-lab.de/doc/index.html">docs</a>:</p>
<blockquote>
<p><code>(task 'num ['num] [sym 'any ..] [. prg]) -&gt; lst</code></p>
<p>A front-end to the <code>*Run</code> global. If called with only a single num argument, the corresponding entry is removed from the value of <code>*Run.</code> Otherwise, a new entry is created. If an entry with that key already exists, an error is issued. For negative numbers, a second number must be supplied. If sym/any arguments are given, a job environment is built for the <code>*Run</code> entry. </p>
</blockquote>
<hr />
<h3 id="heading-a-simple-counter">A simple counter</h3>
<p>This is a lot of information, so let's look at the most straightforward example first: Printing a counter 1, 2, 3, 4, 5.... We want to print <strong>one number per second</strong> (i. e. 1000 ms), and we want to start immediately (i. e. after 0 ms).</p>
<p>The syntax for this is as follows:</p>
<pre><code><span class="hljs-string">:</span> <span class="hljs-string">(task</span> <span class="hljs-number">-1000</span> <span class="hljs-number">0</span> <span class="hljs-string">(tty</span> <span class="hljs-string">(println</span> <span class="hljs-string">(inc</span> <span class="hljs-string">(0)))))</span>
</code></pre><p>The first number defines the frequency, the second number defines the delay until the command is first executed. The first number needs to be <strong>negative</strong>.</p>
<ul>
<li><em>Note 1: we use <code>(tty (println ...))</code> instead of only <code>println</code>, because this will keep the command prompt in the REPL stable, as you can see in the following gif:</em></li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650969144806/h8LgZ-G2m.gif" alt="task_count.gif" /></p>
<p>   <em>Without <code>tty</code>: The command prompt gets overwritten by the <code>println</code>-output, the result is very messy.</em> </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650969336473/0Q4m04_Ya.gif" alt="task_count-notty.gif" /></p>
<ul>
<li><em>Note 2, for PicoLisp enthusiasts: <code>(inc (0))</code> <strong>destructively</strong> increments the cell which initially contains <code>0</code>. For this reason, the return value will constantly increase. Note the difference to <code>(inc 0)</code>, which will always return <code>1</code>.</em></li>
</ul>
<hr />
<p>Now how can we stop the counter? As the documentation tells us, the first number servers as identifier. This means in order to stop this task, we can simply call:</p>
<pre><code>(<span class="hljs-name">task</span> <span class="hljs-number">-1000</span>)
</code></pre><hr />
<h3 id="heading-the-run-global-variable">The <code>*Run</code> global variable</h3>
<p>As the docs tell us, <code>task</code> is only a front-end to the global variable <code>*Run</code>. So let's execute task and check the content of <code>*Run</code> to understand what that means.</p>
<p>If <strong>no</strong> task is running, <code>*Run</code> is <code>NIL</code>:</p>
<pre><code>: <span class="hljs-operator">*</span>Run
<span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span> NIL
</code></pre><p>Now let's set a task and try again:</p>
<pre><code>: <span class="hljs-function"><span class="hljs-params">(task <span class="hljs-number">-10000</span> <span class="hljs-number">-10000</span> (tty (println (inc (<span class="hljs-number">0</span>)))))</span>
-&gt;</span> (<span class="hljs-number">-10000</span> <span class="hljs-number">-10000</span> (tty (println (inc (<span class="hljs-number">0</span>)))))
: *Run
-&gt; ((<span class="hljs-number">-10000</span> <span class="hljs-number">-8102</span> (tty (println (inc (<span class="hljs-number">0</span>))))))
</code></pre><p>We have set a task that fires after 10 seconds and then every ten seconds. If we check <code>*Run</code>, we see that the second item of the list seem to contain the time difference up to the next execution, as well as the current values:</p>
<pre><code><span class="hljs-number">1</span>
<span class="hljs-number">2</span>
<span class="hljs-number">3</span>
<span class="hljs-number">4</span>
<span class="hljs-number">5</span>
<span class="hljs-string">:</span> <span class="hljs-meta">*Run</span>
<span class="hljs-string">-&gt;</span> <span class="hljs-string">((-10000</span> <span class="hljs-number">-1251</span> <span class="hljs-string">(tty</span> <span class="hljs-string">(println</span> <span class="hljs-string">(inc</span> <span class="hljs-string">(5))))))</span>
<span class="hljs-number">6</span>
<span class="hljs-string">:</span>
</code></pre><hr />
<h3 id="heading-conditional-execution-of-task">Conditional Execution of <code>task</code></h3>
<p>Now let's extend our little example: We want to count down from 10 to 0, after that the task should be stopped.</p>
<p><code>task</code> implicitly defines a <strong>closure</strong> (read here for more on <a target="_blank" href="https://picolisp-explored.com/picolisp-explored-the-curry-function">PicoLisp closures</a>). This means we can also execute more complex functions:</p>
<ul>
<li>first we set <code>N</code> to 10,</li>
<li>then we print it,</li>
<li>then we decrement it with <code>(dec 'N)</code></li>
<li>then we check if the result is equal to 0.</li>
<li>If it is equal to zero, the task is stopped.</li>
</ul>
<p>In other words:</p>
<pre><code>: <span class="hljs-function"><span class="hljs-params">(task <span class="hljs-number">-1000</span> <span class="hljs-number">0</span> N <span class="hljs-number">10</span> (tty (println N)) (<span class="hljs-keyword">and</span> (=<span class="hljs-number">0</span> (dec <span class="hljs-string">'N)) (task -1000)))
-&gt; (-1000 0 (job '</span>((N . <span class="hljs-number">10</span>)) (tty (println N)) (<span class="hljs-keyword">and</span> (=<span class="hljs-number">0</span> (dec <span class="hljs-string">'N)) (task -1000))))
10
9
8
7
...</span></span></span>
</code></pre><p>As you can see, <code>task</code> wraps a <code>job</code> function around the <code>prg</code> part of the task. <code>job</code> first takes a list with the current values of the symbols (in this case <code>(N . 10)</code>), and then the program body which defines the new values of the symbols.</p>
<hr />
<h3 id="heading-working-with-file-descriptors">Working with file descriptors</h3>
<p>There is a second way to work with <code>task</code>: Instead of a periodic time in milliseconds, we can define a <strong>file descriptor</strong>. File descriptors are unique identifiers for files or other input/output resources such as pipes or networks in Unix systems (<a target="_blank" href="https://en.wikipedia.org/wiki/File_descriptor">"File descriptors" on Wikipedia</a>).</p>
<p>The file descriptors 0, 1 and 2 are defined as Standard Input, Standard Output and Standard Error. After that, each new file or socket we open will define a new file descriptor, which is also the return value for the picolisp functions like <code>open</code> and <code>port</code>.</p>
<pre><code>: <span class="hljs-function"><span class="hljs-params">(open <span class="hljs-string">"myfile.txt"</span>)</span>
-&gt;</span> <span class="hljs-number">3</span>
: <span class="hljs-function"><span class="hljs-params">(port <span class="hljs-number">4444</span>)</span>
-&gt;</span> <span class="hljs-number">4</span>
</code></pre><p><em>Note: <code>port 4444</code> opens a TCP port on 4444. For an UDP port, the second arguments should be <code>T</code>: <code>port T 4444</code>.</em></p>
<hr />
<p>Now what can we do with this? We can define a <code>task</code> which "listens" on a port and executes all commands that it receives:</p>
<pre><code>: <span class="hljs-function"><span class="hljs-params">(task (port T <span class="hljs-number">4444</span>) (<span class="hljs-built_in">eval</span> (udp @)))</span>
-&gt;</span> (<span class="hljs-number">3</span> (<span class="hljs-built_in">eval</span> (udp @)))
</code></pre><p><code>(udp &lt;FD&gt;)</code> <strong>receives</strong> one UDP package at the corresponding file descriptor, which is set to the socket at port 4444 in the example above.</p>
<p>Next, we can <strong>send</strong> data to this socket via  </p>
<pre><code>: (udp <span class="hljs-string">"localhost"</span> <span class="hljs-number">4444</span> '(println *Pid))  # <span class="hljs-selector-tag">Send</span> <span class="hljs-selector-tag">RPC</span> <span class="hljs-selector-tag">message</span>
<span class="hljs-selector-tag">-</span>&gt; (println *Pid)
</code></pre><p>and it will be <strong>evaluated</strong> because of the <code>eval</code> function defined in the <code>task</code>.</p>
<hr />
<p>In the next post, we will go a little bit deeper into the socket handling with task by exploring a very simple messenger app.</p>
<hr />
<p>Sources</p>
<ul>
<li>https://en.wikipedia.org/wiki/File_descriptor</li>
<li>https://software-lab.de/doc/index.html</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[An OpenStreetMap App written in PicoLisp (Pt. 1)]]></title><description><![CDATA[Let's write a little app that uses the GPS module of the smartphone. The app will display the current position on the map (Open Street Map) and fetch all ice cream cafes and supermarkets from the Open Street Map Overpass API.

But before we dive into...]]></description><link>https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1</link><guid isPermaLink="true">https://picolisp-explored.com/an-openstreetmap-app-written-in-picolisp-pt-1</guid><category><![CDATA[Functional Programming]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Fri, 25 Mar 2022 18:32:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1647468385402/F_gxbg6PG.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's write a little app that uses the GPS module of the smartphone. The app will display the current position on the map (Open Street Map) and fetch all ice cream cafes and supermarkets from the Open Street Map <a target="_blank" href="https://wiki.openstreetmap.org/wiki/Overpass_API">Overpass API</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647469007977/8O_8hYTnN.png" alt="grafik.png" /></p>
<p>But before we dive into Open Street Map, we need to understand how to interact with the GPS module of our smartphone.</p>
<hr />
<h3 id="heading-importing-the-gisl-library">Importing the <code>gis.l</code> library</h3>
<p>In order to use the OpenStreetMap and Google Map functions, we need to import the <code>@lib/gis.l</code> library. <code>gis.l</code> contains some GPS-specific functions such as defining latitude and longitude, calculating the distance between two coordinates and the interaction with the OpenStreetMap and Google Maps API.</p>
<p>We can import additional libraries by adding them to our <code>App.l</code> file directly after the app name declaration. Also we need to add <code>gis</code> to the App's name space in order to make the functions from <code>gis.l</code> available.</p>
<pre><code class="lang-undefined">"Mia's Ice Cream Finder" "@lib/gis.l"

(symbols 'icecream 'gis 'android 'pico)
</code></pre>
<hr />
<h3 id="heading-checking-for-permissions">Checking for permissions</h3>
<p>Just like in the camera example, we have to verify that we actually have permission to access the phone's GPS. Just like there is a <code>camera?</code> function to check the camera permissions, there is a <code>location?</code> function to check the GPS permissions.</p>
<p>If GPS is not permitted, we could display a little warning "Please enable 'Location'":</p>
<pre><code class="lang-undefined">(unless (location?)
   (&lt;p&gt; "tiny red"
      ,"Please enable \"Location\"" ) ) )
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647470154698/wMg4O5_rN.png" alt="grafik.png" /></p>
<p><code>location?</code> is defined in <code>assets/run/lib/android.l</code>.</p>
<hr />
<h3 id="heading-latitude-and-longitude-some-basics">Latitude and Longitude - some basics</h3>
<p>GPS coordinates are represented in degrees, relative to the equator for the North/South coordinates (latitude), and relative to the prime meridian for West/East (longitude).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648199751138/CPtGbxd6A.png" alt="lat-lon.png" /></p>
<p>The latitude domain ranges from -90° (South Pole) to +90° (North Pole), and the longitude domain from -180° to 180°. Both -180° and +180° are indicating the same location, which is the "anti-meridian".</p>
<p>For example, Berlin is located at (52.52°, 13.404°). Since it is on the North-Eastern quarter of the world, both values are &gt;0.</p>
<hr />
<h3 id="heading-getting-the-current-location">Getting the current location</h3>
<p>We can get the current location with the <code>(gps)</code> function. You can easily test it if you <a target="_blank" href="https://picolisp-explored.com/mobile-app-development-in-picolisp-v-getting-a-remote-shell-to-your-pc">get a pseudoterminal from your PC to the PilBox</a> and type <code>(gps)</code> (of course, GPS permission must be available):</p>
<pre><code class="lang-undefined">icecream: (gps)
-&gt; (143571890 . 192396667)
</code></pre>
<p>The function returns two integer values which stand for the Latitude and Longitude. However, the values are not represented in the same way as we normally expect. First of all, we need to fix the scale, as PicoLisp only uses <a target="_blank" href="https://picolisp-explored.com/floating-point-vs-fixed-point-arithmetics">Fixed-Point Calculation</a>.</p>
<p>The scale is 6, which means that the formatted GPS output looks like this:</p>
<pre><code class="lang-undefined">icecream: (format (car (gps)) *Scl ))
-&gt; "142.521890"
icecream: (format (cdr (gps)) *Scl )
-&gt; "193.404667"
</code></pre>
<p>Secondly, the latitude domain range at PicoLisp is mapped from [-90, 90] to [0, 180]. Likewise, the longitude domain range is mapped from [-180, 180] to [0, 360]. This simplifies the internal representation. So in order to re-transform the values, we need to subtract <strong>90 degrees</strong> from the latitude and <strong>180 degrees</strong> from the longitude, and adjust the scale.</p>
<pre><code class="lang-undefined">icecream: (format (- (car (gps)) 90.0) *Scl )
-&gt; "52.521890"
icecream: (format (- (cdr (gps)) 180.0) *Scl )
-&gt; "13.404667"
</code></pre>
<p>Let's get the current location with a button which adds both values to the global variables <code>*Latitude</code> and <code>*Longitude</code>.</p>
<pre><code class="lang-undefined">(gui '(+Able +Button) '(location?) "Get my location"
   '(let G (gps)
      (setq *Latitude (car G)  *Longitude (cdr G)) ) )
</code></pre>
<hr />
<h3 id="heading-displaying-the-current-location-on-a-map">Displaying the current location on a map</h3>
<p>There are two main choices if you want to use a map in your app:</p>
<ul>
<li><p><strong>Google Maps</strong>, which is arguably the bigger one, but it requires an API-Key and is not free (depending on the number of requests). You can read more about it on the <a target="_blank" href="https://developers.google.com/maps/documentation/embed/get-api-key">Google Developer docs</a>. Of course you can embed an iframe of a map showing the current location, but the user will not be able to interact with it.</p>
</li>
<li><p>The alternative choice is <a target="_blank" href="https://openstreetmap.org"><strong>Open Street Map</strong></a>, which is entirely free, but the content might be less up-to-date and the data quality depends a lot on the number of volunteers who provided the data.</p>
</li>
</ul>
<hr />
<p><strong>Variant 1: Google Maps</strong></p>
<p>Google maps can be simply integrated with the <code>&lt;google&gt;</code> function which takes four arguments: Latitude, Longitude, Width and Height. For example:</p>
<pre><code class="lang-undefined">(&lt;google&gt; *Latitude *Longitude "100%" 400)
</code></pre>
<p>produces a map which fills the current container's width and 400 px height.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647472233568/ds6P-9XZA.png" alt="grafik.png" /></p>
<p>If you check the source code of <code>&lt;google&gt;</code> in <code>@lib/gis.l</code>, you will see that this simply maps all values to an iframe:</p>
<pre><code class="lang-undefined">(de &lt;google&gt; (Lat Lon DX DY)
   (prinl
      "&lt;iframe width=\"" DX "\" height=\"" DY "\" frameborder=\"3\" \
      src=\"https://www.google.com/maps?source=s_q&amp;amp;q="
      (fmt Lat "," Lon)
      "&amp;amp;output=embed\"&gt;&lt;/iframe&gt;" ) )
</code></pre>
<hr />
<p><strong>Variant 2: Open Street Map</strong></p>
<p>Open Street Map can be integrated with the <code>&lt;osm&gt;</code> function, which takes three arguments: Latitude, Longitude and the zoom level, which is defined in the <a target="_blank" href="https://wiki.openstreetmap.org/wiki/Zoom_levels">Open Street Map documentation</a>. A zoom level of 12 corresponds to a "town, or city district".</p>
<pre><code class="lang-undefined">(&lt;osm&gt; *Latitude *Longitude 12)
</code></pre>
<p><em>Additionally, you can also pass more parameters defining the click and update behaviour, but it is not needed for our minimal example.</em></p>
<p>The nice thing about Open Street Map is that the developer is free to add additional icons or text to the map. For example, for our Ice Cream app, we can mark all ice cream locations with an ice cream icon, which is not possible in Google Maps.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647472717120/xafKv8Wwq.png" alt="grafik.png" /></p>
<p> This can be done via the <code>&lt;poi&gt;</code> (point of interest) function, which takes as a minimum latitude, longitutde, image, an x and y offset, and a text with a text offset. </p>
<p>For example, these lines add a little pen icon and the word "Here" to the specified position on the map:</p>
<pre><code class="lang-undefined">(&lt;poi&gt; *Latitude *Longitude
   "@img/go.png" "0.1" "1.0"
   "Here" -20 "black" )
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647472885432/0xPl_T6zZ.png" alt="grafik.png" /></p>
<hr />
<p>With this, we can already write a little app that displays the current position on a map.</p>
<p>Next, let's try to retrieve the position of all listed ice cafes from the Open Street Map API and try to display it in our app.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://commons.wikimedia.org/wiki/File:Latitude_and_Longitude_of_the_Earth.svg</li>
<li>https://software-lab.de/demo.zip</li>
<li>https://wiki.openstreetmap.org/</li>
<li>https://developers.google.com/maps?hl=de</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[A Camera Android App written in PicoLisp (Pt. 2)]]></title><description><![CDATA[In the last post, we have defined the main functions of camera app: Checking the camera permissions, taking a picture and storing it in a defined file within the app folder.
In this post, we will finalize the app by adding cache deletion, CSS and nam...]]></description><link>https://picolisp-explored.com/a-camera-android-app-written-in-picolisp-pt-2</link><guid isPermaLink="true">https://picolisp-explored.com/a-camera-android-app-written-in-picolisp-pt-2</guid><category><![CDATA[Mobile Development]]></category><category><![CDATA[Mobile apps]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 22 Mar 2022 10:05:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1647464298306/2TcMFuyLm.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last post, we have defined the main functions of camera app: Checking the camera permissions, taking a picture and storing it in a defined file within the app folder.</p>
<p>In this post, we will finalize the app by adding cache deletion, CSS and name spaces.</p>
<hr />
<h3 id="heading-deleting-the-cache">Deleting the cache</h3>
<p>If you tested the previous version of the app, you might have noticed that the picture does not refresh. This is because the picture is loaded from the <strong>cache</strong> of the app and is not refreshed.</p>
<p>Luckily, it is very easy to solve it: we only need to add the <code>(clearCache)</code> function somewhere in our code, for example before reloading the page.</p>
<pre><code class="lang-undefined">'(takePicture (tmp "img.jpg")
   '((Intent)
      (clearCache)
         ...
</code></pre>
<hr />
<h3 id="heading-adding-css">Adding CSS</h3>
<p>Next, let's add our own CSS files to our app. The PilBox searches for a file called <code>lib.css</code> in our app's home folder. So we have two possibilities: We could either write all our CSS specs into <code>lib.css</code>, or simply <em>import</em> other CSS files into <code>lib.css</code>.</p>
<p>I think the second approach is better, because it allows to use multiple CSS-files - for example, a <a target="_blank" href="https://getbootstrap.com/docs/3.4/css/">bootstrap</a> layout and an app-specific one:</p>
<pre><code><span class="hljs-keyword">@import</span> <span class="hljs-string">"css/bootstrap.css"</span>;
<span class="hljs-keyword">@import</span> <span class="hljs-string">"css/camera.css"</span>;
</code></pre><p>I like using the Bootstrap pre-defined containers because it saves a lot of time in the development process. <a target="_blank" href="https://picolisp-explored.com/web-application-programming-in-picolisp-adding-css">Here</a> you can read how to add CSS classes to PicoLisp GUI components.</p>
<hr />
<h3 id="heading-adding-icons">Adding icons</h3>
<p>We can also add a dedicated icon to our app. It has to be saved to a file called <code>logo.png</code>. Additionally, we can also replace the "take Picture" button by an icon and define it's size and behaviour in our dedicated CSS file:</p>
<pre><code>(gui <span class="hljs-string">'(+Style +Able +Button) "button-icon bg-white" '</span>(camera?) <span class="hljs-literal">T</span> <span class="hljs-string">"miasCamera/img/camera.png"</span>
</code></pre><p>where the class <code>button-icon</code> is defined as:</p>
<pre><code><span class="hljs-selector-class">.button-icon</span> {
   <span class="hljs-attribute">width</span>: <span class="hljs-number">60px</span>;
   <span class="hljs-attribute">height</span>: <span class="hljs-number">60px</span>;
   <span class="hljs-attribute">padding</span>: <span class="hljs-number">5px</span>;
   <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ddd</span>;
   ...
   <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">6px</span>;
   ...
   <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">3px</span> <span class="hljs-number">5px</span> <span class="hljs-number">#ccc</span>;
}

<span class="hljs-selector-class">.button-icon</span><span class="hljs-selector-pseudo">:hover</span> {
   <span class="hljs-attribute">margin</span>: <span class="hljs-number">5px</span> auto <span class="hljs-number">3px</span>;
   ...
}
</code></pre><p>which gives it a more button-like look &amp; feel when it is pressed.</p>
<hr />
<h3 id="heading-setting-the-picture-size">Setting the picture size</h3>
<p>We also want a responsive size of our picture. It should be centered in the middle and its width should not be larger than the smartphone width. </p>
<p>For this, we can simply add a <code>width: 80%; height auto</code> attribute to the image class, which will take 80% of the parent's container size. </p>
<pre><code>(<span class="hljs-operator">&lt;</span>div<span class="hljs-operator">&gt;</span> <span class="hljs-string">"d-flex mb-5 justify-content-center"</span> (gui <span class="hljs-string">'(+Style +Var +Img) "my-img" '</span><span class="hljs-operator">*</span>Picture ))
</code></pre><p>where CSS is</p>
<pre><code><span class="hljs-selector-class">.my-img</span> {
   <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
   <span class="hljs-attribute">height</span>: auto;
}
</code></pre><p>After these modifications, the app should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647465340586/6vHetD77_.jpg" alt="Screenshot_20220312-180853_PilBox.jpg" /></p>
<hr />
<h3 id="heading-local-variables-and-name-spaces">Local variables and name spaces</h3>
<p>For the sake of readability, we could now introduce a local variable <code>*Picture</code> instead of the full path when we want to address the file.</p>
<p>However, there might be several apps running in parallel in our PilBox app, and maybe other apps also have a local variable called <code>*Picture</code>. So let's make sure that these don't get mixed up by adding our own local <em>name space</em> to the app:</p>
<pre><code>(symbols <span class="hljs-symbol">'miasCamera</span> <span class="hljs-symbol">'android</span> <span class="hljs-symbol">'pico</span>)
(local) *Picture
</code></pre><p>This means that symbols are first searched in the <code>miasCamera</code> name space, then in <code>android</code>, and finally in <code>pico</code> which is the "standard" PicoLisp namespace.</p>
<p>Now we can set our global variable without worrying about name conflicts.</p>
<pre><code>(setq <span class="hljs-operator">*</span>Picture <span class="hljs-string">"miasCamera/img/img.jpg"</span>)
...   
   (gui <span class="hljs-string">'(+Style +Var +Img) "my-img" '</span><span class="hljs-operator">*</span>Picture )
...
</code></pre><hr />
<h3 id="heading-adding-the-work-and-start-functions">Adding the <code>work</code> and <code>start</code> functions</h3>
<p>Our app works now without problems. However, it is cleaner to wrap the code to be executed <strong>each time the app is opened</strong> into a <code>work</code> function, and the code that should <strong>only be executed once at start of the app</strong> in a <code>start</code> function.</p>
<p>However, in this specific case, the <code>start</code> function is empty because there are no specific things to be loaded.</p>
<pre><code>(<span class="hljs-keyword">start</span>)

(setq *Picture <span class="hljs-string">"miasCamera/img/img.jpg"</span>)

(de <span class="hljs-keyword">work</span> ()
   (menu <span class="hljs-string">"Mia's Camera App"</span>
      ... ) )

(<span class="hljs-keyword">work</span>)
</code></pre><hr />
<p>With this, our very first (and not too useful) PicoLisp app is finished!</p>
<p>You can download the source code of the finished app <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/tree/main/miasCamera">here</a> and the zip-file <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/blob/main/miasCamera.zip">here</a>.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>http://software-lab.de</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[A Camera Android App written in PicoLisp (Pt. 1)]]></title><description><![CDATA[In the last posts, we have seen how we can access the Java API from PicoLisp, and how a PicoLisp app looks like in general.
Now I would like to start a little series of small independent "Apps". We will start with a little "Camera" app. The functiona...]]></description><link>https://picolisp-explored.com/a-camera-android-app-written-in-picolisp-pt-1</link><guid isPermaLink="true">https://picolisp-explored.com/a-camera-android-app-written-in-picolisp-pt-1</guid><category><![CDATA[Mobile Development]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Fri, 18 Mar 2022 07:59:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1646596210760/ffocAi5ou.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last posts, we have seen how we can access the Java API from PicoLisp, and how a PicoLisp app looks like in general.</p>
<p>Now I would like to start a little series of small independent "Apps". We will start with a little "Camera" app. The functionality is extremely simple: We can take a picture and save it to the app's local storage. If we take another picture, the old one is overwritten.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647427290536/cfKvHVaU5.jpg" alt="Screenshot_20220312-180853_PilBox.jpg" /></p>
<hr />
<h3 id="heading-check-camera-availability">Check Camera Availability</h3>
<p>First of all, we should investigate how we can address the smartphone camera from within our app. For a little inspiration, let's check the <code>camera.l</code> file in the <a target="_blank" href="https://software-lab.de/demo.zip">demo app</a>.</p>
<p>The permissions flow as defined in the android developer tools is as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647428989860/ABgYVf3U7.svg" alt="Permissions.svg" /></p>
<p>Step 1 (declaring the permission in the app's manifest file) is already done by the PilBox APK.  Let's focus on the flow from step 3 to step 6: Checking for available permissions and ask for setting them.</p>
<p>We can test if the camera is enabled with the <code>(camera?)</code> function. It checks if the camera is available for the smartphone  and if the camera permission is set. If permission is not available, the <code>permit</code> function asks for permission by launching the typical Android pop-up:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647429327588/IKXfaOzWS.png" alt="grafik.png" /></p>
<p>Let's create an <code>App.l</code> in our new app and put the following code inside:</p>
<pre><code>(menu "Camera"
   (form NIL
      (gui <span class="hljs-string">'(+Able +Button) '</span>(camera?) "Take Picture")
</code></pre><p>This will simply render a button that is enabled if the camera permission is already set. Otherwise, permission will be requested for the user.</p>
<hr />
<h3 id="heading-optional-check-the-sources">Optional: Check the sources</h3>
<p>Theoretically, it is enough for us to know that <code>camera?</code> does what we want: Check permissions and get them if needed.</p>
<p>However, I think it's worth to also study the PilBox source code to see how this exactly maps to the classes and methods on <code>https://developer.android.com</code>.</p>
<hr />
<p><code>camera?</code> checks if the camera is available for the smartphone and whether the camera permission is set. Otherwise, the function returns <code>NIL</code>. You can find it in line 286 in <code>assets/run/lib/android.l</code>.</p>
<pre><code>(de camera? ()
   (and
      (java (java CONTEXT <span class="hljs-symbol">'getPackageManager</span>) <span class="hljs-symbol">'hasSystemFeature</span> <span class="hljs-string">"android.hardware.camera"</span>)
      (permit <span class="hljs-string">"android.permission.CAMERA"</span>) ) )
</code></pre><p>The <code>and</code> condition checks two things: First, whether the smartphone actually has a camera, and secondly, if the permissions are enabled. If not, the <code>permit</code> function asks for permission. How does it work?</p>
<p>As explained in the post <a target="_blank" href="https://picolisp-explored.com/mobile-app-development-in-picolisp-vi-intents-and-the-java-interface">Intents and the Java Interface</a>, the first condition of <code>camera?</code> maps directly to the <a target="_blank" href="https://developer.android.com/reference/android/content/pm/PackageManager#hasSystemFeature">Java method</a></p>
<pre><code><span class="hljs-selector-tag">getPackageManager</span>()<span class="hljs-selector-class">.hasSystemFeature</span>(<span class="hljs-string">"android.hardware.camera"</span>)
</code></pre><p>The second condition calls the <code>permit</code> function which is defined in line 123 of <code>assets/run/android.l</code>.  It connects two steps with an <code>or</code> clause:</p>
<ul>
<li>Has the permission already been granted? </li>
<li>If not, ask the user for permission and return the result.</li>
</ul>
<p>The permission check is realized by the <a target="_blank" href="https://developer.android.com/training/permissions/requesting"><code>ContextCompat.checkSelfPermission()</code></a> method, while the actual permission request is done by <a target="_blank" href="https://developer.android.com/reference/androidx/core/app/ActivityCompat#requestPermissions"><code>ActivityCompat.RequestPermission()</code></a>.</p>
<p>Called from PicoLisp:</p>
<pre><code>(de permit (Str)
   (or
      (=<span class="hljs-number">0</span>
         (java  <span class="hljs-string">"android.support.v4.content.ContextCompat"</span>
            <span class="hljs-symbol">'checkSelfPermission</span>
            (; CONTEXT GUI)
            Str ) )
      (java  <span class="hljs-string">"android.support.v4.app.ActivityCompat"</span>
         <span class="hljs-symbol">'requestPermissions</span>
         (; CONTEXT GUI)
         (list Str)
         <span class="hljs-number">0</span> ) ) )
</code></pre><p>where <code>Str</code> is the relevant permission, in our case <code>"android.permission.CAMERA"</code>.</p>
<hr />
<h3 id="heading-taking-a-picture-and-storing-it">Taking a picture and storing it</h3>
<p>Now let's assume the user has given permission to use the camera. Next, we want to take a picture and store it. For this purpose, we can use the pre-defined function <code>takePicture</code>, which takes a destination and a function as arguments. </p>
<p>In our case, let's store the picture in the <code>tmp</code>-folder of our app and reload the page. The <code>tmp</code> folder is automatically deleted at the end of the PilBox process.</p>
<pre><code><span class="hljs-string">'(takePicture (tmp "img.jpg")
   '</span>((Intent)                           
      (loadUrl (baseHRef) *SesId "miasCamera/App.l") ) )
</code></pre><p>The <code>tmp</code> function creates a folder in <code>.pil/tmp/&lt;*Pid&gt;/</code>, where <code>*Pid</code> is the current process ID. With this, we create a "take picture" intent for the native camera function. The return value of the intent, is the input value for our anonymous function <code>'((Intent)</code>. Strictly speaking, it is not needed because we don't use the intent's return value; instead we simply reload the page. But it helps to illustrate that we are working with an intent here.</p>
<hr />
<p>Of course, we don't only want to have the picture in our <code>tmp</code> folder, but we want to display it in our app and keep it even if the app is restarted. So let's copy the temporary file to our local app folder and display it:</p>
<pre><code>(gui <span class="hljs-string">'(+Able +Button) '</span>(camera?) "Take picture"
   <span class="hljs-string">'(takePicture (tmp "img.jpg")
      '</span>((Intent)       
         (<span class="hljs-keyword">call</span> "cp" (tmp "img.jpg") "miasCamera/img/img.jpg")             
         (loadUrl (baseHRef) *SesId "miasCamera/App.l") ) ) )
(gui <span class="hljs-string">'(+Var +Img) "miasCamera/img/img.jpg")</span>
</code></pre><p>With this, we have fulfilled the minimum requirements of our basic app: Asking for camera, taking a picture and displaying it. It is not very usuable yet, so this point will be discussed in the next post.</p>
<hr />
<h3 id="heading-deploying-the-app">Deploying the app</h3>
<p>How can we get our app now onto our smartphone? There are two ways:</p>
<p><strong>1. Create a zip-File, saving it to the phone and opening it with PiLBox.</strong></p>
<p>This approach works very well with finished apps, but is not so helpful for development, because you end up zipping and transferring all files for each minor change.</p>
<p><strong>2. Get a pseudoterminal on your phone via WiFi and edit the files directly.</strong></p>
<p>This approach has been explained in this post: <a target="_blank" href="https://picolisp-explored.com/mobile-app-development-in-picolisp-v-getting-a-remote-shell-to-your-pc">Getting a shell to your PC</a>. After setting it up as described in the post, you connect to your phone with</p>
<pre><code><span class="hljs-operator">~</span><span class="hljs-operator">/</span>pil21<span class="hljs-operator">/</span>pil @<span class="hljs-operator">/</span>bin<span class="hljs-operator">/</span>pty <span class="hljs-operator">&lt;</span>smartphone<span class="hljs-operator">-</span>IP<span class="hljs-operator">-</span><span class="hljs-keyword">address</span><span class="hljs-operator">&gt;</span>
</code></pre><p><em>(assuming that pil21 is installed in your home folder, otherwise replace the path).</em></p>
<p>Then you can either modify the source code directly with the vi-based PicoLisp editor <a target="_blank" href="https://picolisp-explored.com/introduction-to-vip-an-editor-for-picolisp-development">vip</a>, or you can edit the files locally and push them with <code>pbPut &lt;folder&gt;/&lt;file&gt;</code>. Note that in this case, the folder structure needs to be the same locally and on your phone.</p>
<pre><code>: (pbPut <span class="hljs-string">"miasCamera/App.l"</span>)
</code></pre><p>This allows you to modify the app instantly.</p>
<hr />
<p>In the next post, we will improve the app's look &amp; feel, as it is barely usable at this point.</p>
<p>The source code of the example up to here can be found <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/tree/main/miasCamera-Pt1">here</a>, the zip-File <a target="_blank" href="https://gitlab.com/picolisp-blog/mobile-applications/-/raw/main/miasCamera-Pt1.zip?inline=false">here</a>.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>http://software-lab.de/</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mobile App Development in PicoLisp - VII:  Basic App Components]]></title><description><![CDATA[In this post, we will see what files and components are needed to write an Android app in PicoLisp.

The "Generic App" Source Code
First of all, let's return to the original pilBox.apk that you can download here. Let's unzip it to take a look at the ...]]></description><link>https://picolisp-explored.com/mobile-app-development-in-picolisp-vii-basic-app-components</link><guid isPermaLink="true">https://picolisp-explored.com/mobile-app-development-in-picolisp-vii-basic-app-components</guid><category><![CDATA[mobile app development]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 15 Mar 2022 13:34:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1646155192041/6RkESUeOK.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, we will see what files and components are needed to write an Android app in PicoLisp.</p>
<hr />
<h3 id="heading-the-generic-app-source-code">The "Generic App" Source Code</h3>
<p>First of all, let's return to the original <code>pilBox.apk</code> that you can download <a target="_blank" href="http://software-lab.de/pilBox.apk">here</a>. Let's unzip it to take a look at the sources. We can find the Android Manifest, the Java classes and a few other documents there. </p>
<p><em>Note: if you are interested in the complete data (like the original Java sources), you can get it here: <a target="_blank" href="https://software-lab.de/PilBox.tgz">PilBox-complete</a>; installation details in the <a target="_blank" href="https://software-lab.de/PilBox/README">ReadMe</a>.</em></p>
<p>What we are interested in specifically is the folder <code>assets/run</code>, which specifies the PicoLisp environment.  For example, we can find the PicoLisp libraries in <code>assets/run/lib</code>.</p>
<p>Now let's take a look at <code>assets/run/App.l</code>. It is titled "Generic PicoLisp App" and defines the environment of the apps, such as loaded libraries, namespaces and so on.</p>
<pre><code class="lang-undefined">"Generic PicoLisp App"

(load "@lib/net.l" "@lib/misc.l" "@lib/btree.l" "@lib/db.l" "@lib/pilog.l")

(msg *Pid " " (stamp))

# Generic PilBox App
(allowed ()
   "!pb0" "!pbHome" "!pbRepl" "@lib.css" "@lib/phone.css" "!pb.css"
   "!pbSettings" "!pbList" "!pbCat" "!work" )

...

(symbols (setq *PbSymbols '(android pico)))

...
</code></pre>
<p>Now with that in mind, we will check out some of the demo applications.</p>
<hr />
<h3 id="heading-a-minimal-example">A minimal example</h3>
<p>Let's begin with the <code>hello.zip</code> demo app, which is truly minimal. After unzipping it, we get a folder <code>hello</code> with a single file inside, which is <code>App.l</code>. This is it's content:</p>
<pre><code class="lang-undefined">"Hello World"

(menu "Hello World!"
   (&lt;h1&gt; "center fh" "Hello, World!") )
</code></pre>
<p>The first string is the <strong>description title</strong> of the list which is rendered to the home screen button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645638919066/-jhWiGfDZ.png" alt="helloworld-button.png" /></p>
<p>Since we didn't specify a logo, the standard PicoLisp logo is used.</p>
<hr />
<p>The <code>menu</code> function is rendered to this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645638555134/kQ-XMaB9S.png" alt="helloworld-app.png" /></p>
<p><code>menu</code> is defined in <code>assets/run/App.l</code>:</p>
<pre><code class="lang-undefined">(de menu (Ttl . Prg)
   (unless *SesId (forbidden))
   ...
  (action
     (html 0 Ttl
        (if (hasFile "lib.css")
           (list "@lib.css" "@lib/phone.css" @)
           '("@lib.css" "@lib/phone.css" "!pb.css") )
           ...
         ((0 0 'main)
            (prog
               (&lt;div&gt; @
                  (run Prg 1) )
               ...
</code></pre>
<p>It basically defines the header with the logo and settings wheel and the HTML and CSS environment for the program to be executed. In our case, the title is "Hello World!" and the program is <code>(&lt;h1&gt; "center fh" "Hello, World!") )</code> which just prints a string.</p>
<hr />
<h3 id="heading-error-handling-the-crash-demo-app">Error handling: The <code>crash</code> demo app</h3>
<p>Now let's take a look at a slightly more complex example: the <a target="_blank" href="https://software-lab.de/crash.zip">"Crash" app</a>. Besides the <code>App.l</code> it contains a file called <code>logo.png</code> which is displayed on the Home screen and in the upper left corner.</p>
<p>By clicking on the "Crash me!" button, you can provoke an error.</p>
<pre><code class="lang-undefined">(menu "Crash me"
   (form NIL
      (&lt;div&gt; "center"
         (&lt;h2&gt; NIL "Crash me")
         (gui '(+Button) "Crash now!"
            '(/ 1 0) ) ) ) )
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646155767968/PWoS41hpj.png" alt="crash.png" /></p>
<p>The code is defined in the PicoLisp error handler <code>*Err</code> in <code>assets/run/App.l</code> of the PilBox source code (line 361):</p>
<pre><code class="lang-undefined">(de *Err
   (println '==== *Pid (symbols))
   (for ("L" (trail T)  "L")
      &lt;...&gt;
   (println '====)
   (loadTxt
      "&lt;style type=\"text/css\"&gt;body{color:white;background-color:red}&lt;/style&gt;"
      "&lt;h1&gt;☹&lt;/h1&gt;&lt;pre&gt;" (sym ^) "&lt;/pre&gt;"
      "&lt;pre&gt;" *Msg "&lt;/pre&gt;" )
   (wait 420) )
</code></pre>
<p>where <code>*Msg</code> is a PicoLisp global variable holding the last recently issued error message. </p>
<hr />
<h3 id="heading-standard-gui-elements">"Standard" GUI elements</h3>
<p>As long as no smartphone-specific functions are required, we have now all the knowledge to create purely PicoLisp-based apps. Basically the structure will be the same like in the <a target="_blank" href="https://picolisp-explored.com/series/web-app">Web Apps</a> tutorials, except that the code is not executed on the server but by the PilBox.</p>
<p>Some good examples for this are in the demo app:</p>
<ul>
<li>Canvas: the <a target="_blank" href="https://picolisp-explored.com/the-forest-fire-model-let-it-burn">Forest Fire</a></li>
<li>Fields: A collection of HTML text input fields,</li>
<li>Charts: A simple table,</li>
<li>Life: A simple animated version of the <a target="_blank" href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life">"Game of Life"</a> algorithm.</li>
</ul>
<hr />
<p>In the next couple of posts, we will discuss apps which use the java interface to access device functions such as camera and GPS.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://software-lab.de</li>
<li>https://software-lab.de/doc/index.html</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mobile App Development in PicoLisp - VI:  Intents and the Java Interface]]></title><description><![CDATA[As we already learned, the PilBox is a tool providing an interface to the Android Java runtime environment. Specifically, we are able to use most of the classes that are listed in the official Android documentation: https://developer.android.com/refe...]]></description><link>https://picolisp-explored.com/mobile-app-development-in-picolisp-vi-intents-and-the-java-interface</link><guid isPermaLink="true">https://picolisp-explored.com/mobile-app-development-in-picolisp-vi-intents-and-the-java-interface</guid><category><![CDATA[android app development]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Fri, 11 Mar 2022 08:12:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1646134691891/nDw9MEH3S.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As we already learned, the PilBox is a tool providing an interface to the Android Java runtime environment. Specifically, we are able to use most of the classes that are listed in the official Android documentation: https://developer.android.com/reference/classes.html</p>
<p>Often, the interesting part of a smartphone app needs to acces smartphone-specific resources (like camera, GPS..). In this case, we need to leave our PicoLisp environment and send an <strong>intent</strong> to an app which provides the needed resources. This post will cover a general explanation of intents and how we can call them from PicoLisp using the Java Interface.</p>
<hr />
<h3 id="heading-android-intents">Android Intents</h3>
<p><a target="_blank" href="https://developer.android.com/guide/components/intents-filters"><strong>Intents</strong></a> are messaging objects that can be used to request an action from another app component such as camera, GPS, contacts and so on. There are three fundamental uses cases:</p>
<ul>
<li><strong>starting an activity</strong>, which is represented by a single screen in an app,</li>
<li><strong>services</strong>, which run in the background, </li>
<li>or <strong>broadcast deliveries</strong>: messages that any app can receive.</li>
</ul>
<p>There are two types of intents:</p>
<ul>
<li><strong>Explicit intents</strong> specify which application will satisfy the intent, by supplying either the target app's package name or a fully-qualified component class name. </li>
<li><strong>Implicit intents</strong> do not name a specific component, but instead declare a general action to perform, which allows a component from another app to handle it.</li>
</ul>
<p>Obviously, implicit intents are inherently less secure because there is no control from developer side which app will accept the intent. The Android system will simply find all appropriate components based on the <em>intent filters</em> in the manifest files of other apps.  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645707558824/KOkwIouO2.png" alt="intents.png" /></p>
<p><em>From the <a target="_blank" href="https://developer.android.com/guide/components/intents-filters">android docs</a>: 1. How an implicit intent is delivered through the system to start another activity: [1] Activity A creates an Intent with an action description and passes it to startActivity(). [2] The Android System searches all apps for an intent filter that matches the intent. When a match is found, [3] the system starts the matching activity (Activity B) by invoking its onCreate() method and passing it the Intent.</em></p>
<p>Now let's see how we can call intents from our PicoLisp app.</p>
<hr />
<h3 id="heading-example-camera-takepictureintent-as-per-android-docs">Example: Camera <code>takePictureIntent</code> as per Android docs</h3>
<p>A typical intent is a call to take a picture from the smartphone app. Let's look at the example Java code from the <a target="_blank" href="https://developer.android.com/training/camera/photobasics#java">Android documentation</a>.</p>
<p>First, we need to check if the camera is available: </p>
<pre><code class="lang-undefined">getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
</code></pre>
<p>Then we can call the <strong>intent</strong>, which involves three pieces: The Intent itself, a call to start the external Activity, and some code to handle the image data when focus returns to your activity. </p>
<pre><code class="lang-undefined">static final int REQUEST_IMAGE_CAPTURE = 1;

private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    try {
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
    } catch (ActivityNotFoundException e) {
        // display error state to the user
    }
}
</code></pre>
<p>Now let's see how we can call this from PicoLisp.</p>
<hr />
<h3 id="heading-the-java-function">The <code>java</code> function</h3>
<p>Let's take a look at <code>lib/android.l</code> in your local pil21-installation (or in the PilBox source code). Here we find the definition how to access the Java environment from PicoLisp in line 37 to 45:</p>
<pre><code class="lang-undefined"># Java I/O
# (java "cls" 'T ['any ..]) -&gt; obj         New object
# (java 'obj ['n] 'msg ['any ..]) -&gt; any   Send message to object
# (java 'obj "fld" ['any]) -&gt; any          Value of object field
# (java "cls" ['n] 'msg ['any ..]) -&gt; any  Call method in class
# (java "cls" "fld" ['any]) -&gt; any         Value of class field
# (java T "cls" ["cls" ..]) -&gt; obj         Define interface
# (java 'obj) -&gt; [lst ..]                  Reflect object
# (java "cls") -&gt; cls                      Get class
</code></pre>
<p>What does this tell us. The types of the arguments to <code>java</code> specify the type of the call. These types may be</p>
<ul>
<li>symbols (transient, internal or external),</li>
<li>short numbers,</li>
<li>or <code>T</code>.</li>
</ul>
<p>(read <a target="_blank" href="https://picolisp-explored.com/concepts-and-data-types">here</a> for data types of PicoLisp).</p>
<p>Then a transient symbol <code>cls</code> denotes a <strong>Java class name</strong>, and <code>fld</code> a <strong>field</strong> in a class:</p>
<ul>
<li>An external symbol <code>obj</code> denotes a Java object</li>
<li>An internal symbol <code>msg</code> denotes a message (method call)</li>
</ul>
<p>The following <code>any</code> arguments may be of any type (numbers, symbols (normally strings) or lists (e. g., arrays in Java).</p>
<hr />
<p>Now let's "translate"  the line of code which checks the camera permissions: </p>
<pre><code class="lang-undefined">getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
</code></pre>
<p><code>hasSystemFeature</code> is a method of the Android <a target="_blank" href="https://developer.android.com/reference/android/content/pm/PackageManager">PackageManager abstract class</a> and <code>getPackageManager</code> is a method of the abstract <a target="_blank" href="https://developer.android.com/reference/android/content/Context"><code>Context</code> class</a>. So this means, the line above is actually a short form of:</p>
<pre><code class="lang-undefined">context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
</code></pre>
<p>Now in PicoLisp: we can express <code>context.getPackageManager()</code> by </p>
<pre><code class="lang-undefined">(let PM (java CONTEXT 'getPackageManager))
</code></pre>
<p>where <code>CONTEXT</code> is a pre-defined database object describing the android context (more on this later) and <code>'getPackageManager</code> is the message. This corresponds to the syntax:</p>
<pre><code class="lang-undefined"># (java 'obj ['n] 'msg ['any ..]) -&gt; any   Send message to object
</code></pre>
<p>Then we call the<code>hasSystemFeature</code> method of the package manager class:</p>
<pre><code class="lang-undefined">(java PM 'hasSystemFeature "android.hardware.camera")
</code></pre>
<hr />
<p>Now let's look at the <code>takePictureIntent</code> in Java and PicoLisp:</p>
<pre><code class="lang-undefined"># Java
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

# PicoLisp
(let Intent (java "android.content.Intent" T "android.media.action.IMAGE_CAPTURE"))
</code></pre>
<hr />
<p>Next, the Java code</p>
<pre><code class="lang-undefined">startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
</code></pre>
<p>can be mapped to the PicoLisp function <code>startActivityForResult</code> which is defined in <code>lib/android.l</code>. Note that the intent is already defined within in the PicoLisp function <code>startActivityForResult</code>:</p>
<pre><code class="lang-undefined">(de startActivityForResult (Fun Action . @)
   (let Intent (java "android.content.Intent" T Action)
      (catch '("ActivityNotFound")
         ...
</code></pre>
<p>where <code>Fun</code> is the function that should be handled and <code>Action</code> is the activity, in this case <code>"android.media.action.IMAGE_CAPTURE"</code>. It generates a new object by calling the <code>new()</code> function in Java.</p>
<p>The complete example: </p>
<pre><code class="lang-undefined"># Java (try-catch removed)
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent, 1);

# PicoLisp
(startActivityForResult Fun "android.media.action.IMAGE_CAPTURE")
</code></pre>
<p>where <code>Fun</code> defines what to do with the picture. We will see an example of this in the next post, where the picture will be saved in a temporary directory.</p>
<hr />
<h3 id="heading-the-context-object">The CONTEXT object</h3>
<p>In the example above, we used the <code>CONTEXT</code> object in <code>(java CONTEXT 'getPackageManager)</code> without explaining what is actually is. So let's do that now: <code>CONTEXT</code> is defined in <code>lib/android.l</code> as</p>
<pre><code class="lang-undefined"># Android Context
(local) (CONTEXT GUI Config javaExt)
(de CONTEXT . {H@@@40000000000})  # file 32768, obj (hex "100000000")
</code></pre>
<p>where <code>{H@@@40000000000}</code> is the external database object. We can inspect it in the PilBox Repl or from your local pty-connection:</p>
<pre><code class="lang-undefined">android: (show CONTEXT)
{H@@@40000000000} ({H@@@1404477010} . "de.software_lab.pilbox.PicoLisp")
   GUI {H@@@1725467726}
   Home "/data/user/0/de.software_lab.pilbox/files"
   Pid {H@@@27043500604}
   Port "8081"
    &lt;...&gt;
   Uuid "de1958ea-d909-44a7-83f7-cd4d750a68ca"
   Loaded T
-&gt; {H@@@40000000000}
</code></pre>
<p>As  you can see, the object's class is <code>"de.software_lab.pilbox.PicoLisp"</code>. Let's check that one:</p>
<pre><code class="lang-undefined">android: (show '{H@@@1404477010})
{H@@@1404477010} ({H@@@1114542263} . "android.app.Service")
   NIL
   mActivityManager
   mApplication
   &lt;...&gt;
-&gt; {H@@@1404477010}
</code></pre>
<p>and we find that the superclass is <code>"android.app.Service"</code> which shows that PicoLisp is actually running as a <strong>service</strong>. Apps have activities and services - the PilBox <strong>activity</strong> can be inspected in the <code>GUI</code> property of <code>CONTEXT</code>:</p>
<pre><code class="lang-undefined">android: (show  (get CONTEXT 'GUI))
{H@@@1725467726} ({H@@@1233152210} . "de.software_lab.pilbox.PilBoxActivity")
   PilView {H@@@46020644}
   &lt;...&gt;
   Config {H@@@1565731746}
   &lt;...&gt;
   Home "/data/user/0/de.software_lab.pilbox/files/"
   &lt;...&gt;
-&gt; {H@@@1725467726}
</code></pre>
<p>From here, you could check the <code>Config</code> component with <code>(show (get CONTEXT 'GUI 'Config)</code> or <code>PilView</code> with <code>(show (get CONTEXT 'GUI 'PilView))</code>, and so on.</p>
<hr />
<p>This post showed a quick (and rather superficial) introduction to how to map Java and PicoLisp code in order to access smartphone components. In the next posts, we will study some examples from the demo applications.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://developer.android.com</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mobile App Development in PicoLisp - V: Getting a Remote Shell to your PC]]></title><description><![CDATA[In the last post, we have checked out the REPL. If you have used it, you might agree that it is not really adequate to write complex program. Typing on the phone is not easy, the window is too small and we cannot properly test the code.
Today we will...]]></description><link>https://picolisp-explored.com/mobile-app-development-in-picolisp-v-getting-a-remote-shell-to-your-pc</link><guid isPermaLink="true">https://picolisp-explored.com/mobile-app-development-in-picolisp-v-getting-a-remote-shell-to-your-pc</guid><category><![CDATA[android app development]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[shell]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 08 Mar 2022 10:08:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645547271931/piJeIi4r7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last post, we have checked out the REPL. If you have used it, you might agree that it is not really adequate to write complex program. Typing on the phone is not easy, the window is too small and we cannot properly test the code.</p>
<p>Today we will see how we can get a shell on our smartphone with help of PilBox.</p>
<hr />
<h3 id="heading-how-it-works">How it works</h3>
<p>We establish a pseudoterminal (<a target="_blank" href="https://en.wikipedia.org/wiki/Pseudoterminal">PTY</a>) between our smartphone and our desktop computer or any other device you plan to use. The PTY is established between the ports of the two process and enables asynchronous, bidirectional communication.</p>
<p>In order for this to work, both devices don't have to be physically connected, but they need to be in the same network. It will not work from mobile network, so as first step, connect both devices (phone and PC) to the same WiFi.</p>
<hr />
<h3 id="heading-identify-your-phones-ip-address">Identify your phone's IP address</h3>
<p>As first step, we need to identify our phone's IP address. If we had full privileges on the PilBox REPL, we could call <code>ipconfig</code> or <code>ip addr</code> or similar commands to get the IP address, but unfortunately these are blocked.   One easy way to find the local IP address is by checking the list of connected devices in your router.</p>
<hr />
<p>Now, as we learned before, the PTY needs two open ports. In other words, our PilBox is opening a port on your smartphone. You can confirm that for example with the command line tool <a target="_blank" href="https://nmap.org/"><code>nmap</code></a>. The output will probably look something like this:</p>
<pre><code>$ sudo nmap <span class="hljs-operator">&lt;</span>smartphone<span class="hljs-operator">-</span>local<span class="hljs-operator">-</span>ip<span class="hljs-operator">&gt;</span>
Starting Nmap <span class="hljs-number">7.80</span> ( https:<span class="hljs-comment">//nmap.org ) at 2022-02-22 17:46 CET</span>
Nmap scan report <span class="hljs-keyword">for</span> <span class="hljs-operator">&lt;</span>your<span class="hljs-operator">-</span>smartphone<span class="hljs-operator">&gt;</span>
Host <span class="hljs-keyword">is</span> up (<span class="hljs-number">0</span>.017s latency).
Not shown: <span class="hljs-number">997</span> closed ports
PORT     STATE SERVICE
<span class="hljs-number">8081</span><span class="hljs-operator">/</span>tcp open  blackice<span class="hljs-operator">-</span>icecap

Nmap done: <span class="hljs-number">1</span> IP <span class="hljs-keyword">address</span> (<span class="hljs-number">1</span> host up) scanned in <span class="hljs-number">21.16</span> <span class="hljs-literal">seconds</span>
</code></pre><p>There is one open port, 8081. (There might also be more depending on what other apps you have installed.) I think the "blackice-icecap" service name is just a wild guess from nmap because PilBox is not in their database yet, so we can ignore that.</p>
<hr />
<h3 id="heading-change-the-port-if-needed">Change the port (if needed)</h3>
<p>If the port 8081 is clashing with some other apps, you also have the possibility to adjust the port. For this, simply access the file <code>Port</code> (located in the app's home directory) in the REPL by typing "Port" and press "Edit".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645549149362/Vw1uoPhz2.png" alt="port9999.png" /></p>
<p>After that restart the PilBox and scan again. Now <code>nmap</code> should show two open ports on 9999:</p>
<pre><code>PORT      STATE SERVICE
<span class="hljs-number">9999</span>/tcp  <span class="hljs-keyword">open</span>  abyss
</code></pre><hr />
<h3 id="heading-creating-the-secret-key">Creating the "secret key"</h3>
<p>Next, you need to create a "secret key" file in the home directory of both app and your PC. The content of both files should be the same. The file name is <code>.pty</code>. For example, I created a file with content "testkey" in my home directory on my laptop:</p>
<pre><code class="lang-undefined">$ cat ~/.pty
testkey
</code></pre>
<p>and on my phone:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645549476201/2rG4qYnIZ.png" alt="catpty.png" /></p>
<p><em>I encourage you to choose a stronger pass file than "testkey".</em></p>
<p>If you now restart the PilBox, it will run in debug mode, as can be seen because the <code>debug</code> button in the REPL will be disabled, and if you run <code>nmap</code> again, you would notice a  <em>second</em> open port, one digit higher then the existing one (default: 8081 + 8082). These two ports will be used for the communication.</p>
<hr />
<h3 id="heading-starting-the-session">Starting the session</h3>
<p>The script to establish the PTY can be found in the <code>bin/pty</code> file of your pil21-installation.</p>
<p><em>Note: If you have changed the port number from 8081 to another port, you need to modify the port variable in the starting script, too (line 7).</em></p>
<p>Then we can establish the connection. For example, if your pil21-installation is in your home folder and the local IP address of your phone is 192.168.178.27, it looks like this:</p>
<pre><code><span class="hljs-operator">~</span><span class="hljs-operator">/</span>pil21<span class="hljs-operator">/</span>pil @<span class="hljs-operator">/</span>bin<span class="hljs-operator">/</span>pty <span class="hljs-number">192.168</span><span class="hljs-number">.178</span><span class="hljs-number">.27</span>
<span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span> NIL
android:
</code></pre><p>Just like in the smartphone REPL, we get a PicoLisp REPL in the android namespace. This is nice, but I promised you a shell. So type: <code>(call "sh")</code>. Now we are on the phone!</p>
<pre><code>android: (call <span class="hljs-string">"sh"</span>)
:<span class="hljs-operator">/</span>data<span class="hljs-operator">/</span>data<span class="hljs-operator">/</span>de.software_lab.pilbox/files $ whoami 
u0_a384
:<span class="hljs-operator">/</span>data<span class="hljs-operator">/</span>data<span class="hljs-operator">/</span>de.software_lab.pilbox/files $ ls 
App.l    PIL<span class="hljs-operator">-</span>battery  PIL<span class="hljs-operator">-</span>radio   Version  db           lib.l  steps.rc
BOSS     PIL<span class="hljs-operator">-</span>browser  PIL<span class="hljs-operator">-</span>steps   battery  demo         loc    tls
COPYING  PIL<span class="hljs-operator">-</span>calc     PIL<span class="hljs-operator">-</span>wecker  bin      favicon.ico  log    wecker
JAVA     PIL<span class="hljs-operator">-</span>chess    Port        browser  hello        log<span class="hljs-operator">-</span>
LISP     PIL<span class="hljs-operator">-</span>crash    RPLY        calc     img          radio
Locale   PIL<span class="hljs-operator">-</span>demo     RQST        chess    lib          src
PID      PIL<span class="hljs-operator">-</span>hello    UUID        crash    lib.css      steps
</code></pre><p><em>Note: Be aware that the communication between the devices is not encrypted, so don't use this in networks you don't trust.</em></p>
<hr />
<h3 id="heading-editing-files">Editing files</h3>
<p>The shell we get is rather limited, you will not be able to use a text editor. It is better to modify source code files from the REPL. There are two ways to do it:</p>
<ul>
<li>use <a target="_blank" href="https://picolisp-explored.com/introduction-to-vip-an-editor-for-picolisp-development">Vip</a>, the PicoLisp editor,</li>
<li>or modify the files on your local machine and use the commands <code>(pbPut &lt;filename&gt;</code> and <code>(pbGet &lt;filename&gt;)</code> to get and change files.</li>
</ul>
<hr />
<p><strong>Using VIP</strong></p>
<p>Let's say we want to check the log files. In this case, call this in the REPL:</p>
<pre><code>: (vi <span class="hljs-string">"log"</span>)
</code></pre><p>It will open a vi-like editor (vip) that allows you to modify the file. Likewise, you can use <code>vi</code> for source files and to see function definitions:</p>
<pre><code>: (vi <span class="hljs-string">"radio/App.l"</span>)
: (vi 'car)
</code></pre><p><em>More on Vip can be found in <a target="_blank" href="https://picolisp-explored.com/introduction-to-vip-an-editor-for-picolisp-development">this post</a>.</em></p>
<hr />
<p><strong>Using <code>pbPut</code>, <code>pbGet</code></strong></p>
<p>Two other very useful functions are <code>pbPut</code> and <code>pbGet</code>. Assumingafter you want to edit the string in <code>.pty</code>, you can first get the file to your local machine:</p>
<pre><code>: (pbGet <span class="hljs-string">"log"</span>)
</code></pre><p>modify it with your preferred editor, and put it back up:</p>
<pre><code>: (pbPut <span class="hljs-string">"log"</span>)
</code></pre><p>Note that you cannot specify the destination folder, so you should start the pty from your local equivalent to the app "home" folder. E.g.: If you want to copy the file <code>myApp/App.l</code>, you need to have a folder <code>myApp</code> both on your local machine and on your smartphone. If it is not available yet, you need to create it:</p>
<pre><code>: <span class="hljs-function"><span class="hljs-params">(call <span class="hljs-string">"mkdir"</span> <span class="hljs-string">"myApp"</span>)</span>
-&gt;</span> T
: (pbPut <span class="hljs-string">"myApp/App.l"</span>)
</code></pre><p>Also, be aware that any exiting files with the same name will be overwritten, which is very convenient for updating source code but can also lead to sad accidents.</p>
<hr />
<p>Now we're almost ready to write our own apps. The next post will explain how the Java interface can be reached from PicoLisp, and then we will take a look at how PicoLisp apps are structured. This should give us all the knowledge we need to write our own apps.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>http://software-lab.de/pilBox.apk</li>
<li>http://picolisp.com</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mobile App Development in PicoLisp - IV: Using the PilBox REPL]]></title><description><![CDATA[In the last post, we have downloaded and checked the source code of some demo applications. Now let's see what we can do with the other built-in tool: the REPL.

About the PilBox REPL
The PilBox REPL provides us with a PicoLisp interpreter and a very...]]></description><link>https://picolisp-explored.com/mobile-app-development-in-picolisp-iv-using-the-pilbox-repl</link><guid isPermaLink="true">https://picolisp-explored.com/mobile-app-development-in-picolisp-iv-using-the-pilbox-repl</guid><category><![CDATA[Web Development]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Fri, 04 Mar 2022 11:14:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645545918773/WzQSVdzvZ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last post, we have downloaded and checked the source code of some demo applications. Now let's see what we can do with the other built-in tool: the REPL.</p>
<hr />
<h3 id="heading-about-the-pilbox-repl">About the PilBox REPL</h3>
<p>The PilBox REPL provides us with a PicoLisp interpreter and a very simple shell on our phone. However, typing on the phone can be quite tedious, and it is not adequate for complex operations. A little teaser: In the next post, we will see how to get a proper PilBox shell from your PC.</p>
<p>But for now, let's try to understand how the built-in shell works.</p>
<hr />
<h3 id="heading-basic-functions">Basic functions</h3>
<p>When you open the REPL page (by clicking on the PicoLisp icon in the top left side), you can see a big white field and a small input field below.</p>
<p>Before the input field comes the current <strong>namespace</strong>, which is currently <em>android</em>. This means that the interpreter first searches the android namespace for a given function and after that the standard 'pico' namespace.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645543429096/8FOvakC7g.png" alt="namespace.png" /></p>
<p>We have two ways to interact with it:</p>
<ul>
<li>either we type standard "PicoLisp" code,</li>
<li>or we can use invoke shell commands, if we prefix them with <code>!</code>.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645543604965/cr0a_4_NB.png" alt="repl-test.png" /></p>
<p>In the example above, you can see that I checked the current system with the shell command <code>! uname -a</code>, and executed the PicoLisp code <code>(* 3 4)</code>.</p>
<p>In other words, with this we have a simple shell on our current phone. <code>whoami</code> returns the PilBox user, which in my case is <code>u0_a384</code>, and <code>ls -la</code>  shows us all the files in the current directory. Here you can see what the "sandbox" concept in Android means: all files in the folder belong to user <code>u0_a384</code> and no other user (process) has access to it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645544064378/oSmSVb1EK.png" alt="terminal.png" /></p>
<p>Of course it also means that we cannot call commands that require higher privileges: for example <code>(! ifconfig)</code> returns <code>No file /proc/net/dev: Permission denied</code>.</p>
<hr />
<h3 id="heading-loading-files">Loading files</h3>
<p>Next to the "eval" button, you can find an "edit" button. This button takes the current text in the input field and opens a file of the corresponding name. If no such file exists, a new one is created (but it will only be saved after we have typed something).</p>
<p>Let's try: We could open the main file (<code>App.l</code>) from the "hello"-demo and modify the code. It can be found in the <code>hello/</code> folder:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645545388421/P0uh88J-f.png" alt="hello-app.png" /></p>
<p>Let's tap into the field and change "Hello World" to "Hello, Goodbye". When we click on the top left icon and then on our "Hello" app, we will see that it has changed:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645545575469/CevYXVhT4.png" alt="hellogoodbye.png" /></p>
<hr />
<h3 id="heading-check-the-logs">Check the logs</h3>
<p>The list of files, viewed with <code>! ls -l</code>, also shows two interesting files: <code>log</code> and <code>log-</code>. Both of them are <strong>log files</strong>; while <code>log</code> contains the data of the current process, <code>log-</code> contains the data of the <em>previous</em> process. Accordingly, it can contain important information if your app suddenly stops working.</p>
<p>You can check the content of the files by typing <code>log</code> and press the EDIT-button, or even easier, type <code>! cat log</code> / <code>! cat log-</code>.</p>
<hr />
<h3 id="heading-clear-cache-and-debug">"Clear Cache" and "Debug"</h3>
<p>There are two more buttons: "Clear Cache" and "Debug". When you press "clear cache", you usually won't see much, unless you changed for example the CSS-file: In this case clearing the cache will automatically load the new CSS file (otherwise it might take up to 24 hours).</p>
<p>If you tap the debug-button, you will enter the "debug" mode. This loads all necessary files, and after that the button gets disabled and can't be tapped again. Debug mode is enabled automatically if we connect the smartphone to the computer via a pseudo-tty, as we will see in the next post.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>www.software-lab.de/pilBox.apk</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mobile App Development in PicoLisp - III: Installing Demo Applications]]></title><description><![CDATA[In the last post, we have seen how to install the PilBox in Android (i. e.: just download it from the Google PlayStore). But there is not much we can do with this app yet, as it is just a container for our future PicoLisp apps. 
Luckily, there are al...]]></description><link>https://picolisp-explored.com/mobile-app-development-in-picolisp-iii-installing-demo-applications</link><guid isPermaLink="true">https://picolisp-explored.com/mobile-app-development-in-picolisp-iii-installing-demo-applications</guid><category><![CDATA[Functional Programming]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[app development]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 01 Mar 2022 10:35:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645530702145/tsk5lONek.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last post, we have seen how to install the PilBox in Android (i. e.: just download it from the Google PlayStore). But there is not much we can do with this app yet, as it is just a container for our future PicoLisp apps. </p>
<p>Luckily, there are already some demo apps available: Let's take a look.</p>
<hr />
<h3 id="heading-pilbox-demo-apps">PilBox Demo Apps</h3>
<p>At the point of writing this post, there are <a target="_blank" href="https://picolisp.com/wiki/?pilbox">10 demo apps available as .zip-File</a>: <code>hello</code>, <code>steps</code>, <code>wecker</code>, <code>radio</code>, <code>chess</code>, <code>browser</code>, <code>battery</code>, <code>calc</code>, <code>demo</code> and <code>crash</code>.</p>
<p>Let's take a look at "Radio" as example. You can download the zip-file from <code>http://software-lab.de/radio.zip</code> or do it directly from the app:</p>
<ol>
<li>Touch the "settings" wheel and type "radio" into the input field of the "PILs" tab.</li>
<li>Click on "Download". A new entry called "binary" will appear in the table.</li>
<li>If you go back to the home screen (PicoLisp symbol on the upper left), you will see a button "Radio".</li>
<li>Clicking on it shows several web radios.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645535356641/C2euEWrSY.png" alt="radiopanel.png" /></p>
<p>Reminder: Just like you shouldn't download files from unknown sources, you should also be careful what kind of zip-files you are loading into your pilbox. I'm pretty sure there is no PicoLisp malware out in the wild, but better safe than sorry :)</p>
<hr />
<h3 id="heading-functionality">Functionality</h3>
<p>Next, let's test the functionality. It is pretty simple: When we tap a station name, the radio starts playing (obviously internet connection is needed). When you tap the "stop" button at the bottom, the radio stops.</p>
<p>When you tap the settings wheel, you will also find a few setting options, namely "alarm", "stations" and "language".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645535801621/OmZGnGAil.png" alt="radiosettings.png" /></p>
<p>It does what you expect - you can set an automatic alarm at a given time (format HH:MM:SS), you can change the pre-defined stations and the language.</p>
<hr />
<h3 id="heading-examine-the-source-code">Examine the source code</h3>
<p>Now tap on the radio symbol until you get back to the home screen, and then click on settings. From there, we can examine the app's source code by clicking on "radio", which will list all files included in the app. </p>
<p>By clicking on each of the files, we can see the respective code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645535257658/EE7g7PSSz.png" alt="sourcecode-radio.png" /></p>
<hr />
<h3 id="heading-demo-apps-overview">Demo Apps Overview</h3>
<p>The main purpose of the demo apps is to demonstrate how to write your own apps and access system functions. We will go further into that in one of the next posts.</p>
<p>Below you can find the available apps and what features they are demonstrating:</p>
<ul>
<li><code>hello.zip</code>: A "hello world" app, which just prints a "Hello World!" headline to the screen.</li>
<li><code>steps.zip</code>: Needs access to the <strong>physical activity</strong>. It is a simple step counter. It gets the "steps" from the step counter built into the phone, and compares it cumulatively against a daily target.</li>
<li><code>wecker.zip</code>: a simple notifier. You can set date, time and title, and a automatic <strong>notification</strong> will pop up.</li>
<li><code>radio.zip</code>: streams web radio. You can set an alarm too.</li>
<li><code>chess.zip</code>: A chess game against a (not very strong) AI. You can set the difficulty by defining the "search depth".</li>
<li><code>browser.zip</code>: A simple web browser. You can also set bookmarks and start pages. Also, you can set the header's user-agent to arbitrary values.</li>
<li><code>battery.zip</code>: displays the battery status of the current device (charging rate and capacity).</li>
<li><code>calc.zip</code>: a bignum calculator (only integers).</li>
<li><code>demo.zip</code>: a collection of demo examples for typical smartphone applications: GPS, Camera, QR scan, Notification, Gaphics with canvas (the <a target="_blank" href="https://picolisp-explored.com/the-forest-fire-model-let-it-burn">forest fire</a>]), the <a target="_blank" href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life">Game of Life</a>, input fields and charts.</li>
<li><code>crash.zip</code>: error handling example (division by 0).</li>
</ul>
<hr />
<p><em>Note: Unfortunately it can happen that the PilBox app terminates the process while running in the background. The screen will show "Zombie" when you re-open it. In this case, just swipe it out and restart it.</em></p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://picolisp.com/wiki/?pilbox</li>
<li>http://software-lab.de</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mobile App Development in PicoLisp - II: How to Install the "PilBox"]]></title><description><![CDATA[As described in the last post, before we can start writing our app in PicoLisp, we need to use a little tool to interface the Java API. This is provided by the AndroidApp PilBox. At the moment of writing this post, the latest version is 22.2.23.

Ins...]]></description><link>https://picolisp-explored.com/mobile-app-development-in-picolisp-ii-how-to-install-the-pilbox</link><guid isPermaLink="true">https://picolisp-explored.com/mobile-app-development-in-picolisp-ii-how-to-install-the-pilbox</guid><category><![CDATA[Functional Programming]]></category><category><![CDATA[Android]]></category><category><![CDATA[app development]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Fri, 25 Feb 2022 07:54:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645479836955/Fk4UccqS0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As described in the last post, before we can start writing our app in PicoLisp, we need to use a little tool to interface the Java API. This is provided by the AndroidApp <a target="_blank" href="https://play.google.com/store/apps/details?id=de.software_lab.pilbox&amp;hl=de&amp;gl=US">PilBox</a>. At the moment of writing this post, the latest version is 22.2.23.</p>
<hr />
<h3 id="heading-installation">Installation</h3>
<p>Like any PlayStore App, it can be installed by simply clicking on the "install" button. Opening the App shows the "Home" view of the app, which should at that point be empty.</p>
<p>On the upper right, there is a "Settings" icon. Clicking on it shows a page with three tabs: The first one shows a table with the installed PicoLisp apps and should be empty after installation. The second one is titled "CSS", the third one is for language settings.</p>
<p>On the upper left, you can find the PicoLisp Logo. Touching it toggles between the <strong>REPL</strong> and the <strong>Home</strong> screen. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645479527316/O8fR3aB0g.png" alt="pilbox-screenshots.png" /></p>
<p>As long as the App is running, the PilBox logo is displayed among the notifications. Like most Android apps, it is closed by swiping it out from the running applications view.</p>
<hr />
<h3 id="heading-analyzing-the-pilbox-source-code">Analyzing the PilBox source code</h3>
<p>Before we get deeper into how to use the app, let's quickly check out the source code. As you might guess from the description in the last post, the PilBox is quite a powerful tool, so let's make sure that we have at least a rough understanding of what the app is actually doing.</p>
<p>To inspect the app's source code, you can get it as APK or TGZ from <a target="_blank" href="https://software-lab.de/">here</a>. There are several ways to analyze android app APKs. I have opened it in the "Mobile Security Framework" Tool <a target="_blank" href="https://mobsf.github.io/docs/#/">MobSF</a>, which allows you to do a static and dynamic analysis of the app in a quite organized way. You can install MobSF locally or access the hosted version: https://mobsf.live/.</p>
<hr />
<p>Let's open <code>pilBox.apk</code> in MobSF and run the static analysis. First we see some general file and aggregated "score" information. The overall security store of 55/100 is not surprising, given that the app is very powerful (although of course it does not do anything malicious, unless you load that code by yourself).</p>
<p>We will see later where this rating comes from in detail.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645482204750/TzFs0HCH8.png" alt="score.png" /></p>
<ul>
<li><strong>Permissions</strong></li>
</ul>
<p>Next, let's take a look at the permissions. As you might have noticed, PilBox does not require any permissions during installation. </p>
<p>However, depending on the app which is loaded into the box, the user <em>could</em> be asked for the following permissions:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645482151620/65Yg-dO3B.png" alt="permission.png" /></p>
<p>GPS and activity tracking as well as microphone and camera access are rated as "dangerous" which means that explicit consent from user side is required. The "normal" permissions are granted by default.</p>
<ul>
<li><strong>Android API</strong></li>
</ul>
<p>Next, we find an overview of the files which contain the app's soure code. By clicking on it, we could read the de-compiled code in cleartext.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645482129080/O9qOllW95.png" alt="api.png" /></p>
<ul>
<li><strong>Manifest Analysis</strong></li>
</ul>
<p>The next analysis fields, "Browsable Activites" and "Network Security", are emtpy, but the next point "Manifest Analysis" contains some interesting information. </p>
<p>For one thing, it claims that the app is communicating in cleartext. This is actually not fully true: Cleartext communication is <em>permitted</em>, but the default communication is ssl-encrypted by the C-library <code>libssl.so</code> (also included in the standard pil21 distribution).</p>
<p>Also, application data can be backed up which means that the data can be copied unencrypted from the device when connected to a computer. Again, it depends on the stored data if this is a problem or not.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645482111194/LpbzJ1R4s.png" alt="manifest.png" /></p>
<hr />
<p>As last step, let's take a look at the shared library binaries. Here the security checker is complaining about runpath variables and missing stack canaries. I'm not 100% sure about the details, but potentially, these kind of settings can be abused by an attacker to gain system control. However, we should keep in mind that PilBox is already a powerful tool by itself, as it allows almost anything you can do within the scope of your app sandbox. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645481212371/C5VaAfKUE.png" alt="binaries.png" /></p>
<hr />
<h3 id="heading-conclusion">Conclusion</h3>
<p>The PilBox is a powerful tool and allows you to do a lot of things on your smartphone which normally requires a full Android studio development environment. Obviously, this also means that the developer needs to know what they are doing. For example, for certain applications it might be needed to add additional safety features if the default ones from the PilBox app are not sufficient.</p>
<p>In the next post, we will see how to load and modify basic applications in to the PilBox.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://picolisp.com/wiki/?pilbox</li>
<li>https://software-lab.de</li>
<li>https://github.com/MobSF/Mobile-Security-Framework-MobSF</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mobile App Development in PicoLisp - I: Android Basics]]></title><description><![CDATA[Welcome to a new series, "Mobile App Development in PicoLisp".  As the title already tells, this series will explain how to write mobile apps in PicoLisp. 
This series builds up on the Web App Programming and Databases series, so it might be helpful ...]]></description><link>https://picolisp-explored.com/mobile-app-development-in-picolisp-i-android-basics</link><guid isPermaLink="true">https://picolisp-explored.com/mobile-app-development-in-picolisp-i-android-basics</guid><category><![CDATA[Functional Programming]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[Mobile apps]]></category><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Tue, 22 Feb 2022 09:45:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645454212614/Y68mdEfq6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to a new series, "Mobile App Development in PicoLisp".  As the title already tells, this series will explain <strong>how to write mobile apps in PicoLisp</strong>. </p>
<p>This series builds up on the <a target="_blank" href="https://picolisp-explored.com/series/web-app">Web App Programming</a> and <a target="_blank" href="https://picolisp-explored.com/series/database">Databases</a> series, so it might be helpful to check out those posts - or the <a target="_blank" href="http://picolisp.com">PicoLisp documentation</a> - first.</p>
<p>Note that this works for Android only, and you will need a smartphone - or emulator - with Android &gt;= 5.0 and a Arm64 CPU (in case you're unsure: if you have a smartphone built after 2020, it is very likely that your phone fulfills the conditions). Rooting is <em>not</em> necessary.</p>
<p>This post will cover the basics of Android smartphone architecture, because I think it is helpful to understand the concept.</p>
<hr />
<h3 id="heading-the-android-platform-architecture">The Android Platform Architecture</h3>
<p>Android is an operation system as well as a software platform for mobile devices such as smartphones, tablets and other devices. Android is free software, published by the <em>Android Open Source Project</em> under the Apache License. The company Google is behind Android, which is the reason why most smartphones have the Google Play Store pre-installed and require a Google account. However, depending on your needs, this it is not a must -  there are alternative repositories for Android, such as <a target="_blank" href="https://f-droid.org/">F-Droid</a> that are completely independent from Google.</p>
<p>The <a target="_blank" href="https://developer.android.com/guide/platform">Android software stack</a> consists of six main components: The Linux Kernel, the Hardware Abstraction Layer, Native C/C++ Libraries, the Android Runtime Environment, the Java API Framework and the System Apps, organized in five layers.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645454480978/Kl6v89u6t.png" alt="android_softwareStack.png" /></p>
<ol>
<li><p>At its core Android has a <strong>Linux kernel</strong> and uses the key security features of Unix systems, such as a user-based permission model and process isolation. </p>
</li>
<li><p>On the next-higher level, we have the <strong>hardware abstraction layer (HAL)</strong> with multiple library modules. Each of the modules interface to a specific hardware component (such as camera or bluetooth). When a framework API makes a call to access device hardware, the Android system loads these modules from the library.</p>
</li>
<li><p>Then we find the <strong>Android Runtime (ART)</strong>, which is the application runtime environment. It translates the bytecode of an application into native instructions for the processor.</p>
</li>
<li><p>On the same level, we have the native <strong>Android C/C++ libraries</strong> which can be directly accessed to interact with physical device input (<a target="_blank" href="https://developer.android.com/ndk/guides">Native Development Kit (NDK)</a>) instead of via the Java framework APIs.</p>
</li>
<li><p>The "standard" access to system functions is via the <strong>Java API Framework</strong> which provides all features to build native apps, for example the view system to build the app's user interface, a resource manager, notifications- and activity managers, and content providers to access data from other apps.</p>
</li>
<li><p>On the top layer, we can find the Android core <strong>system apps</strong> for email, SMS, calendar, browsing, contacts and so on. The capabilities of these apps can be re-used by developers, and they can also be replaced by external applications.</p>
</li>
</ol>
<hr />
<h3 id="heading-the-sandbox-principle">The Sandbox Principle</h3>
<p>One of the key factors for the success of smartphones was to open the devices for apps from <strong>independent developers</strong>. In other words, anyone can write and publish a smartphone app. At the same time, smartphones collect very sensitive, personal user information, such as contacts, position, microphone and camera access and so on, which makes it very attractive for hackers. One important safety feature to prevent malicious apps from gaining access to all data on the phone is the Android <strong>sandbox principle</strong>. </p>
<p>The Sandbox builds up on the Linux user-based protection to identify and isolate app resources. Each app is running in their own sandbox, has a unique user ID and runs its own process. By default, apps can't interact with each other and have only limited access to the OS.</p>
<p>Since the sandbox principle is implemented in the kernel, it is not easy to compromise it. However, it is not invulnerable. On the <a target="_blank" href="https://source.android.com/security/app-sandbox?hl=en">Android documentation page</a>, you can see that the access control sandbox has been getting more and more restrictive which each Android version as reaction to known vulnerabilties:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645459582954/p13d3UrXo.png" alt="sandbox.png" /></p>
<hr />
<h3 id="heading-writing-and-publishing-android-apps">Writing and Publishing Android Apps</h3>
<p>The standard way to write Android apps is using the <a target="_blank" href="https://developer.android.com/studio">Android Studio and SDK</a>, which is a rather heavy tool and includes a debugger, libraries, emulators and tutorials. The standard language to write Android Apps is in Java or Kotlin. Other languages, such as JavaScript, can be used most comfortably with the help of frameworks such as <a target="_blank" href="https://reactnative.dev/">React Native</a> or the <a target="_blank" href="https://ionicframework.com/">Ionic Framework</a>.</p>
<p>The finished app can then be published in repositories. The most important source for external apps is the <a target="_blank" href="https://play.google.com/store">Google Play Store</a>. All apps hosted on the Play Store are checked for basic security features - although you can still find a lot of malware as well. Nevertheless, apps downloaded from a controlled repository such as the PlayStore guarantee a minimum safety that downloaded software has not been manipulated by malicious acters and has a minimum functionality.</p>
<hr />
<h3 id="heading-the-picolisp-pilbox">The PicoLisp "PilBox"</h3>
<p>Now finally, let's come to the point: How can we use PicoLisp to write our own apps? The principle is simple: What we need is a kind of "framework" that makes it possible to access the Java API via PicoLisp by mapping the code to Java.</p>
<p>For this purpose, we can use the <a target="_blank" href="https://play.google.com/store/apps/details?id=de.software_lab.pilbox&amp;hl=de&amp;gl=US">PilBox App</a>. It is available in the Google PlayStore and is written in Java. It displays a WebView GUI, and starts a PicoLisp binary compiled for Arm64 CPUs.</p>
<p> The PilBox kernel provides an interface to the Android Java runtime environment. To the PicoLisp code it looks like a remote database, where Java objects are mapped to PicoLisp DB objects, and Java functions and methods are executed via remote procedure calls.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645458191256/WgM993s_R.png" alt="pilbox-graphic.png" /></p>
<p>In other words, the PilBox is just a container for our future apps. It comes with some built-in demo apps though, that we will check out in the next few posts.</p>
<hr />
<p>One big advantage (besides that we can use PicoLisp) is that the heavy Android SDK environment can be avoided, and strictly speaking not even a laptop is required to develop the app (if you are comfortable typing on the phone). </p>
<p>I think this is a very interesting approach for small apps that are mainly written for your own needs. For example, one of the simple demo apps is a step counter that interfaces with the built-in step counter in the phone. Of course, you can use a pre-installed "Health"-App or download a new one, but if you don't want to share your activity with outside parties or have specific ideas how to monitor it, you could simply write your own app.</p>
<hr />
<h3 id="heading-next-steps">Next steps</h3>
<p>In the next couple of weeks, I plan to cover the following topics:</p>
<ul>
<li>How to install the PilBox,</li>
<li>How to connect from other devices (like your PC) to the PilBox for app development,</li>
<li>The main components to write your own PicoLisp app,</li>
<li>Modifying or expanding the existing demo apps,</li>
<li>Writing a new app.</li>
</ul>
<p>I think it will be interesting, so stay tuned :-)</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://developer.android.com/guide/platform</li>
<li>https://picolisp.com/wiki/?pilbox</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Riddle 10: Summation of primes]]></title><description><![CDATA[The Task

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.


This task is so easy that it is almost not worth its own post. The reason is because it is identical to Task 7, "10001st prime" except...]]></description><link>https://picolisp-explored.com/riddle-10-summation-of-primes</link><guid isPermaLink="true">https://picolisp-explored.com/riddle-10-summation-of-primes</guid><category><![CDATA[Mathematics]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Mia Temma]]></dc:creator><pubDate>Fri, 18 Feb 2022 10:45:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644782440627/mKVyVvPsq.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-the-taskhttpsprojecteulernetproblem10"><a target="_blank" href="https://projecteuler.net/problem=10">The Task</a></h3>
<blockquote>
<p>The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.</p>
<p>Find the sum of all the primes below two million.</p>
</blockquote>
<hr />
<p>This task is so easy that it is almost not worth its own post. The reason is because it is identical to Task 7, <a target="_blank" href="https://picolisp-explored.com/riddle-7-10001st-prime">"10001st prime"</a> except that we need to add one single line.</p>
<hr />
<h3 id="heading-the-solution">The solution</h3>
<p>What we need to do is:</p>
<ol>
<li>Generate a list of all prime numbers below 2.000.000,</li>
<li>Sum up all list items.</li>
</ol>
<p>For 1., we can re-use the code from Task 7 without modification. The only challenge is that instead of 10.000 prime numbers, we need to calculate around <strong>150.000</strong> prime numbers. Then we sum all list items up with <code>apply</code>:</p>
<pre><code class="lang-undefined">(load "./Task_7_10001_Prime_final.l")
(prinl (apply + (sieve 2000000)))
</code></pre>
<hr />
<p>Let's compare the computation time for Task 7 and Task 10.</p>
<pre><code><span class="hljs-string">:</span> <span class="hljs-string">(bench</span> <span class="hljs-string">(apply</span> <span class="hljs-string">+</span> <span class="hljs-string">(sieve</span> <span class="hljs-number">110000</span><span class="hljs-string">)))</span>
<span class="hljs-number">0.114</span> <span class="hljs-string">sec</span>
<span class="hljs-string">-&gt;</span> <span class="hljs-number">544815056</span>
<span class="hljs-string">:</span> <span class="hljs-string">(bench</span> <span class="hljs-string">(apply</span> <span class="hljs-string">+</span> <span class="hljs-string">(sieve</span> <span class="hljs-number">2000000</span><span class="hljs-string">)))</span>
<span class="hljs-number">5.135</span> <span class="hljs-string">sec</span>
<span class="hljs-string">-&gt;</span> <span class="hljs-number">142913828922</span>
</code></pre><p>The computation time has increased from 0.1 s to 5.1 s, but is still much faster than the 60 seconds that the task description allows.</p>
<hr />
<p>You can find the "code" for the finished task <a target="_blank" href="https://gitlab.com/picolisp-blog/single-plage-scripts/-/blob/main/euler/Task_10_Summation_of_primes.l">here</a>.</p>
<hr />
<h3 id="heading-sources">Sources</h3>
<ul>
<li>https://projecteuler.net/problem=10</li>
</ul>
]]></content:encoded></item></channel></rss>