
    
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
                
    
        
        
            
{"version":"https:\/\/jsonfeed.org\/version\/1","title":"mathspp.com feed","home_page_url":"https:\/\/mathspp.com\/blog\/tags\/apl","feed_url":"https:\/\/mathspp.com\/blog\/tags\/apl.json","description":"Stay up-to-date with the articles on mathematics and programming that get published to mathspp.com.","author":{"name":"Rodrigo Gir\u00e3o Serr\u00e3o"},"items":[{"title":"Hold my parentheses","date_published":"2024-04-03T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/hold-my-parentheses","url":"https:\/\/mathspp.com\/blog\/hold-my-parentheses","content_html":"<p>Explore unusual Python features to solve the problem of determining whether an expression is properly parenthesised.<\/p>\n\n<p>Given a string representing a parenthesised expression like <code>\"(3*(x+42)\"<\/code>, how can we figure out if the expression is correctly parenthesised?<\/p>\n<p>In this article I want to explore a solution that doesn't look like your usual piece of Python code.\nWe'll build it up and we'll start with a list of Booleans that flag the positions of opening parentheses:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; expression = \"(3*(x+42)\"\n&gt;&gt;&gt; [c == \"(\" for c in expression]\n[True, False, False, True, False, False, False, False, False]\n&gt;&gt;&gt; list(zip(expression, _))\n[\n    ('(', True),\n    ('3', False),\n    ('*', False),\n    ('(', True),\n    ('x', False),\n    ('+', False),\n    ('4', False),\n    ('2', False),\n    (')', False)\n]<\/code><\/pre>\n<p>We can do a similar thing for closing parentheses:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; [c == \")\" for c in expression]\n[False, False, False, False, False, False, False, False, True]\n&gt;&gt;&gt; list(zip(expression, _))\n[\n    ('(', False),\n    ('3', False),\n    ('*', False),\n    ('(', False),\n    ('x', False),\n    ('+', False),\n    ('4', False),\n    ('2', False),\n    (')', True)\n]<\/code><\/pre>\n<p>If we subtract the two, we can create a list with the values <code>1<\/code>, <code>0<\/code>, and <code>-1<\/code>, that tell you where we have opening parentheses or closing parentheses:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; closes = [c == \")\" for c in expression]\n&gt;&gt;&gt; opens = [c == \"(\" for c in expression]\n&gt;&gt;&gt; [o - c for o, c in zip(opens, closes)]\n[1, 0, 0, 1, 0, 0, 0, 0, -1]\n&gt;&gt;&gt; list(zip(expression, _))\n[\n    ('(', 1),\n    ('3', 0),\n    ('*', 0),\n    ('(', 1),\n    ('x', 0),\n    ('+', 0),\n    ('4', 0),\n    ('2', 0),\n    (')', -1)\n]<\/code><\/pre>\n<p>Notice how we have the <code>1<\/code> next to the characters <code>\"(\"<\/code>, <code>-1<\/code> next to the characters <code>\")\"<\/code>, and <code>0<\/code> next to every other character.<\/p>\n<p>It's also worth noting that the expression above only works because Booleans are integers and so we can write things like the following:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; False - False\n0\n&gt;&gt;&gt; True - False\n1\n&gt;&gt;&gt; False - True\n-1<\/code><\/pre>\n<p>To make everything even more interesting, we can fuse the previous expressions into a single comprehension:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; [(c == \"(\") - (c == \")\") for c in expression]\n[1, 0, 0, 1, 0, 0, 0, 0, -1]\n&gt;&gt;&gt; list(zip(expression, _))\n[\n    ('(', 1),\n    ('3', 0),\n    ('*', 0),\n    ('(', 1),\n    ('x', 0),\n    ('+', 0),\n    ('4', 0),\n    ('2', 0),\n    (')', -1)\n]<\/code><\/pre>\n<p>With this, we can compute the final solution with a single <code>sum<\/code>:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; sum((c == \"(\") - (c == \")\") for c in expression)\n1<\/code><\/pre>\n<p>If the final result is positive, it means we have opened parentheses that haven't been closed.\nIf the final result is negative, it means we closed too many parentheses.\nIf the final result is exactly <code>0<\/code>, it means the parentheses are balanced.<\/p>\n<p>Here are more examples:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; sum((c == \"(\") - (c == \")\") for c in \"(3 + 6)\")\n0\n&gt;&gt;&gt; sum((c == \"(\") - (c == \")\") for c in \"(3 + 6)))\")\n-2\n&gt;&gt;&gt; sum((c == \"(\") - (c == \")\") for c in \"(((3...<\/code><\/pre>","summary":"Explore unusual Python features to solve the problem of determining whether an expression is properly parenthesised.","date_modified":"2025-07-23T16:49:02+02:00","tags":["algorithms","apl","programming","python"],"image":"\/user\/pages\/02.blog\/hold-my-parentheses\/thumbnail.webp"},{"title":"What learning APL taught me about Python","date_published":"2023-08-15T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/what-learning-apl-taught-me-about-python","url":"https:\/\/mathspp.com\/blog\/what-learning-apl-taught-me-about-python","content_html":"<p>Learning programming in APL taught me many new things about Python and this article is an account of that.<\/p>\n\n<h2 id=\"what-learning-apl-taught-me-about-python\">What learning APL taught me about Python<a href=\"#what-learning-apl-taught-me-about-python\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>In the past, I've written an article where I share some areas in which my Python programming was heavily influenced by learning APL.\nYou can read this article here: <a href=\"\/blog\/why-apl-is-a-language-worth-knowing\">&ldquo;Why APL is a language worth knowing&rdquo;<\/a>.<\/p>\n<p>I've given it further thought and now I have a better understanding of how APL influenced my Python code.\nIt is likely that I am not fully aware of all the repercussions that APL had on me, but I have new things to tell you about and that is what I want to focus on in this article.<\/p>\n<p>So, without further ado, let me tell you what APL taught me about Python.<\/p>\n<h2 id=\"the-loc-that-changed-everything\">The LOC that changed everything<a href=\"#the-loc-that-changed-everything\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>There is one line of code (LOC) that changed everything!\nFiguratively speaking.<\/p>\n<p>Some time ago I wrote a piece of Python code pretty naturally.\nYou know when you are so focused on what you are doing that things just flow?\nThat's the state I was in.\nWhen suddenly?\nI looked at the code I had written and I saw this piece of code:<\/p>\n<pre><code class=\"language-py\">sum(age &gt; 17 for age in ages)<\/code><\/pre>\n<p>When I looked at it, I was surprised by it.\nI was surprised because that is not the type of Python code that I usually see written in the books or tutorials I learn from.\nAnd it's also not a pattern I had seen in Python code from other projects...\nUntil it hit me: I wrote this Python code because of the influence that APL had on the way I think about programming.<\/p>\n<p>But first, let us make sure we understand this code!\nWhat does <code>sum(age &gt; 17 for age in ages)<\/code> do?\nWell, if <code>ages<\/code> is a list with the age of a bunch of different people, then the line of code we saw above will count how many people are aged 18 or older:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; ages = [18, 15, 42, 73, 5, 6]\n&gt;&gt;&gt; sum(age &gt; 17 for age in ages)\n3<\/code><\/pre>\n<p>That's what the code does.\nThat's it.\nIt is not that magical.\nBut, curiously enough, it encapsulates plenty of things that APL taught me about Python, so let me tell you all about them.<\/p>\n<h2 id=\"stating-the-obvious\">Stating the obvious<a href=\"#stating-the-obvious\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Now, the remainder of this article might seem like I will be stating the obvious over and over and over and over.\nThat may be the case.\nBut the truth of the matter is, before I stated these things to myself, they hadn't clicked.\nOr, put another way, it was when I stated these things out loud and wrote about them that everything finally made sense.\nAfter all, just because something is obvious, it doesn't mean it is worthless saying it out loud!<\/p>\n<p>A prime example of something obvious that we can benefit from by saying it out loud &ndash; and even giving it a name &ndash; is the...<\/p>","summary":"Learning programming in APL taught me many new things about Python and this article is an account of that.","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","programming","python"],"image":"\/user\/pages\/02.blog\/what-learning-apl-taught-me-about-python\/thumbnail.webp"},{"title":"Connecting Python and Dyalog APL with sockets","date_published":"2023-01-21T00:00:00+01:00","id":"https:\/\/mathspp.com\/blog\/connecting-python-and-dyalog-apl-with-sockets","url":"https:\/\/mathspp.com\/blog\/connecting-python-and-dyalog-apl-with-sockets","content_html":"<p>This article shows how to communicate between Python and Dyalog APL through the use of sockets. We will use the module <code>socket<\/code> from Python and the Conga workspace from Dyalog.<\/p>\n\n<p><img alt=\"\" src=\"\/images\/c\/7\/9\/3\/2\/c793259a18fd94998098f3c57fd8b3b1abf2b7ad-thumbnail.webp\"><\/p>\n<h2 id=\"introduction\">Introduction<a href=\"#introduction\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Programs communicate with each other all the time.\nFor example, your browser communicated with my server to retrieve this article.\nSometimes, you may want your programs to communicate with others, and when that time comes, you may want to use sockets<sup id=\"fnref1:1\"><a href=\"#fn:1\" class=\"footnote-ref\">1<\/a><\/sup>.<\/p>\n<p>This article will show how to communicate between Python and <a href=\"https:\/\/dyalog.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Dyalog APL<\/a> using sockets:<\/p>\n<ul><li>we will use the module <code>sockets<\/code> on the Python side; and<\/li>\n<li>we will use Conga on the Dyalog APL side.<\/li>\n<\/ul><p>Both <code>sockets<\/code> for Python and Conga for Dyalog APL come with their respective systems by default, so that should make things easier for us.<\/p>\n<h2 id=\"how-to-create-a-socket-server-in-python\">How to create a socket server in Python<a href=\"#how-to-create-a-socket-server-in-python\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Thanks to some investigation I did some months ago and <a href=\"\/blog\/til\/sockets\">an article I wrote about <code>sockets<\/code><\/a>, we can see that it doesn't take much code to create a socket server in Python.<\/p>\n<p>In fact, the four lines of code that follow are enough to create a socket server in Python that will listen on port 7342 on the local host:<\/p>\n<pre><code class=\"language-py\">import socket\nserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nserver.bind((\"localhost\", 7342))\nserver.listen()<\/code><\/pre>\n<p>If you are following along, what I suggest is that you run this code in your REPL, so that the Dyalog APL socket you create in the next step connects to your server and you see what is going on.<\/p>\n<p>Go ahead, paste those four lines of code in your REPL, and then add this fifth one to wait for a socket to connect:<\/p>\n<pre><code class=\"language-py\">client, address = server.accept()<\/code><\/pre>\n<p>If all went well, running that line of code should make your interpreter hang, which is normal because you are waiting for a socket to connect to your server.<\/p>\n<p>Let's see how to connect from the APL side<\/p>\n<h2 id=\"how-to-create-a-client-socket-in-dyalog-apl\">How to create a client socket in Dyalog APL<a href=\"#how-to-create-a-client-socket-in-dyalog-apl\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>To work with sockets in Dyalog APL we need to load the Conga workspace, or we can just copy the namespace <code>DRC<\/code> in:<\/p>\n<pre><code class=\"language-apl\">      )copy conga DRC<\/code><\/pre>\n<p>Next up, we initialise the namespace:<\/p>\n<pre><code class=\"language-apl\">      DRC.Init ''\n&#9484;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;\n&#9474;0&#9474;Conga loaded from: conga34_64&#9474;\n&#9492;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;<\/code><\/pre>\n<p>The exact numbers you get in the <code>conga34_64<\/code> portion of the output will differ from version to version (and possibly from OS to OS).<\/p>\n<p>Finally, we use the function <code>DRC.Clt<\/code> to create a client socket.\nWe will pass four arguments to <code>DRC.Clt<\/code>:<\/p>\n<ul><li>the name of the socket we are going to create (any character vector will do);<\/li>\n<li>the address or name of the host (<code>'localhost'<\/code> in our example);<\/li>\n<li>the port to which to connect to (<code>7342<\/code> in our example); and<\/li>\n<li>the type of the socket (<code>'Text'<\/code> in our example):<\/li>\n<\/ul><pre><code class=\"language-apl\">      DRC.Clt 'my socket' 'localhost' 7342 'Text'\n&#9484;&#9472;&#9516;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;\n&#9474;0&#9474;my socket&#9474;\n&#9492;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;<\/code><\/pre>\n<p>If the first element of the result vector is a <code>0<\/code>, that means everything worked out and you managed to create your socket.\nOtherwise, that integer will have an error code...<\/p>","summary":"This article shows how to communicate between Python and Dyalog APL through the use of sockets. We will use the module `socket` from Python and the Conga workspace from Dyalog.","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","networking","python"],"image":"\/user\/pages\/02.blog\/connecting-python-and-dyalog-apl-with-sockets\/thumbnail.webp"},{"title":"Solving Wordle with APL","date_published":"2022-03-28T15:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/solving-wordle-with-apl","url":"https:\/\/mathspp.com\/blog\/solving-wordle-with-apl","content_html":"<p>Join me in solving the word game Wordle in (Dyalog) APL.<\/p>\n\n<figure class=\"image-caption\"><img title=\"A screenshot of a session of Wordle I played.\" alt=\"\" src=\"\/images\/2\/f\/1\/8\/4\/2f1843fc9239532c53c2d0d2ca0b46632768f425-thumbnail.webp\"><figcaption class=\"\">A screenshot of a session of Wordle I played.<\/figcaption><\/figure><h2 id=\"introduction\">Introduction<a href=\"#introduction\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p><a href=\"https:\/\/www.nytimes.com\/games\/wordle\/index.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Wordle<\/a> is a conceptually simple game that you can play online.\n(For those of you who know it, it's like <a href=\"https:\/\/en.wikipedia.org\/wiki\/Mastermind_(board_game)\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Mastermind<\/a> (the board game),\nbut with words.)\nThere is a secret word that you have to guess and you are given 6 tries\nto find out what word is the secret word.\nWhen you make a guess, you get some information back:<\/p>\n<ul><li>you are told which letters of the guess match letters of the secret word;<\/li>\n<li>you are told which letters of the guess exist in the secret word,\nbut are in the wrong position in the guess; and<\/li>\n<li>you are told which letters of the guess don't exist in the secret word.<\/li>\n<\/ul><p>For example, assume that the secret word is &ldquo;chess&rdquo;, and you guess &ldquo;caves&rdquo;:<\/p>\n<ul><li>the &ldquo;c&rdquo; and the &ldquo;s&rdquo; are in their correct positions when compared to the secret word;<\/li>\n<li>the letter &ldquo;e&rdquo; in &ldquo;caves&rdquo; exists in the secret word but it's in the wrong position; and<\/li>\n<li>the letters &ldquo;a&rdquo; and &ldquo;v&rdquo; do not exist in the secret word.<\/li>\n<\/ul><p>Here is how the game would represent this information:<\/p>\n<figure class=\"image-caption\"><img title=\"The visual representation of the letter information.\" alt=\"The word &ldquo;caves&rdquo; where the &ldquo;c&rdquo; and the &ldquo;s&rdquo; are highlighted in green, the &ldquo;e&rdquo; is in yellow, and the &ldquo;a&rdquo; and the &ldquo;v&rdquo; are shaded in grey.\" src=\"\/user\/pages\/02.blog\/solving-wordle-with-apl\/_caves.webp\"><figcaption class=\"\">The visual representation of the letter information.<\/figcaption><\/figure><p>Again, recall that:<\/p>\n<ul><li>the green squares around &ldquo;c&rdquo; and &ldquo;s&rdquo; tell you that those letters are in the correct place;<\/li>\n<li>the yellow square around &ldquo;e&rdquo; tells you that &ldquo;e&rdquo; exists in the secret word but in some other position; and<\/li>\n<li>the gray squares around &ldquo;a&rdquo; and &ldquo;v&rdquo; tell you that &ldquo;a&rdquo; and &ldquo;v&rdquo; are not in the secret word.<\/li>\n<\/ul><h2 id=\"objective\">Objective<a href=\"#objective\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>What we want to do is write an <a href=\"https:\/\/apl.wiki\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">APL<\/a> program that helps us play Wordle.\n(I have written <a href=\"\/blog\/solving-wordle-with-python\">a similar article<\/a> in the past, but using Python.)<\/p>\n<p>We will write a couple of functions:<\/p>\n<ul><li>a function <code>Score<\/code> that scores a given guess with respect to a given secret word; and<\/li>\n<li>a function <code>Filter<\/code> that returns the possible secret words with respect to a given guess and its score.<\/li>\n<\/ul><div class=\"notices yellow\">\n<p>All the code is available in <a href=\"https:\/\/github.com\/rodrigogiraoserrao\/WordleAPL\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this GitHub repository<\/a>.<\/p>\n<\/div>\n<p>As for the letter information, which I'll call the score of a guess, we will encode it in this way:<\/p>\n<ul><li>a <code>0<\/code> means the letter isn't in the secret word;<\/li>\n<li>a <code>1<\/code> means the letter is in the incorrect position; and<\/li>\n<li>a <code>2<\/code> means the letter is in the correct position.<\/li>\n<\/ul><p>Here are a couple of examples:<\/p>\n<table><thead><tr><th style=\"text-align: left;\">Secret word<\/th>\n<th style=\"text-align: left;\">Guess<\/th>\n<th style=\"text-align: left;\">Score<\/th>\n<\/tr><\/thead><tbody><tr><td style=\"text-align: left;\">chess<\/td>\n<td style=\"text-align: left;\">caves<\/td>\n<td style=\"text-align: left;\"><code>2 0 0 1 2<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">chess<\/td>\n<td style=\"text-align: left;\">swiss<\/td>\n<td style=\"text-align: left;\"><code>0 0 0 2 2<\/code><\/td>\n<\/tr><tr><td style=\"text-align: left;\">talon<\/td>\n<td style=\"text-align: left;\">fault<\/td>\n<td style=\"text-align: left;\"><code>0 2 0 1 1<\/code><\/td>\n<\/tr><\/tbody><\/table><p>Take a second to make sure you understand all of the scores above.<\/p>\n<h2 id=\"getting-some-data\">Getting some data<a href=\"#getting-some-data\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The first thing we will do is <a href=\"https:\/\/raw.githubusercontent.com\/rodrigogiraoserrao\/WordleAPL\/main\/WORD.LST\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">grab a list of words<\/a> to play with.\nIf I'm not mistaken, the list I linked to is a free list of the Scrabble dictionary.<\/p>\n<p>(If you are on a Unix system, you may also get away with just using the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Words_(Unix)\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">\n  <code>words<\/code>\n<\/a> file.)<\/p>\n<p>Now that we have some data,...<\/p>","summary":"Join me in solving the word game Wordle in (Dyalog) APL.","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","game","logic","programming"],"image":"\/user\/pages\/02.blog\/solving-wordle-with-apl\/thumbnail.webp"},{"title":"Why APL is a language worth knowing","date_published":"2022-03-24T00:00:00+01:00","id":"https:\/\/mathspp.com\/blog\/why-apl-is-a-language-worth-knowing","url":"https:\/\/mathspp.com\/blog\/why-apl-is-a-language-worth-knowing","content_html":"<p>Let me show you characteristics of APL that will influence your understanding of programming concepts and the way you use other languages.<\/p>\n\n<figure class=\"image-caption\"><img title=\"&ldquo;A language that doesn't affect the way you think about programming, is not worth knowing.&rdquo;, by Alan J. Perlis.\" alt=\"A quote by Alan J. Perlis that reads &ldquo;A language that doesn't affect the way you think about programming, is not worth knowing.&rdquo; on a light background, with a quote symbol at the top and Alan Perlis's signature at the bottom right.\" src=\"\/user\/pages\/02.blog\/why-apl-is-a-language-worth-knowing\/thumbnail.webp\"><figcaption class=\"\">&ldquo;A language that doesn't affect the way you think about programming, is not worth knowing.&rdquo;, by Alan J. Perlis.<\/figcaption><\/figure><h2 id=\"why-apl-is-a-language-worth-knowing\">Why APL is a language worth knowing<a href=\"#why-apl-is-a-language-worth-knowing\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Alan_Perlis\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Alan Perlis<\/a>, the computer scientist recipient of the first <a href=\"https:\/\/en.wikipedia.org\/wiki\/Turing_Award\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Turing award<\/a>, wrote<\/p>\n<blockquote>\n<p>&ldquo;A language that doesn't affect the way you think about programming, is not worth knowing.&rdquo;<\/p>\n<p>&#8213; Alan J. Perlis, 1982. Special feature: Epigrams on programming. ACM Sigplan Notices, 17(9), pp.7-13.<\/p>\n<\/blockquote>\n<p>Inspired by this statement, this article focuses on showing you how <em>a language that <strong>does<\/strong> affect the way you think <strong>is<\/strong> a language worth knowing<\/em>.\nIn particular, I will be drawing from my own experiences with APL and Python to give empirical evidence that supports my statement.<\/p>\n<div class=\"notices blue\">\n<p>This article is also the written version of a talk I gave at <a href=\"https:\/\/confengine.com\/conferences\/functional-conf-2022\/proposal\/16278\/why-apl-is-a-language-worth-knowing\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">FnConf 2022<\/a>.\nThe talk slides are available <a href=\"https:\/\/github.com\/mathspp\/talks\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">here<\/a> and I'll link to the YouTube recording ASAP.<\/p>\n<\/div>\n<h3 id=\"background\">Background<a href=\"#background\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>I started writing Python code in 2012 and that is the programming language I am most fluent in.\nBefore Python, I had written code in other languages such as Visual Basic, JavaScript, and C,\nand after picking up Python I played around with many other different languages\nsuch as Pascal, Haskell, C++, F#, Matlab, Mathematica, and Java.<\/p>\n<p>Then, in 2020, I started learning APL.\nToday, I am nowhere nearly as competent with APL as I am with Python, and yet,\nmy experience with APL has notably affected the way I think about programming,\nthe way I understand and reason about certain computer science concepts,\nand especially the way I write my Python code.<\/p>\n<p>So, in short, in this article I will share evidence that supports the statement that<\/p>\n<blockquote>\n<p>&ldquo;APL is a language worth knowing because it affects the way you think about programming.&rdquo;<\/p>\n<\/blockquote>\n<p>As you will soon find out, APL has had such a notorious impact in my programming because APL is the programming language that is most different from everything else I have learned.\nTherefore, it is only natural that APL has been the language that provided more enlightening moments for me.<\/p>\n<h3 id=\"disclaimer\">Disclaimer<a href=\"#disclaimer\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>Of course, all evidence I am sharing is drawn from my own programming experience and is subjective.\nThus, my examples should not be taken as definite proof that (Python) programmers will get the same benefits as I did from learning APL.\nI just think that this following scenario does not make much sense:<\/p>\n<blockquote>\n<p>&#8213; [someone] So, Rodrigo, how has your experience with APL been?<\/p>\n<p>&#8213; [me] It's been great! It even has influenced my code in other languages, for example in Python.<\/p>\n<p>&#8213; [someone] Really? How so?<\/p>\n<p>&#8213; [me] I don't know, I just feel it.<\/p>\n<\/blockquote>\n<p>Because of that, I spent a lot of time reflecting and trying to come up with concrete and objective instances of things that were influenced by APL.\nThat ought to make for a more compelling conversation than the hypothetical...<\/p>","summary":"Let me show you characteristics of APL that will influence your understanding of programming concepts and the way you use other languages.","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","programming","python"],"image":"\/user\/pages\/02.blog\/why-apl-is-a-language-worth-knowing\/thumbnail.webp"},{"title":"TIL #034 \u2013 multi-channel transposed convolution","date_published":"2022-02-23T00:00:00+01:00","id":"https:\/\/mathspp.com\/blog\/til\/034","url":"https:\/\/mathspp.com\/blog\/til\/034","content_html":"<p>Today I learned about multi-channel transposed convolutions.<\/p>\n\n<h2 id=\"multi-channel-transposed-convolution\">Multi-channel transposed convolution<a href=\"#multi-channel-transposed-convolution\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p><a href=\"\/blog\/til\/033\">After having learned about transposed convolutions<\/a>,\nI needed to see if I could understand how these convolutions work when they have multiple input and output channels.\nAfter all, when used in convolutional neural networks,\nthey typically accept multiple input channels and produce multiple output channels.<\/p>\n<p>After giving it some thought,\nI knew what I <em>expected<\/em> the behaviour to be,\nbut I still had to test it to make sure I was right.<\/p>\n<p>The diagram below is a representation of what I thought should happen,\nthat I will also put in words.\nOn the left, we have the input composed of two channels and,\non the right, we have the output composed of three channels.\nThe black arrows represent part of the work being done by the transposed convolution.<\/p>\n<figure class=\"image-caption\"><img title=\"Diagram representing part of the work done by a multi-channel transposed convolution.\" alt=\"Paint diagram representing part of the work done by a multi-channel transposed convolution, where we have a 2-channel input image on the left, a 3-channel output image on the right, and the representation done by part of the kernel to produce a corner of the output of the first of the output channels.\" src=\"\/user\/pages\/02.blog\/04.til\/034.multi-channel-transposed-convolution\/thumbnail.webp\"><figcaption class=\"\">Diagram representing part of the work done by a multi-channel transposed convolution.<\/figcaption><\/figure><p>The first thing I suspected was that what I really needed was to understand how things worked for multiple input channels.\nMy reasoning was that, whatever happens when the input has <span class=\"mathjax mathjax--inline\">\\(n\\)<\/span> channels and the output has 1 channel,\nwill happen <span class=\"mathjax mathjax--inline\">\\(m\\)<\/span> times if the output has <span class=\"mathjax mathjax--inline\">\\(m\\)<\/span> channels.\nThat's why, in the diagram above, the two rightmost output channels having nothing going on:\nso that we can focus on how the first output channel is built.<\/p>\n<p>Then, I needed to figure out how multiple channels can be combined,\nin a transposed convolution,\nto produce one output channel.<\/p>\n<p>I don't think I needed to be particularly insightful to realise only one thing made sense:\nfor each input channel, there would be a kernel;\nthen, each kernel would be applied to its input channel;\nfinally, the outputs produced by each kernel would be summed up.<\/p>\n<p>In order to test this theory, I resorted to PyTorch again,\nbecause they have transposed convolutions implemented.\nHere is the plan to test my theory:<\/p>\n<ul><li>create a transposed convolution with 2 input channels and 1 output channel;<\/li>\n<li>create two transposed convolutions with a single input channel and a single output channel,\nand set their weights to match those of the first transposed convolution; and<\/li>\n<li>apply the 3 transposed convolutions and check the output of the first matches the sum of the outputs of the other two.<\/li>\n<\/ul><p>Start by creating the three transposed convolutions:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; double = torch.nn.ConvTranspose2d(2, 1, (2, 2), stride=2, bias=False)\n&gt;&gt;&gt; single1 = torch.nn.ConvTranspose2d(1, 1, (2, 2), stride=2, bias=False)\n&gt;&gt;&gt; single2 = torch.nn.ConvTranspose2d(1, 1, (2, 2), stride=2, bias=False)<\/code><\/pre>\n<p>Notice how the shape of the weights of <code>double<\/code> is <code>2 1 2 2<\/code>,\nwhich we can think of consisting of 2 layers of shape <code>1 1 2 2<\/code>,\neach of those layers corresponding to <code>single1<\/code> or <code>single2<\/code>.<\/p>\n<p>Next, we set the weights of <code>single1<\/code> and <code>single2<\/code> to match the corresponding layer of the weights of <code>double<\/code>:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; with torch.no_grad():\n...     single1.weight[:] = double.weight[0:1]\n...     single2.weight[:] = double.weight[1:2]\n...\n&gt;&gt;&gt; single1.weight == double.weight[0]\ntensor([[[[True, True],\n          [True, True]]]])\n&gt;&gt;&gt; single2.weight == double.weight[1]...<\/code><\/pre>","summary":"Today I learned about multi-channel transposed convolutions.","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","machine learning","mathematics","programming"],"image":"\/user\/pages\/02.blog\/04.til\/034.multi-channel-transposed-convolution\/thumbnail.webp"},{"title":"TIL #033 \u2013 transposed convolution","date_published":"2022-02-22T00:00:00+01:00","id":"https:\/\/mathspp.com\/blog\/til\/033","url":"https:\/\/mathspp.com\/blog\/til\/033","content_html":"<p>Today I learned about the transposed convolution transformation in CNNs.<\/p>\n\n<h2 id=\"transposed-convolution\">Transposed convolution<a href=\"#transposed-convolution\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>I am currently working on a project based off of the architecture of the u-net neural network of <a href=\"https:\/\/arxiv.org\/abs\/1505.04597\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this paper<\/a>.\nI struggled to understand how the upsampling was being done,\nuntil I understood it was being done by a transposed convolution.<\/p>\n<p>While I am not a master of transposed convolutions,\nI was able to understand how the u-net upsamples with transposed convolutions.\nIn order to reach the enlightenment stage I'm at,\nI used the two resources you can find below in the references.<\/p>\n<p>To me,\nit is easier to reason about the upsampling step if I think about the &ldquo;reverse&rdquo; downsampling step:\nhow would you use a 2 by 2 convolution to downsample an image into half its size?<\/p>\n<p>Well, if you set your 2 by 2 convolution to have no padding and a stride of 2,\nthen downsampling is exactly what you get:<\/p>\n<figure class=\"image-caption\"><img title=\"Representation of a 2x2 kernel acting on a 4x6 image producing a 2x3 downsample.\" alt=\"Paint diagram representing a 2x2 kernel acting on a 4x6 image producing a 2x3 downsample.\" src=\"\/user\/pages\/02.blog\/04.til\/033.transposed-convolution\/thumbnail.webp\"><figcaption class=\"\">Representation of a 2x2 kernel acting on a 4x6 image producing a 2x3 downsample.<\/figcaption><\/figure><p>In the figure above, the top rectangle represents the input image and the bottom rectangle represents the output (downsampled) image.\nThe black squares on the top-left and bottom-right corners of the input image represent the kernel.\nBecause we have a stride of 2, no pixel from the input is used twice.<\/p>\n<p>In order to go the other way around,\nwe see that each pixel from the bottom image should be able to generate a 2 by 2 region of the image above,\nas represented in the next figure:<\/p>\n<figure class=\"image-caption\"><img title=\"Each pixel of the bottom image generates 4 of the top image.\" alt=\"Paint diagram representing the transposed convolution.\" src=\"\/user\/pages\/02.blog\/04.til\/033.transposed-convolution\/_transposed.webp\"><figcaption class=\"\">Each pixel of the bottom image generates 4 of the top image.<\/figcaption><\/figure><p>This pixel-becomes-2-by-2-region must involve the 2 by 2 kernel,\nso the only sensible thing to do is to multiply each pixel of the bottom image by the kernel!\nSo, in other words, in this particular transposed convolution,\neach 2 by 2 region of the top image is going to be the kernel times the corresponding element of the bottom image.<\/p>\n<p>We can verify this, for example,\nwith the transposed convolution available with PyTorch,\nan open-source machine learning framework for Python!<\/p>\n<p>We start by creating a transposed convolution operator;\nwe set in and out channels to 1,\nso that we can play with a single dimension,\nset the kernel size to 2 by 2,\nthe stride to 2,\nand use no bias so that we can see the effects of multiplication\nlike I described them above:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; import torch.nn\n&gt;&gt;&gt; up = torch.nn.ConvTranspose2d(1, 1, (2, 2), stride=2, bias=False)<\/code><\/pre>\n<p>Up next, we create the corresponding of the bottom image,\na 2 by 3 tensor\n(with leading dimensions 1 and 1 for the batch size and channels,\nrespectively, which we pretty much ignore):<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; inp = torch.randn((1, 1, 2, 3))\n&gt;&gt;&gt; inp\ntensor([[[[-0.0564,  1.5080,  1.6263],\n          [ 0.8452,  0.8627, -0.5019]]]])<\/code><\/pre>\n<p>Then, we make the input go through the upsampling:<\/p>\n<pre><code class=\"language-py\">&gt;&gt;&gt; out = up(inp)<\/code><\/pre>\n<p>Now, we can check that the top-left 2 by 2 region of the output is actually the kernel multiplied by...<\/p>","summary":"Today I learned about the transposed convolution transformation in CNNs.","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","machine learning","mathematics","programming"],"image":"\/user\/pages\/02.blog\/04.til\/033.transposed-convolution\/thumbnail.webp"},{"title":"TIL #021 \u2013 Spouge&#039;s formula","date_published":"2022-01-10T00:00:00+01:00","id":"https:\/\/mathspp.com\/blog\/til\/021","url":"https:\/\/mathspp.com\/blog\/til\/021","content_html":"<p>Today I learned about Spouge's formula to approximate the factorial.<\/p>\n\n<figure class=\"image-caption\"><img title=\"Photo by Scott Graham on Unsplash (cropped).\" alt=\"\" src=\"\/images\/3\/5\/b\/c\/e\/35bcec4646bc80054d47a77cfc1d0a69b5377379-thumbnail.png\"><figcaption class=\"\">Photo by Scott Graham on Unsplash (cropped).<\/figcaption><\/figure>\n<h2 id=\"spouge-s-formula\">Spouge's formula<a href=\"#spouge-s-formula\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Spouge's formula allows one to approximate the value of the gamma function.\nIn case you don't know, the gamma function is like a generalisation of the factorial.<\/p>\n<p>In fact, the following equality is true:<\/p>\n<p class=\"mathjax mathjax--block\">\\[\n\\Gamma(z + 1) = z!\\]<\/p>\n<p>where <span class=\"mathjax mathjax--inline\">\\(\\Gamma\\)<\/span> is the gamma function.<\/p>\n<p>What Spouge's formula tells us is that<\/p>\n<p class=\"mathjax mathjax--block\">\\[\n\\Gamma(z + 1) = (z + a)^{z + \\frac12}e^{-z-a}\\left( c_0 + \\sum_{k=1}^{a-1} \\frac{c_k}{z+k} + \\epsilon_a(z) \\right)\\]<\/p>\n<p>In the equality above, <span class=\"mathjax mathjax--inline\">\\(a\\)<\/span> is an arbitrary positive integer and <span class=\"mathjax mathjax--inline\">\\(\\epsilon_a(z)\\)<\/span> is the error term.\nThus, if we drop <span class=\"mathjax mathjax--inline\">\\(\\epsilon_a(z)\\)<\/span>, we get<\/p>\n<p class=\"mathjax mathjax--block\">\\[\n\\Gamma(z + 1) = z! \\approx (z + a)^{z + \\frac12}e^{-z-a}\\left( c_0 + \\sum_{k=1}^{a-1} \\frac{c_k}{z+k} \\right)\\]<\/p>\n<p>The coefficients <span class=\"mathjax mathjax--inline\">\\(c_k\\)<\/span> are given by:<\/p>\n<p class=\"mathjax mathjax--block\">\\[\n\\begin{cases}\nc_0 = \\sqrt{2\\pi} \\\\\nc_k = \\frac{(-1)^{k-1}}{(k - 1)!}(-k + a)^{k - \\frac12}e^{-k+a}, ~ k \\in \\{1, 2, \\cdots, a-1\\}\n\\end{cases}\\]<\/p>\n<p>By picking a suitable value of <span class=\"mathjax mathjax--inline\">\\(a\\)<\/span>, one can approximate the value of <span class=\"mathjax mathjax--inline\">\\(z!\\)<\/span> up to a desired number of decimal places.\nAlthough we need the factorial function to compute the coefficients <span class=\"mathjax mathjax--inline\">\\(c_k\\)<\/span>,\nthose coefficients only need the factorial of numbers up to <span class=\"mathjax mathjax--inline\">\\(a - 2\\)<\/span>.\nIf we are approximating <span class=\"mathjax mathjax--inline\">\\(z!\\)<\/span>, where <span class=\"mathjax mathjax--inline\">\\(a &lt;&lt; z\\)<\/span>, then this approximation saves us some work.<\/p>\n<p>In order to determine the number of correct decimal places of the result,\none needs to control the error term <span class=\"mathjax mathjax--inline\">\\(\\epsilon_a(z)\\)<\/span>.\nIf <span class=\"mathjax mathjax--inline\">\\(a &gt; 2\\)<\/span> and the <span class=\"mathjax mathjax--inline\">\\(Re(z) &gt; 0\\)<\/span> (which is always true if <span class=\"mathjax mathjax--inline\">\\(z\\)<\/span> is a positive integer), then<\/p>\n<p class=\"mathjax mathjax--block\">\\[\n\\epsilon_a(z) \\leq a^{-\\frac12}(2\\pi)^{-a-\\frac12}\\]<\/p>\n<p>By determining the value of <span class=\"mathjax mathjax--inline\">\\(a^{-\\frac12}(2\\pi)^{-a-\\frac12}\\)<\/span>,\nwe can tell how many digits of the result will be correct.\nFor example, with <span class=\"mathjax mathjax--inline\">\\(a = 10\\)<\/span>, we get<\/p>\n<p class=\"mathjax mathjax--block\">\\[\na^{-\\frac12}(2\\pi)^{-a-\\frac12} \\approx 1.31556 \\times 10^{-9} ~ ,\\]<\/p>\n<p>meaning we will get 8 correct digits.<\/p>\n<div class=\"notices yellow\">\n<p>However, notice that the approximating formula must, itself,\nbe computed with enough precision for the final result to hold\nas many correct digits as expected.\nIn other words, if a higher value of <span class=\"mathjax mathjax--inline\">\\(a\\)<\/span> is picked so that the\nfinal result is more accurate, then we need to control the accuracy used when\ncomputing the coefficients <span class=\"mathjax mathjax--inline\">\\(c_k\\)<\/span> and the formula itself.<\/p>\n<\/div>\n<p>I'll leave it as an exercise for you, the reader,\nto implement this approximation in your favourite programming language.<\/p>\n<h2 id=\"spouge-s-formula-in-apl\">Spouge's formula in APL<a href=\"#spouge-s-formula-in-apl\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>In APL, (and disregarding the accuracy issues) it can look something like this:<\/p>\n<pre><code class=\"language-APL\">      \u235d Computes the `c_k` coefficients:\n      Cks \u2190 {(.5*\u2368\u25cb2),((!ks-1)\u00f7\u2368\u00af1*ks-1)\u00d7((\u2375-ks)*ks-.5)\u00d7*\u2375-ks\u21901+\u2373\u2375-1}\n\n      \u235d Computes the approximation of the gamma function:\n      GammaApprox \u2190 {((\u2375+\u237a)*\u2375+.5)\u00d7(*-\u2375+\u237a)\u00d7(\u22a2\u00f71,\u2375+1\u2193\u2373\u2218\u2262)Cks \u237a}\n\n      \u235d Computes an upper bound for the error term:\n      Err \u2190 {(\u2375*\u00af.5)\u00d7(\u25cb2)*-\u2375+.5}\n\n      a \u2190 10\n      Err a\n1.315562187E\u00af9  \u235d Thus, we expect 8 decimal places to be correct.\n      z \u2190 100\n      a GammaApprox z\n9.332621544E157\n      !z\n9.332621544E157<\/code><\/pre>\n<p>That's it for now! <a href=\"\/subscribe\">Stay tuned<\/a> and I'll see you around!<\/p>","summary":"Today I learned about Spouge&#039;s formula to approximate the factorial.","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","mathematics","numerical analysis"],"image":"\/user\/pages\/02.blog\/04.til\/021.spouges-formula\/thumbnail.png"},{"title":"Counting mosaics with APL","date_published":"2021-11-15T00:00:00+01:00","id":"https:\/\/mathspp.com\/blog\/counting-mosaics-with-apl","url":"https:\/\/mathspp.com\/blog\/counting-mosaics-with-apl","content_html":"<p>This is a short article on how I quickly used APL to verify my combinatorics calculations.<\/p>\n\n<p><img alt=\"An image of two 3 by 3 grids with coloured cells\" src=\"\/images\/5\/d\/5\/b\/3\/5d5b3ed7dceadb06d9253de0dbee99d3cc69abb5-thumbnail.webp\"><\/p>\n<h2 id=\"preamble\">Preamble<a href=\"#preamble\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>A local university runs a weekly challenge with mathematical problems\nfor everyone to solve.\nThis past week, the problem shared was a combinatorics problem that read as follows\n(I'm paraphrasing):<\/p>\n<p>&ldquo;Consider a 3 by 3 grid of squares composing a mosaic.\nIn how many ways can we colour that mosaic, if we have 3 different colours\nand if adjacent squares cannot share the same colour?&rdquo;<\/p>\n<p>In the problem statement, they clarify that &ldquo;adjacent&rdquo; means &ldquo;horizontally or vertically adjacent&rdquo;,\nand they even give a hint\n(skip to the next paragraph if you do not want <em>any<\/em> spoilers!):\n&ldquo;number the squares from 1 to 9, and then work with the colours of the even squares.\nThat shall determine the colours of the odd squares.&rdquo;.<\/p>\n<p>Combinatorics has never been my strongest suit, but I wanted to solve this problem.\nWith that in mind, I sat down and started drafting my solution.<\/p>\n<p>By the time I was done, I decided to quickly verify my solution with <a href=\"https:\/\/apl.wiki\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">APL<\/a>,\na very neat programming language that I have been learning for the past 2 years.<\/p>\n<p>This is the article of how it took me 30 seconds in APL to figure out my\nsolution had a problem.<\/p>\n<ol><li>I'll start by showing you my flawed proof (as I wrote it);<\/li>\n<li>then, I'll tell you what I did in APL to check my solution;<\/li>\n<li>afterwards, I'll show you the mistake I made initially; and finally,<\/li>\n<li>I'll work a bit more on the APL code to make it cleaner.<\/li>\n<\/ol><h2 id=\"my-initial-solution\">My initial solution<a href=\"#my-initial-solution\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The text that follows was my initial solution to the problem I described above.\nAs a challenge for you, try to find the flaws in my reasoning\/calculations.\nHere we go.<\/p>\n<p>&ldquo;As per the problem statement hint, we'll number the squares in the grid:<\/p>\n<pre><code class=\"language-txt\">1 2 3\n4 5 6\n7 8 9<\/code><\/pre>\n<p>Now we will study all the possible colourings as a function of the colours\nattributed to squares 2, 4, 6, and 8.<\/p>\n<p>The even squares can only use up to 2 colours,\notherwise square 5 won't have a possible colour.<\/p>\n<p>Let's suppose that the even squares have a single colour.\nIn that case, the odd squares can be coloured arbitrarily.\nThat makes up for a total of <span class=\"mathjax mathjax--inline\">\\(3 \\times 3^5 = 3^6\\)<\/span> mosaics.<\/p>\n<p>Now, let's assume that the even squares have 2 colours.\nLet's fix the colour of square number 2,\nwhich can be any one colour of the three available colours.\nNext, there's either one, two, or three,\nsquares with a colour that is different from square 2,\nbut equal among themselves.\nLet's consider these three cases separately.<\/p>\n<p>We start with assuming there's only one square with a colour different\nfrom the colour of square 2.\nThat colour can be any one of two colours.\nNext, we just have to figure out in how many ways we can colour the odd squares.\nThat will depend on the position...<\/p>","summary":"This is a short article on how I quickly used APL to verify my combinatorics calculations.","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","combinatorics","mathematics","programming"],"image":"\/user\/pages\/02.blog\/counting-mosaics\/thumbnail.webp"},{"title":"Let&#039;s build a simple interpreter for APL - part 4","date_published":"2021-04-03T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/lsbasi-apl-part4","url":"https:\/\/mathspp.com\/blog\/lsbasi-apl-part4","content_html":"<p>In part 4 of this series we add some unit testing,\nimprove our tokenizer and implement the primitives <code>&#9076;<\/code> and <code>&#9060;<\/code>.<\/p>\n\n<p>In the previous post I said I would be making less changes in between each blog post\nto make the blog posts smaller, but now I went back to check the changes I had\nto write about and I realised I did <em>way<\/em> too much to fit in a single blog post...<\/p>\n<p>So while RGSPL v0.4 is out, I'm going to split it in a couple of blog posts.\nYou can see all the changes from v0.3 to v0.4 <a href=\"https:\/\/github.com\/RodrigoGiraoSerrao\/RGSPL\/compare\/v0.3...v0.4\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">here<\/a>.<\/p>\n<h2 id=\"today\">Today<a href=\"#today\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The RGSPL v0.4 is essentially v0.3 plus the exercises of the previous blog post,\nand that represents plenty of changes and additions to our code base.\nIn this article we will only cover a few:<\/p>\n<ul><li>add testing for the primitives I already have;<\/li>\n<li>tokenizer tweaks and fixes;<\/li>\n<li>tweaking the CLI to accept a flag to toggle debugging;<\/li>\n<li>implement the shape and reshape functions (monadic and dyadic <code>&#9076;<\/code>); and<\/li>\n<li>implement the atop operator <code>&#9060;<\/code>.<\/li>\n<\/ul><h3 id=\"next-time\">Next time<a href=\"#next-time\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>Here are the changes we still have to go through in the next blog posts.<\/p>\n<ul><li>\n<p>add class methods to deal with the n-cells of APL arrays and others;<\/p>\n<\/li>\n<li>\n<p>homogenise the representation of APL scalars;<\/p>\n<\/li>\n<li>\n<p>modify the <em>index generator<\/em> <code>&#9075;<\/code> function to make a distinction between 1-item vectors and scalars;<\/p>\n<\/li>\n<li>\n<p>modify the <em>without<\/em> <code>~<\/code> function to work on the major cells of the left argument;<\/p>\n<\/li>\n<li>\n<p>implement pretty printing of APL arrays;<\/p>\n<\/li>\n<li>\n<p>add auxiliary decorators that do input checking;<\/p>\n<\/li>\n<li>\n<p>implement the Boolean functions <code>&and;&or;&#9074;&#9073;<\/code>;<\/p>\n<\/li>\n<li>\n<p>implement the encode and decode functions <code>&#8868;&perp;<\/code>;<\/p>\n<\/li>\n<\/ul><h3 id=\"the-code\">The code<a href=\"#the-code\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p><a href=\"https:\/\/github.com\/RodrigoGiraoSerrao\/RGSPL\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link image\">\n  <img src=\"https:\/\/img.shields.io\/github\/stars\/RojerGS\/RGSPL?style=social\" alt=\"\"><\/a><\/p>\n<p>The whole code for this project is hosted in <a href=\"https:\/\/github.com\/RodrigoGiraoSerrao\/RGSPL\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this<\/a> GitHub repo\nand the code for this specific blog post is <a href=\"https:\/\/github.com\/RodrigoGiraoSerrao\/RGSPL\/releases\/tag\/v0.4\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">the release v0.4<\/a>.<\/p>\n<p><a href=\"https:\/\/github.com\/RodrigoGiraoSerrao\/RGSPL\/compare\/v0.3...v0.4\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">This link<\/a> shows the diff with all the changes that happened since v0.3.<\/p>\n<hr><h2 id=\"testing\">Testing<a href=\"#testing\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Unit testing is a really important thing for several reasons, for example\nit provides an automated way to test your code\n(and therefore gives you confidence that your code works as expected) and\nit helps you figure out when code refactoring broke something.\nIf you also start by writing the unit testing for a certain feature and only\nthen implement the feature, you are forced to write code that passes your tests,\ninstead of writing tests that your code passes.<\/p>\n<p>I don't have much experience with unit testing in Python so I went\nto look for a simple alternative in the Python Standard Library and found <code>unittest<\/code>,\nso that is what I am using.<\/p>\n<p>I figured I would be writing many more tests than the ones we wrote in the\nprevious blog post, so I decided to create a directory for the tests and created\na <code>tests\/utils.py<\/code> file with some utility functions:<\/p>\n<pre><code class=\"language-py\">\"\"\"\nUtility functions used by the tests.\n\"\"\"\n\nimport functools\nimport unittest\n\nfrom rgspl import Interpreter, Parser, Tokenizer\nfrom arraymodel import APLArray\n\ndef run(code):\n    \"\"\"Run a string containing APL code.\"\"\"\n    return Interpreter(Parser(Tokenizer(code))).interpret()\n\ndef S(scalar):...<\/code><\/pre>","date_modified":"2025-07-23T16:49:02+02:00","tags":["apl","interpreters","lsbasi-apl","programming","python"],"image":"\/user\/pages\/02.blog\/lsbasi-apl-part4\/thumbnail.webp"}]}
