<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"><channel><description></description><title>Ram's blog</title><generator>Tumblr (3.0; @ramrachum)</generator><link>https://blog.ram.rachum.com/</link><language>en-us</language><itunes:explicit>no</itunes:explicit><itunes:subtitle/><item><title>GridRoyale - A life simulation for exploring social dynamics</title><description>&lt;h2&gt;
          &lt;a href="#"&gt;
            GridRoyale - A life simulation for exploring social dynamics
          &lt;/a&gt;
        &lt;/h2&gt;
        
        &lt;p&gt;
          Another day, another project :)
        &lt;/p&gt;
        
        &lt;div class="center_image_container"&gt;
          &lt;a href="https://github.com/cool-RR/grid_royale"&gt;
            &lt;figure class="tmblr-full" data-orig-height="768" data-orig-width="600" data-orig-src="https://i.imgur.com/pmxEKnR.gif"&gt;&lt;img src="https://64.media.tumblr.com/8af80b8c19135ba8737087221a718bff/f154f7bae512b079-30/s540x810/1a1fcc3fe08fd4b78a6a5c272bf7c6c023662be4.gif" data-orig-height="768" data-orig-width="600" data-orig-src="https://i.imgur.com/pmxEKnR.gif"/&gt;&lt;/figure&gt;&lt;/a&gt;
        &lt;/div&gt;
        
        &lt;p&gt;
          This is a project that I wanted to do for years. I finally had the opportunity to do it.
          &lt;a href="https://github.com/cool-RR/grid_royale"&gt;
            Check out the GridRoyale readme on GitHub for more details and a live demo.
          &lt;/a&gt;
        &lt;/p&gt;
        
        &lt;p&gt;
          GridRoyale is a life simulation. It&amp;rsquo;s a tool for machine learning researchers to explore social dynamics.
        &lt;/p&gt;
        
        &lt;p&gt;
          It&amp;rsquo;s similar to Game of Life or GridWorld, except I added game mechanics to encourage the players
          to behave socially. These game mechanics are similar to those in the battle royale genre of
          computer games, which is why it&amp;rsquo;s called GridRoyale.
        &lt;/p&gt;
        
        &lt;p&gt;
          The game mechanics, Python framework and visualization are pretty good&amp;ndash; The core algorithm sucks,
          and I&amp;rsquo;m waiting for someone better than me to come and write a new one. If that&amp;rsquo;s you, please open
          a pull request.
        &lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/631666550733225984</link><guid>https://blog.ram.rachum.com/post/631666550733225984</guid><pubDate>Sun, 11 Oct 2020 11:16:03 +0300</pubDate><category>planetpython</category><category>python</category><category>open-source</category><category>projects</category><category>machine learning</category><category>reinforcement learning</category></item><item><title>Live-coding a music synthesizer</title><description>&lt;h2&gt;
          &lt;a href="#"&gt;
            Live-coding a music synthesizer
          &lt;/a&gt;
        &lt;/h2&gt;
        
        &lt;p&gt;
          After so much work and waiting, the video of my EuroPython talk is
          &lt;a href="https://www.youtube.com/watch?v=SSyQ0kRHzis"&gt;finally released!&lt;/a&gt;
        &lt;/p&gt;
        
        &lt;div class="center_image_container"&gt;
         &lt;iframe width="560" height="315" src="https://www.youtube.com/embed/SSyQ0kRHzis" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;
        &lt;/div&gt;
        
        &lt;p&gt;
          This is a fun live-coding session using
          &lt;a href="https://numpy.org/"&gt;NumPy&lt;/a&gt;
          and
          &lt;a href="https://github.com/spatialaudio/python-sounddevice"&gt;SoundDevice.&lt;/a&gt;
          The goal of this talk is to make the computer produce realistic-sounding instrument sounds, using nothing but math.
        &lt;/p&gt;
        
        &lt;p&gt;
          The talk starts with creating a simple sound using a sine wave. We gradually make it sound more like a real instrument, learning a little bit about music theory on the way. We add features one-by-one until by the end of the talk, we hear our synthesizer play a piece of classical music.
        &lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/629952546416541696</link><guid>https://blog.ram.rachum.com/post/629952546416541696</guid><pubDate>Tue, 22 Sep 2020 13:12:44 +0300</pubDate><category>python</category><category>planetpython</category><category>europython</category><category>talks</category><category>open-source</category></item><item><title>Quick project: Guitar tuning peg turner</title><description>&lt;h2&gt;
          &lt;a href="#"&gt;
            Quick project: Guitar tuning peg turner
          &lt;/a&gt;
        &lt;/h2&gt;
        
        &lt;p&gt;
          Here&amp;rsquo;s a cute 3D printing I did on a whim a couple of days ago.
        &lt;/p&gt;
        
        &lt;p&gt;
          I wanted to change the strings on my acoustic bass guitar, so I&amp;rsquo;ll have crisp sound on my upcoming talk
          &lt;a href="https://ep2020.europython.eu/talks/4WLzSf3-live-coding-a-music-synthesizer/"&gt;Live-coding a music synthesizer&lt;/a&gt;
          on EuroPython 2020. Do watch it, or watch the YouTube video after it&amp;rsquo;s released.
        &lt;/p&gt;
        
        &lt;!-- more --&gt;
        
        &lt;p&gt;
          To change my strings, I need to unwind the old ones all the way through, and then wind the new ones manually, using these tuning pegs:
        &lt;/p&gt;
        
        &lt;div class="center_image_container"&gt;
          &lt;figure class="tmblr-full" data-orig-height="1231" data-orig-width="1394" data-orig-src="https://i.imgur.com/FIFjLtv.jpg"&gt;&lt;img src="https://64.media.tumblr.com/3d9a19723d4233bc6ae2e6882312a354/2aa585d685b569c0-5e/s540x810/5c757440320828c908e1ccb5740a334404c11f36.jpg" style="max-width: 600px;" data-orig-height="1231" data-orig-width="1394" data-orig-src="https://i.imgur.com/FIFjLtv.jpg"/&gt;&lt;/figure&gt;&lt;/div&gt;
        
        &lt;p&gt;
          Ain&amp;rsquo;t nobody got time for that! 3D-printing to the rescue:
        &lt;/p&gt;
        
        &lt;div class="center_image_container"&gt;
          &lt;figure class="tmblr-full" data-orig-height="471" data-orig-width="467" data-orig-src="https://i.imgur.com/3fW3JDH.jpg"&gt;&lt;img src="https://64.media.tumblr.com/3a322061a788c77ca178b0591643d28e/2aa585d685b569c0-1c/s540x810/1a8272c289dea506125474fa1cb6d721e8f9b6f2.jpg" data-orig-height="471" data-orig-width="467" data-orig-src="https://i.imgur.com/3fW3JDH.jpg"/&gt;&lt;/figure&gt;&lt;/div&gt;
        
        
        &lt;p&gt;
          Printing took only 25 minutes:
        &lt;/p&gt;
        
        &lt;div class="center_image_container"&gt;
          &lt;figure class="tmblr-full" data-orig-height="330" data-orig-width="600" data-orig-src="https://i.imgur.com/WVIPuRa.gif"&gt;&lt;img src="https://64.media.tumblr.com/5c0a40dfba15b5caf243105945cb6941/2aa585d685b569c0-21/s540x810/ea68b17f12613878159e9f27208de976939f16fb.gif" style="max-width: 600px;" data-orig-height="330" data-orig-width="600" data-orig-src="https://i.imgur.com/WVIPuRa.gif"/&gt;&lt;/figure&gt;&lt;/div&gt;
        
        &lt;p&gt;
          After connecting it to my electric screwdriver, it worked perfectly:
        &lt;/p&gt;
        
        &lt;div class="center_image_container"&gt;
         &lt;iframe width="560" height="315" src="https://www.youtube.com/embed/6UX9oX-sL34" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;
        &lt;/div&gt;
        
        &lt;p&gt;
          Good times :)
        &lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/624430307333079040</link><guid>https://blog.ram.rachum.com/post/624430307333079040</guid><pubDate>Thu, 23 Jul 2020 14:19:05 +0300</pubDate></item><item><title>Improving Python exception chaining with raise-from</title><description>&lt;h2&gt;
          &lt;a href="#"&gt;
            Improving Python exception chaining with raise-from
          &lt;/a&gt;
        &lt;/h2&gt;
        
        &lt;p&gt;
          This is going to be a story about an esoteric feature of Python 3, and how I spent the last few months reviving it and bringing it into the limelight.
        &lt;/p&gt;
        
        &lt;p&gt;
          Back in the yee-haw days of 2003, Raymond Hettinger
          &lt;a href="https://mail.python.org/pipermail/python-dev/2003-January/032492.html"&gt;wrote an email&lt;/a&gt;
          to the python-dev mailing list, sharing an idea for improving the way that Python handles exceptions that are caught and replaced with other exceptions. The goal was to avoid losing information about the first exception while reporting the second one. Showing the full information to the user would make debugging easier, and if you&amp;rsquo;ve
          &lt;a href="https://github.com/cool-RR/PySnooper/"&gt;followed my work before,&lt;/a&gt;
          you know there&amp;rsquo;s nothing I love better than that.
        &lt;/p&gt;
        
        &lt;!-- more --&gt;
        
        &lt;p&gt;
          That idea was polished and refined by many discussions on python-dev. A year later, Python core developer
          &lt;a href="http://zesty.ca/"&gt;Ka-Ping Yee&lt;/a&gt;
          wrote up a comprehensive PEP that was then known as PEP 344, later to be renamed to
          &lt;a href="https://www.python.org/dev/peps/pep-3134/"&gt;PEP 3134.&lt;/a&gt;
          That idea was detailed there, with all the loose ends, potential problems and solutions. Guido accepted the PEP, and it was implemented for the infamous Python 3.0, to be used&amp;hellip; By no one. For a long time.
        &lt;/p&gt;
        
        &lt;p&gt;
          If there&amp;rsquo;s one thing I don&amp;rsquo;t miss, it&amp;rsquo;s waiting 10 years for the Python ecosystem to adopt Python 3. But finally, it happened. Almost all the packages on PyPI support Python 3 now, and getting a job writing Python 3 code is no longer a luxury. Only a few days ago, NumPy finally dropped Python 2 support. We live in good times.
        &lt;/p&gt;
        
        &lt;p&gt;
          When a modern Python developer catches an exception and raises a new one to replace it, they can enjoy seeing the complete information for both tracebacks. This is very helpful for debugging, and is a win for everybody.
        &lt;/p&gt;
        
        &lt;p&gt;
          Except&amp;hellip; For one thing.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          Two cases of exception chaining
        &lt;/h3&gt;
        
        &lt;p&gt;
          There was one interesting detail of PEP 3134 that was forgotten: It has to do with the question, &amp;ldquo;What does it
          &lt;i&gt;
            mean
          &lt;/i&gt;
          when one exception is replaced with another? Why would someone make that switcheroo?&amp;rdquo;
        &lt;/p&gt;
        
        &lt;p&gt;
          These can be roughly divided into two cases, and PEP 3134 provided a solution for each case.
        &lt;/p&gt;
        
        &lt;p&gt;
          The first case is this:
        &lt;/p&gt;
        
        &lt;blockquote&gt;
            &amp;ldquo;An exception was raised, we were handling it, and something went wrong in the process of handling it.&amp;rdquo;
          &lt;/blockquote&gt;
        
        
        &lt;p&gt;
          The second case is this:
        &lt;/p&gt;
        
        &lt;blockquote&gt;
            &amp;ldquo;An exception was raised, and we decided to replace it with a different exception that will make more sense to whoever called this code. Maybe the new exception will make more sense because we&amp;rsquo;re giving a more helpful error message. Or maybe we&amp;rsquo;re using an exception class that&amp;rsquo;s more relevant to the problem domain, and whoever&amp;rsquo;s calling our code could wrap the call with an
            &lt;code&gt;
              except
            &lt;/code&gt;
            clause that&amp;rsquo;s tailored for this failure mode.&amp;rdquo;
          &lt;/blockquote&gt;
        
        
        &lt;p&gt;
          That second case is quite a mouthful, isn&amp;rsquo;t it? It didn&amp;rsquo;t help that the first case was defined as the default. The second case ended up falling by the wayside. Most Python developers haven&amp;rsquo;t learned how to tell Python that the second case is what&amp;rsquo;s happening in their code, and to listen when Python is telling them that it&amp;rsquo;s happening in code that they&amp;rsquo;re currently debugging. This resulted in a Catch 22 situation, not that different from the one that slowed down Python 3 adoption in the first place.
        &lt;/p&gt;
        
        &lt;p&gt;
          Before I tell you what I did to break that Catch 22, I&amp;rsquo;ll bring you into the fold and show you how to make that feature work in your project.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          Exception causes, or `raise new from old`
        &lt;/h3&gt;
        
        &lt;p&gt;
          I&amp;rsquo;m going to show you both sides of this feature: How to tell Python that you&amp;rsquo;re catching an exception to replace it with a friendlier one, and how to understand when Python is telling you that this is what&amp;rsquo;s happening in code that you&amp;rsquo;re debugging.
        &lt;/p&gt;
        
        &lt;p&gt;
          For the first part, here&amp;rsquo;s
          &lt;a href="https://github.com/cool-RR/mypy/blob/e034e8e117be72ca12f483587f07939e4ab25f72/mypy/ipc.py#L238"&gt;
            a good example from MyPy&amp;rsquo;s codebase:
          &lt;/a&gt;
        &lt;/p&gt;
        
        &lt;pre&gt;
            &lt;code&gt;
              try:
                  self.connection, _ = self.sock.accept()
              except socket.timeout as e:
                  raise IPCException('The socket timed out') from e
            &lt;/code&gt;
          &lt;/pre&gt;
        
        
        &lt;p&gt;
          See the
          &lt;code&gt;
            from e
          &lt;/code&gt;
          bit at the end? That&amp;rsquo;s the bit that tells Python: The
          &lt;code&gt;
            IPCException
          &lt;/code&gt;
          that we&amp;rsquo;re raising is just a friendlier version of the
          &lt;code&gt;
            socket.timeout
          &lt;/code&gt;
          that we just caught.
        &lt;/p&gt;
        
        &lt;p&gt;
          When we run that code and reach that exception, the traceback is going to look like this:
        &lt;/p&gt;
        
        &lt;pre&gt;
            &lt;code&gt;
              Traceback (most recent call last):
                File "foo.py", line 19, in &lt;module&gt;
                  self.connection, _ = self.sock.accept()
                File "foo.py", line 7, in accept
                  raise socket.timeout
              socket.timeout
        
              &lt;b&gt;The above exception was the direct cause of the following exception:&lt;/b&gt;
        
              Traceback (most recent call last):
                File "foo.py", line 21, in &lt;module&gt;
                  raise IPCException('The socket timed out') from e
              IPCException: The socket timed out
            &lt;/module&gt;&lt;/module&gt;&lt;/code&gt;
          &lt;/pre&gt;
        
        
        &lt;p&gt;
          See that message in the middle, about the exception above being the direct cause of the exception below? That&amp;rsquo;s the important bit. That&amp;rsquo;s how you know you have a case of a friendly wrapping of an exception.
        &lt;/p&gt;
        
        &lt;p&gt;
          If you were dealing with the first case, i.e. an exception handler that has an error in it, the message between the two tracebacks would be:
        &lt;/p&gt;
        
        &lt;pre&gt;
            &lt;code&gt;
              During handling of the above exception, another exception occurred:
            &lt;/code&gt;
          &lt;/pre&gt;
        
        
        &lt;p&gt;
          That&amp;rsquo;s it. Now you can tell the two cases apart.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          What I did to push this feature
        &lt;/h3&gt;
        
        &lt;p&gt;
          I found that almost no one knows about this feature, which is sad, because I think it&amp;rsquo;s a useful piece of information when debugging. I decided I&amp;rsquo;ll do my part to push the Python community to use this syntax.
        &lt;/p&gt;
        
        &lt;p&gt;
          I wrote a little script that uses Python&amp;rsquo;s
          &lt;a href="https://docs.python.org/3/library/ast.html"&gt;ast&lt;/a&gt;
          module to analyze a codebase and find all instances where this syntax isn&amp;rsquo;t used and should be. The heuristic was simple: If you&amp;rsquo;re doing a
          &lt;code&gt;
            raise
          &lt;/code&gt;
          inside an
          &lt;code&gt;
            except
          &lt;/code&gt;
          then in 99.9% of cases you&amp;rsquo;re wrapping an exception.
        &lt;/p&gt;
        
        &lt;p&gt;
          I took the output from that script and used it to open PRs to a slew of open-source Python packages. Some of the projects I fixed are:
          &lt;a href="https://github.com/pypa/setuptools/pull/2189"&gt;Setuptools&lt;/a&gt;, &lt;a href="https://github.com/scipy/scipy/pull/12353"&gt;SciPy&lt;/a&gt;, &lt;a href="https://github.com/matplotlib/matplotlib/pull/16706"&gt;Matplotlib&lt;/a&gt;, &lt;a href="https://github.com/pandas-dev/pandas/pull/32322"&gt;Pandas&lt;/a&gt;, &lt;a href="https://github.com/pytest-dev/pytest/pull/7387"&gt;PyTest&lt;/a&gt;, &lt;a href="https://github.com/ipython/ipython/pull/12383"&gt;IPython&lt;/a&gt;, &lt;a href="https://github.com/python/mypy/pull/8998"&gt;MyPy&lt;/a&gt;, &lt;a href="https://github.com/pygments/pygments/pull/1482"&gt;Pygments&lt;/a&gt; and &lt;a href="https://github.com/sphinx-doc/sphinx/pull/7832"&gt;Sphinx&lt;/a&gt;.
          Check out my GitHub history for the full list.
        &lt;/p&gt;
        
        &lt;p&gt;
          I then
          &lt;a href="https://github.com/PyCQA/pylint/pull/3695"&gt;added a rule&lt;/a&gt;
          to PyLint, now known as
          &lt;b&gt;
            W0707: raise-missing-from.
          &lt;/b&gt;
          After the PyLint team makes the next release, and the thousands of projects around the world that use PyLint upgrade to that release, they will all get an error when they fail to use
          &lt;code&gt;
            raise from
          &lt;/code&gt;
          in places they should.
        &lt;/p&gt;
        
        &lt;p&gt;
          Hopefully, in a few years&amp;rsquo; time, this feature of Python will become more ingrained in the Python community.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          What you can do to help
        &lt;/h3&gt;
        
        &lt;p&gt;
          Do you maintain a Python project that already dropped Python 2 support? Install the latest version of PyLint from GitHub. You can do this in a virtualenv if you&amp;rsquo;d like to keep your system Python clean. Run this to install:
        &lt;/p&gt;
        
        &lt;pre&gt;
            &lt;code&gt;
              pip install git+https://github.com/PyCQA/pylint
            &lt;/code&gt;
          &lt;/pre&gt;
        
        
        &lt;p&gt;
          Then, run this line on your repo:
        &lt;/p&gt;
        
        &lt;pre&gt;
            &lt;code&gt;
              pylint your_project_path | grep W0707
            &lt;/code&gt;
          &lt;/pre&gt;
        
        
        &lt;p&gt;
          You&amp;rsquo;ll get a list of lines showing where you should add
          &lt;code&gt;
            raise from
          &lt;/code&gt;
          in your code. If you&amp;rsquo;re not getting any output, your code is good!
        &lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/621791438475296768</link><guid>https://blog.ram.rachum.com/post/621791438475296768</guid><pubDate>Wed, 24 Jun 2020 11:15:25 +0300</pubDate><category>planetpython</category><category>python</category><category>open-source</category><category>programming</category><category>debugging</category></item><item><title>Symlinks and hardlinks, move over, make room for reflinks!</title><description>&lt;h2&gt;
          &lt;a href="#"&gt;
            Symlinks and hardlinks, move over, make room for reflinks!
          &lt;/a&gt;
        &lt;/h2&gt;
        
        &lt;p&gt;
          If you&amp;rsquo;ve been around Linux for a while, you know about
          &lt;a href="https://en.wikipedia.org/wiki/Symbolic_link"&gt;symlinks&lt;/a&gt;
          and
          &lt;a href="https://en.wikipedia.org/wiki/Hard_link"&gt;hardlinks.&lt;/a&gt;
          You&amp;rsquo;ve used them and you know the differences between how each of them behaves. Besides being a useful filesystem tool, they&amp;rsquo;re also a favorite interview question, used to gauge a candidate&amp;rsquo;s familiarity with filesystems.
        &lt;/p&gt;
        
        &lt;p&gt;
          What you might not know is that there&amp;rsquo;s also a thing called
          &lt;b&gt;reflink.&lt;/b&gt;
          Right now it&amp;rsquo;s supported only on a handful of filesystems, such as Apple&amp;rsquo;s
          &lt;a href="https://en.wikipedia.org/wiki/APFS"&gt;APFS,&lt;/a&gt;
          used on all Apple devices,
          &lt;a href="https://en.wikipedia.org/wiki/XFS"&gt;XFS&lt;/a&gt;
          which is used on lots of Linux file-sharing servers,
          &lt;a href="https://en.wikipedia.org/wiki/Btrfs"&gt;Btrfs,&lt;/a&gt;
          &lt;a href="https://en.wikipedia.org/wiki/OCFS2"&gt;OCFS2,&lt;/a&gt;
          and Microsoft&amp;rsquo;s
          &lt;a href="https://en.wikipedia.org/wiki/ReFS"&gt;ReFS.&lt;/a&gt;
        &lt;/p&gt;
        
        
        
        
        &lt;p&gt;
          If a symlink is a shortcut to another file, and a hardlink is a first-class pointer to the same inode as another file, what&amp;rsquo;s a reflink, and when is it useful?
        &lt;/p&gt;
        
        &lt;!-- more --&gt;
        
        &lt;p&gt;
          A reflink is a tool for doing
          &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write"&gt;copy-on-write&lt;/a&gt;
          on the filesystem.
        &lt;/p&gt;
        
        &lt;p&gt;
          If you&amp;rsquo;ve heard the term copy-on-write before, I&amp;rsquo;m willing to bet that it was
          &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write#In_virtual_memory_management"&gt;
            in the context of the Linux fork call.
          &lt;/a&gt;
          Let&amp;rsquo;s talk a bit about that.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          Copy-on-write when forking a process
        &lt;/h3&gt;
        
        &lt;p&gt;
          When you fork a process in Linux, the new process has a new copy of the old process&amp;rsquo;s memory. This is essential, because if the new process shared the old process&amp;rsquo;s memory, either process could crash if the other process was making an unexpected change to their shared memory. Therefore, Linux needs to make a copy.
        &lt;/p&gt;
        
        &lt;p&gt;
          However, Linux is smart, and it knows better than to just make a naive copy. Making a naive copy could be a waste of memory, especially if your process has several gigabytes of memory allocated, and you&amp;rsquo;re forking lots of processes for small tasks. If Linux were to make naive copies, you could find yourself with an out-of-memory crash very quickly.
        &lt;/p&gt;
        
        &lt;p&gt;
          When you fork a process, Linux uses copy-on-write to create the new process&amp;rsquo;s memory. This means that it holds off on making actual copies of the existing memory pages until the last possible moment; which means, the moment when the two processes start having different ideas on what the content of these memory pages should be. In other words, as soon as one of these processes start writing to these memory pages, Linux makes a copy of it, assigning the original page to the original process, and the new copy to the newly-forked process.
        &lt;/p&gt;
        
        &lt;p&gt;
          This is a huge boon, because most of the time, the new process will either only be reading the memory, or not even that. So many copy actions are avoided thanks to this technique. The beauty part is that these shenanigans are completely transparent to the process, and to the developer who&amp;rsquo;s writing the logic that this process performs. The new process behaves as if it has its own copy of the parent&amp;rsquo;s memory pages, and the floor is being paved ahead of it as it walks forward, so to speak. It&amp;rsquo;ll never even know that copy-on-write was performed.
        &lt;/p&gt;
        
        &lt;p&gt;
          Now we&amp;rsquo;re ready to talk about reflinks.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          Reflinks are copy-on-write for the filesystem
        &lt;/h3&gt;
        
        &lt;p&gt;
          If you read the section above, you already know 90% of what you need to know to understand and use reflinks.
        &lt;/p&gt;
        
        &lt;p&gt;
          A reflink is a copy of a file, except that copy isn&amp;rsquo;t really created on the hard-drive until the last possible moment. Like the forking version, this logic is invisible. You could do a reflink of a 10 gigabyte file, and the new &amp;ldquo;copy&amp;rdquo; would be created immediately, because the 10 gigabytes wouldn&amp;rsquo;t really be duplicated. They&amp;rsquo;ll only be duplicated once you start modifying one of the copies.
        &lt;/p&gt;
        
        &lt;p&gt;
          All the while, you could treat the reflink as if it was a completely legitimate copy of your original file.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          How do you create reflinks?
        &lt;/h3&gt;
        
        &lt;p&gt;
          On Linux, run the following:
        &lt;/p&gt;
        
        &lt;pre&gt;
          &lt;code&gt;
            $ cp --reflink old_file new_file
          &lt;/code&gt;
        &lt;/pre&gt;
        
        &lt;p&gt;
          On Mac, there&amp;rsquo;s a different flag for some reason:
        &lt;/p&gt;
        
        &lt;pre&gt;
          &lt;code&gt;
            $ cp -c old_file new_file
          &lt;/code&gt;
        &lt;/pre&gt;
        
        &lt;p&gt;
          If you&amp;rsquo;re creating reflinks programmatically, you could also use dedicated libraries such as
          &lt;a href="https://pypi.org/project/reflink/"&gt;this one&lt;/a&gt;
          for Python.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          When are reflinks useful?
        &lt;/h3&gt;
        
        &lt;p&gt;
          Here&amp;rsquo;s an example of where I&amp;rsquo;ve used reflinks for a client of mine years back. They had a tool for developers that takes their entire codebase and copies it into a Docker container to run tests on it. (Don&amp;rsquo;t ask.)
        &lt;/p&gt;
        
        &lt;p&gt;
          That recursive copying took a while, and the developers couldn&amp;rsquo;t change their code in the meanwhile, or checkout any other branches, because then an inconsistent version of their code would be copied into the container. That was pretty annoying for me personally, because I was twiddling my thumbs whenever I started the test process.
        &lt;/p&gt;
        
        &lt;p&gt;
          I figured, why not use reflinks?
        &lt;/p&gt;
        
        &lt;p&gt;
          I wrote some Python code that creates reflinks to the code in a temporary folder, and then does a real copy from that temporary folder to the Docker container. The big advantage here is that as soon as the reflinks were created, I could modify the original code as much as I wanted, without affecting the tests.
        &lt;/p&gt;
        
        &lt;p&gt;
          Fortunately, all the developers were using Macs in that company, so I knew I didn&amp;rsquo;t have to worry about filesystem support.
        &lt;/p&gt;
        
        
        &lt;h3&gt;
          How can reflinks go wrong?
        &lt;/h3&gt;
        
        &lt;p&gt;
          You might be thinking, &amp;ldquo;What happens if I create a reflink of a huge file, that&amp;rsquo;s bigger than the amount of space I have available on the harddrive?&amp;rdquo;
        &lt;/p&gt;
        
        &lt;p&gt;
          I&amp;rsquo;ve never tried this, but here&amp;rsquo;s what I heard: The reflink will be created, but then you&amp;rsquo;ll get an error as soon as one of the copies will be changed, and an actual copy will need to be created. I haven&amp;rsquo;t tested this, but this is something you should take into account if you&amp;rsquo;re relying on reflinks in your business logic.
        &lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/620335081764077568</link><guid>https://blog.ram.rachum.com/post/620335081764077568</guid><pubDate>Mon, 08 Jun 2020 09:27:15 +0300</pubDate><category>planetpython</category><category>programming</category><category>filesystems</category></item><item><title>Make your 3D prints stronger with titanium rods</title><description>&lt;h2&gt;
          &lt;a href="#"&gt;
            Make your 3D prints stronger with titanium rods
          &lt;/a&gt;
        &lt;/h2&gt;
        
        &lt;p&gt;
          I&amp;rsquo;ve been doing 3D printing for a few years, and there&amp;rsquo;s a technique I&amp;rsquo;ve been using that I thought I should share with the world. This was also a good opportunity to make my first YouTube video. Enjoy :)
        &lt;/p&gt;
        
        &lt;p&gt;
          &lt;a href="https://www.youtube.com/watch?v=cF6GeIu3RMA&amp;gt;%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20&amp;lt;figure%20data-orig-height=" data-orig-width="1649" data-orig-src="https://i.imgur.com/HQpSwGJ.jpg" class="tmblr-full"&gt;
              &lt;figure class="tmblr-full" data-orig-height="927" data-orig-width="1649" data-orig-src="https://i.imgur.com/HQpSwGJ.jpg"&gt;&lt;img src="https://64.media.tumblr.com/b1a0f6f8ba5f92fa64323b610f13c334/01d183a59c114538-24/s540x810/979c19174f30e656ce7729109c5feaa13e40932a.jpg" data-orig-height="927" data-orig-width="1649" data-orig-src="https://i.imgur.com/HQpSwGJ.jpg" alt="image"/&gt;&lt;/figure&gt;&lt;/a&gt;
        &lt;/p&gt;
        
        &lt;p&gt;
          Affiliate links to equipment I used in the video:
        &lt;/p&gt;
        
        &lt;p&gt;
          •
          &lt;a href="https://amzn.to/3fqx0wn"&gt;
            Pin vise
          &lt;/a&gt;
          &lt;br/&gt;
        
          •
          &lt;a href="https://amzn.to/30EGbW2"&gt;
            Heavy-duty, keyed pin vise
          &lt;/a&gt;
          &lt;br/&gt;
        
          •
          &lt;a href="https://amzn.to/2N3n6oc"&gt;
            Jeweller&amp;rsquo;s vise
          &lt;/a&gt;
          &lt;br/&gt;
        
          •
          &lt;a href="https://amzn.to/2C1JI6m"&gt;
            Medium-sized bolt cutter
          &lt;/a&gt;
          &lt;br/&gt;
        
          •
          &lt;a href="https://amzn.to/2Y4oEVG"&gt;
            Big bolt cutter
          &lt;/a&gt;
          &lt;br/&gt;&lt;/p&gt;
        
        &lt;p&gt;
          Buy titanium rods
          &lt;a href="https://www.ebay.com/sch/i.html?_nkw=3mm+titanium+rod+grade+5"&gt;
            on eBay.
          &lt;/a&gt;
        &lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/619267414709944320</link><guid>https://blog.ram.rachum.com/post/619267414709944320</guid><pubDate>Wed, 27 May 2020 14:37:07 +0300</pubDate></item><item><title>git-recent: Quickly check out your favorite branches</title><description>&lt;h2&gt;git-recent: Quickly check out your favorite branches&lt;/h2&gt;
&lt;p&gt;I released yet another open-source project!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/cool-RR/git-recent/"&gt;https://github.com/cool-RR/git-recent/&lt;/a&gt;&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/618359891885703168</link><guid>https://blog.ram.rachum.com/post/618359891885703168</guid><pubDate>Sun, 17 May 2020 14:12:27 +0300</pubDate></item><item><title>PySnooper: Never use print for debugging again</title><description>&lt;h2&gt;PySnooper: Never use print for debugging again&lt;/h2&gt;
&lt;p&gt;I just released a new open-source project!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/cool-RR/PySnooper/"&gt;https://github.com/cool-RR/PySnooper/&lt;/a&gt;.&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/184362978203</link><guid>https://blog.ram.rachum.com/post/184362978203</guid><pubDate>Mon, 22 Apr 2019 13:54:01 +0300</pubDate><category>python</category><category>planetpython</category><category>programming</category><category>open-source</category></item><item><title>Mike Driscoll interviewed me on his blog</title><description>&lt;h2&gt;Mike Driscoll interviewed me on his blog&lt;/h2&gt;
&lt;p&gt;I recently had the pleasure of being interviewed by Mike Driscoll on his blog, &lt;a href="http://www.blog.pythonlibrary.org/"&gt;The Mouse vs. The Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mike is well-known in the Python world and especially in the wxPython user group. He often posts tutorials for beginners on his blog, and it&amp;rsquo;s happened serveral times that I googled a technical question and found the answer in one of his tutorials.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.blog.pythonlibrary.org/2015/08/10/pydev-of-the-week-ram-rachum/"&gt;Head over to Mike&amp;rsquo;s blog to read the interview.&lt;/a&gt;&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/126350146203</link><guid>https://blog.ram.rachum.com/post/126350146203</guid><pubDate>Mon, 10 Aug 2015 20:06:19 +0300</pubDate><category>python</category><category>planetpython</category><category>programming</category><category>open-source</category></item><item><title>PythonTurtle makes it into Saudi Arabia's official state curriculum</title><description>&lt;h2&gt;PythonTurtle makes it into Saudi Arabia’s official state curriculum&lt;/h2&gt;&lt;p&gt;I just heard some very exciting news.&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Six years ago, when I was just starting out my development career, I made a little program called &lt;a href="http://pythonturtle.org/"&gt;PythonTurtle&lt;/a&gt;. It’s a program that helps children learn how to program in the &lt;a href="https://www.python.org/"&gt;Python programming language&lt;/a&gt;, which is the programming language that I use it my day-to-day work as a web developer. I created PythonTurtle as a side project, because I saw there wasn’t a viable solution for children to learn how to program in Python. I figured there should be a solution, so I spent roughly two months of hard work building and releasing PythonTurtle.&lt;/p&gt;&lt;!-- more --&gt;
&lt;p&gt;Screenshot from the program:&lt;/p&gt;
&lt;div class="center_image_container"&gt;&lt;a href="http://PythonTurtle.org"&gt;&lt;figure class="tmblr-full" data-orig-height="472" data-orig-width="465" data-orig-src="https://64.media.tumblr.com/d7c0548de05ebbf4ccee5e2684b1aa1b/tumblr_inline_nkj6xnUAdK1qzywlj.gif"&gt;&lt;img src="https://64.media.tumblr.com/d7c0548de05ebbf4ccee5e2684b1aa1b/tumblr_inline_pk0iw2HuRY1qzywlj_540.gif" data-orig-height="472" data-orig-width="465" data-orig-src="https://64.media.tumblr.com/d7c0548de05ebbf4ccee5e2684b1aa1b/tumblr_inline_nkj6xnUAdK1qzywlj.gif"/&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class="nicey"&gt;What’s special about PythonTurtle is that it lets children learn programming in an exciting way that puts emphasis on fun and creativity rather than technical details.&lt;/p&gt;
&lt;p&gt;When using the program, an illustrated turtle is displayed on the screen, and the children can program it to move around the screen and draw lines. The more programming concepts the children learn, the more impressive drawings they can create with the program. This gives them motivation to learn and improve their skills without feeling that it’s being forced on them by their schoolteacher.&lt;/p&gt;
&lt;p&gt;PythonTurtle is based on an educational program called &lt;a href="https://en.wikipedia.org/wiki/Logo_(programming_language)"&gt;LOGO&lt;/a&gt; that was developed in the eighties; what I made is in fact a modern version, so instead of teaching programming in a didactic language, it taught programming in the Python programming language, which is a real language used in the industry today. The idea is to bring children closer to the techniques used in the real world, and possibly plant the seeds of a career in software development.&lt;/p&gt;
&lt;div class="center_image_container"&gt;&lt;figure class="tmblr-full" data-orig-height="274" data-orig-width="301" data-orig-src="http://i.imgur.com/wK7owbX.png"&gt;&lt;img src="https://64.media.tumblr.com/d476d651681d4529f122b7971ed31e10/tumblr_inline_pk0iw2tc6p1qzywlj_540.png" data-orig-height="274" data-orig-width="301" data-orig-src="http://i.imgur.com/wK7owbX.png"/&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Because I was just starting out as software developer back then, I didn’t have the skills that I have today, and developing this software was hard for me. There were technical challenges (specifically modifying the wxPython shell to be able to command an auxiliary process.) These challenges were so hard, that it looked like I wasn’t going to solve them, and at a few points I considered giving up on the project entirely. I was asking myself, why am I even doing this? No one even knew I was working on this program, and no one seemed to care. &lt;/p&gt;
&lt;p class="nicey"&gt;But I told myself that I’m creating something big here, and it’s important that I see this through to the end. So I did, and I overcame the technical problems.&lt;/p&gt;
&lt;p&gt;I released the program as open-source under the MIT license, which means that every person on Earth could download it and use it free of charge. I decided to release it that way rather than as commercial software because I figured more children could use it if it was free, and that seemed more important to me than making a few bucks. I also liked the idea of contributing back to the open-source community, because so much of the software that I use every day is built on open-source software that was made by volunteers, so I was happy to contribute my share of open-source software.&lt;/p&gt;
&lt;p&gt;I released the software for download and I submitted a link to the website to tech forums such as HN and Reddit, and over the next few days, the story blew up, and thousands of people visited the website. I was very happy and proud that people liked my project so much.&lt;/p&gt;
&lt;p&gt;Over the six years since I’ve released the program, I’ve gotten many happy emails from teachers and parents who used the program to teach their children to program. It’s always heartwarming to get these emails. They come from all over the world: From the States, from the UK, from Africa, Australia, South America… I would occasionally also get emails from children themselves, and one time even from a 80-year-old man who said that he used my program to learn to program himself. &lt;a href="http://www.algorithm.co.il/blogs/programming/python/pythonturtle-delivers/"&gt;I got more reports of adults enjoying using the program.&lt;/a&gt; Looking at the analytics for the website, I saw that PythonTurtle was downloaded almost 100,000 times, which made me very proud.&lt;/p&gt;
&lt;p&gt;But last year, I’ve noticed something odd. I was checking how the site is doing on Google Analytics and saw that I’m getting a disproportionally large number of hits from Saudi Arabia.&lt;/p&gt;
&lt;div class="center_image_container"&gt;&lt;figure class="tmblr-full" data-orig-height="141" data-orig-width="453" data-orig-src="http://i.imgur.com/s4nDJsQ.png"&gt;&lt;img src="https://64.media.tumblr.com/1977d2c669ed907b18cf582ce4b80833/tumblr_inline_pk0iw3ELOo1qzywlj_540.png" style="background: black;" data-orig-height="141" data-orig-width="453" data-orig-src="http://i.imgur.com/s4nDJsQ.png"/&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Specifically, there was a big peak of Saudi visitors around January 2014, and than that peak appeared again in January 2015. I also got more feedback emails from people with Arab-sounding names. I investigated why, and found a Saudi forum where PythonTurtle was mentioned. The text was in Arabic, and I tried translating it to English using Google Translate, but the result was too hard to understand, so I let it go and didn’t investigate further. &lt;/p&gt;
&lt;p&gt;Until a couple of days ago, I got an email from a teacher from Saudi Arabia about PythonTurtle. He told me that PythonTurtle is being used in all high-schools in Saudi Arabia! The ministry of education of Saudi Arabia has put PythonTurtle into the official state curriculum! This means that it’s being used by more than &lt;u&gt;4,000 schools&lt;/u&gt; which teach more than &lt;u&gt;700,000 students&lt;/u&gt;!!!&lt;/p&gt;
&lt;p&gt;I’m very excited to have made a program that has helped so many students, and especially the students in Saudi Arabia. I’m an Israeli, and there are no diplomatic relations between Israel and Saudi Arabia. I’m an ignorant regarding the political affairs between the countries, but I’m happy to see that open-source software has no borders; if a developer in one country makes a program that can help people, it can be used everywhere and help people all around the world, regardless of the political situation.&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/112404870538</link><guid>https://blog.ram.rachum.com/post/112404870538</guid><pubDate>Sun, 01 Mar 2015 14:10:08 +0200</pubDate><category>python</category><category>planetpython</category><category>PythonTurtle</category><category>education</category><category>Israel</category><category>programming</category><category>open-source</category><category>middle east</category></item><item><title>Christoph Gohlke's awesome collection of Windows binaries for Python packages</title><description>&lt;h2&gt;Christoph Gohlke&amp;rsquo;s awesome collection of Windows binaries for Python packages&lt;/h2&gt;&lt;p&gt;Today I needed to upgrade the &lt;code&gt;psycopg2&lt;/code&gt; package on a Django app of one of my clients. Without giving it a second thought, I fired up my browser and started typing &lt;b&gt;goh &lt;/b&gt;in the omnibar. I quickly got Christoph Gohlke’s page, which is on my favorites:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/"&gt;http://www.lfd.uci.edu/~gohlke/pythonlibs/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;What is this? &lt;/b&gt;It’s a page where you can find Windows binaries of many popular Python packages. Whenever you need to install a Python package that requires compilation, and that package’s maintainers haven’t made Windows binaries available on PyPI, you could usually find it on Christoph’s page, categorized by package, Python version and 32bit/64bit.&lt;/p&gt;&lt;p&gt;I’ve never met Christoph. Never even spoken to him online. But he’s saved me, and thousands of other developers, from doing countless of hours of dreadful work compiling PyPI packages. His page is a godsend for anyone who does Python development on Windows.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Thank you Christoph!&lt;/b&gt;&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/110662084778</link><guid>https://blog.ram.rachum.com/post/110662084778</guid><pubDate>Tue, 10 Feb 2015 23:41:58 +0200</pubDate><category>python</category><category>planetpython</category><category>programming</category><category>windows</category></item><item><title>Startup lesson learned: Work vertically before you work horizontally</title><description>&lt;div data-band-background-image="url(http://evilcorp.co/images/band.jpg)" data-band-color="white" data-band-min-height="400px" class="band_image_container width_breaker custom_color_text"&gt;
          &lt;div class="width_container middle_table_cell"&gt;
            &lt;h2&gt;
              Startup lesson learned: Work vertically before you work horizontally
            &lt;/h2&gt;
            &lt;p&gt;In this blog post I’m going to share with you an important lesson that I’ve learned about startups. I’m happy to have learned this lesson in the beginning of my career as an entrepreneur, about a decade ago, because I got to apply it in all the projects that came afterwards, both my personal projects and my client projects.&lt;/p&gt;
          &lt;/div&gt;
        &lt;/div&gt;






&lt;p&gt;&lt;strong&gt;The year was 2006.&lt;/strong&gt; My friend and I have just founded our first startup, Bintos. We were both 20 years old. We’ve been good friends since high-school, and we’ve always dreamed of starting our own startup and making it big. Now that we were both “adults”, it was only natural that we’ll start a startup and that we’ll do it together.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;Bintos did something similar to Khan Academy, before the latter came to be famous. We wanted to produce high-quality video lectures for high-school students that would target the material they had to learn for the matriculation exams, and then, of course, put these video lectures free online. Please remember that this was 2006, when YouTube was just a young startup waiting to get acquired by Google, while Google Videos was still superior. Everyone knew that it’s only a matter of time until video on the web makes it big, but the quality and speed weren’t close to what they are today.&lt;/p&gt;
&lt;p&gt;How did we get the idea to produce video lectures for high-school students? We were both fresh out of high-school, and we remembered how difficult it was to find material to use to study for our exams. (There are a lot of books in the library, but students want learning materials that are laser-focused on the exam, because otherwise they might “waste” time learning things that aren’t on the exam :)&lt;/p&gt;
&lt;p&gt;We remembered that when we were in high-school, we were so desperate for relevant learning materials, that we were stoked to find a text-only website that was badly-formatted and almost impossible to read. The fact that such a shitty website was our best option was a sign for us that a change was necessary; so why not bring it ourselves.&lt;/p&gt;
&lt;p&gt;Now, I had just dropped out of the Technion, a leading technical university in Israel. The Technion had a very impressive and successful project of video lectures for its students. Students watched these video lectures obsessively; sometimes to cover for missed lessons, but usually to prepare for an upcoming exams. I would personally watch it from my computer in my dorm room, but most people would watch it in the university’s computer farms. They even had a vending machine giving out VHS tapes of these lectures! It was incredible.&lt;/p&gt;
&lt;p&gt;When we stared Bintos we basically wanted to take the success that video lectures had in the Technion and apply it to the world of high-school students.&lt;/p&gt;

&lt;p&gt;&lt;figure data-orig-height="320" data-orig-width="232" data-orig-src="https://64.media.tumblr.com/fefae1f25ebde711185643f50d702615/tumblr_inline_ni7yqeqqSc1qzywlj.jpg"&gt;&lt;img class="left_image" src="https://64.media.tumblr.com/fefae1f25ebde711185643f50d702615/tumblr_inline_pk0mgnzerb1qzywlj_540.jpg" title="Copyright Seth Anderson 2007, CC by-nc-sa 2.0, https://www.flickr.com/photos/swanksalot/493854770/" data-orig-height="320" data-orig-width="232" data-orig-src="https://64.media.tumblr.com/fefae1f25ebde711185643f50d702615/tumblr_inline_ni7yqeqqSc1qzywlj.jpg"/&gt;&lt;/figure&gt;Now, we were young, inexperienced and poor. Starting a startup together was &lt;strong&gt;hard&lt;/strong&gt;. Neither of us even had a job before. I wasn’t a serious programmer back then. We had little experience in being adults and talking to people seriously– An email that I would write today in 3 minutes, we would labor on for maybe 30 minutes, to make sure it had just the right mix of politeness, assertiveness, and knowing-what-the-hell-we’re-talking-about-ness. My point is that getting &lt;em&gt;anything&lt;/em&gt; done was an inefficient struggle. We were the very definition of a scrappy startup. But still, we worked hard and felt that this was our calling in life.&lt;/p&gt;
&lt;p&gt;Our main goal was to produce a sample video course that we could put online so we could get feedback from students, and hopefully investor attention. This meant we needed (a) a teacher to give the lectures, who should be as good of a teacher as we can get, (b) video equipment and knowing how to use it and © to edit the videos and putting them online on a website.&lt;/p&gt;
&lt;p&gt;After months of hard work, we got everything we needed. We got an amazing math teacher, who worked in a top private school, to volunteer to give the lectures. (I’m still amazed that my cofounder convinced him to spend a few days off from work with us for no pay.) We got the private school mentioned above to allow us to use an empty classroom to film the lectures. We hired a professional cameraman, who had a high-end camcorder that produced great video; he was also in charge of our sound recording. And we pooled our money to buy another, smaller camcorder, for the wide shot, so that we could combine footage from both cameras when we edit the video.&lt;/p&gt;
&lt;p&gt;We scheduled a few days of filming, and everything worked out great. This was the culmination of all our hard work, and we were very excited. We both sat in the back while the teacher gave the lectures and the cameraman followed him with the camera, and made sure everything went according to plan. The teacher did a great job and gave a great lecture.&lt;/p&gt;
&lt;div class="center_image_container"&gt;&lt;figure class="tmblr-full" data-orig-height="405" data-orig-width="467" data-orig-src="https://64.media.tumblr.com/fca7a1fee29e217814b31c7291c1562c/tumblr_inline_ni7ys2RQEX1qzywlj.jpg"&gt;&lt;img src="https://64.media.tumblr.com/fca7a1fee29e217814b31c7291c1562c/tumblr_inline_pk0mgnJEyM1qzywlj_540.jpg" data-orig-height="405" data-orig-width="467" data-orig-src="https://64.media.tumblr.com/fca7a1fee29e217814b31c7291c1562c/tumblr_inline_ni7ys2RQEX1qzywlj.jpg"/&gt;&lt;/figure&gt;&lt;/div&gt;

&lt;p&gt;After we finished all the filming, I sat down to do the arduous work of editing all that footage down to consumable video lectures. (I picked up Adobe Premiere for this task.) We converted all the footage from MiniDV tapes to files, and I took a look at the footage. The footage from the auxiliary camera was good; the sound quality was shitty because it was using the on-camera microphone, but no worries, the main camera was the one connected to the collar microphone that the teacher was wearing, so we’ll use that.&lt;/p&gt;
&lt;p&gt;I load up a video file from the main camera and play it. The video quality is great, audio is loud and clear with no background noises, everything looks perfect…&lt;/p&gt;
&lt;p&gt;And then: &lt;strong&gt;Swoosh swoosh.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A loud, unpleasant noise. I was confused. A few more seconds of perfect audio went by, and then again: &lt;strong&gt;Swoosh swoosh swoosh swoosh.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That noise turned out to be the collar microphone, that wasn’t attached firmly enough, rubbing against the teacher’s sweater.&lt;/p&gt;
&lt;p&gt;I looked at different points in the video file, and at other video files from the same camera. They all had those sounds all over the place. At most it would be gone for 15 seconds, and then it would come back again.&lt;/p&gt;
&lt;p&gt;I showed this to my friend, and we were devastated. That noise was so loud and distracting, we couldn’t release a lecture that had it. We considered what we could do. We tried to digitally remove it, but I doubt even professionals could do that, certainly not us. We considered using audio from the second camera, but the quality was bad, the teacher’s voice was muffled and there was lots of echo.&lt;/p&gt;
&lt;p&gt;We ended up having to refilm the whole thing. We were very lucky that the teacher was patient with us and volunteered a couple more days to help us. The cameraman took responsibility (after some arguing…), since he was supposed to be in charge of the sound, and he gave us those extra days for free. So we got to produce the lectures at the end and do it right: We made 100% sure there weren’t any noises when we filmed, and the lectures came out great after I edited them.&lt;/p&gt;
&lt;p&gt;But after the whole thing was done, I stopped to think: &lt;strong&gt;What can I learn from this?&lt;/strong&gt; How can I prevent something like this from happening again in the future? What’s the mistake I made?&lt;/p&gt;
&lt;p class="nicey"&gt;My mistake was working horizontally before working vertically.&lt;/p&gt;
&lt;p&gt;What do I mean by that?&lt;/p&gt;
&lt;p&gt;There were several “layers” of work. The first layer was filming the lectures. The second layer was editing them. The third layer was uploading them and making sure they looked good on the site.&lt;/p&gt;
&lt;p&gt;Every layer was a lot of work, and the most satisfying way to do work like that is to dive into the first layer, focus exclusively on it, finish it, and then move on to the next. I think that we like this method best because you get a feeling of accomplishment when you’re done with a certain type of tasks. Also, it’s probably more efficient because you get to concentrate better on each task. For example, if you were cleaning your house, you wouldn’t wash half the dishes in the sink, then clean half the floor, then scrub half the toilet, and then go back to the dishes again. You’d finish every layer of work before moving on to the next.&lt;/p&gt;
&lt;p&gt;But this method (which I call working horizontally) is good only when you’re very familiar with the work and have high confidence that nothing will go wrong. (Like housework.) When you’re doing something you’ve never done before, the right thing is to first work vertically, taking a sample amount of work and driving it through all the layers. It’s less efficient, but the reason it’s better is because you learn what every layer really looks like, and you get to make mistakes earlier rather than later, so you could apply the lessons you’ve learned when you do the bulk of the work.&lt;/p&gt;
&lt;p&gt;In the video lectures example, the right thing to do would be to film a single lecture, edit it and upload it. If that came out alright, then we should have gone forward with the course. In fact, I could have probably done the first lecture while they were still filming the other ones, so it wouldn’t have even wasted any time.&lt;/p&gt;
&lt;p class="nicey"&gt;Ever since I’ve learned this lesson, I’ve been applying it to every project that I do.&lt;/p&gt;
&lt;p&gt;When a client comes to me with a job and I look at all the work we have, I always insist on taking one sample unit of work and driving it through all the layers, just to catch any mistakes early. After that’s done, then it’s time to do the bulk of the work.&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/108164892983</link><guid>https://blog.ram.rachum.com/post/108164892983</guid><pubDate>Thu, 15 Jan 2015 15:45:05 +0200</pubDate><category>startups</category><category>story</category></item><item><title>Code comments that I find helpful</title><description>&lt;h2&gt;Code comments that I find helpful&lt;/h2&gt;&lt;p&gt;I’m a huge believer in code quality. When I write code, I put in a lot of effort to make it be as easy to read and understand as possible. Because code is read much more often than it’s written, by writing your code in a way that’s easy to understand you’re saving lots of time for the developers who are going to read your code in the future (one of them being future you) and you’re making it easy for them to build on your code and extend it.&lt;/p&gt;
&lt;p&gt;As we all know, a big part of writing good code is &lt;strong&gt;comments&lt;/strong&gt; that explain crucial points about the code. This is what this blog post is about.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;Making good code comments is not a trivial thing. We’ve all seen comments like this:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;    x += 1 # Increment x by 1&lt;/pre&gt;
&lt;p&gt;Comments like that are not only unhelpful but they are outright harmful, because they add noise to the code; they grab our attention but then don’t give us any useful information. Attention is a scarce resource that shouldn’t be wasted.&lt;/p&gt;
&lt;p&gt;Because adding comments to code adds noise, we need to make sure that our comments deliver the maximum amount of useful information in the minimum amount of noise. In this blog post I’ve listed a few kinds of comments that I put in my code to make it as clear as possible with as little noise as possible.&lt;/p&gt;
&lt;h3&gt;Comment braces&lt;/h3&gt;
&lt;p&gt;Here is a style of comments I picked up a few years ago by reading someone else’s code, and which proved really helpful since then:&lt;/p&gt;
&lt;pre class="prettyprint"&gt; 
   def calculate_length_of_recurrent_perm_space(k, fbb):
    
        # ...

        ### Doing phase one, getting all sub-FBBs: ################################
        #                                                                         #
        levels = []
        current_fbbs = {fbb}
        while len(levels) &amp;lt; k and current_fbbs:
            k_ = k - len(levels)
            levels.append(
                {fbb_: fbb_.get_sub_fbbs_for_one_key_removed()
                 for fbb_ in current_fbbs if (k_, fbb_) not in cache}
            )
            current_fbbs = set(itertools.chain(*levels[-1].values()))
        #                                                                         #
        ### Finished doing phase one, getting all sub-FBBs. #######################
        
        ### Doing phase two, solving FBBs from trivial to complex: ################
        #                                                                         #
        for k_, level in enumerate(reversed(levels), (k - len(levels) + 1)):
            if k_ == 1:
                for fbb_, sub_fbb_bag in level.items():
                    cache[(k_, fbb_)] = fbb_.n_elements
            else:
                for fbb_, sub_fbb_bag in level.items():
                    cache[(k_, fbb_)] = sum(
                        (cache[(k_ - 1, sub_fbb)] * factor for
                               sub_fbb, factor in sub_fbb_bag.items())
                    )
        #                                                                         #
        ### Finished doing phase two, solving FBBs from trivial to complex. #######&lt;/pre&gt;
&lt;p&gt;I call these “comment braces” because they look like huge vertical braces that have code in them. Even though these comments are quite bulky, I still really love them because they divide the code into different segments, which is very helpful when you have a piece of code that can be logically separated into different segments. (Of course, if you can refactor these different segments into different functions, that would be ideal, but in many cases it’s not practical.)&lt;/p&gt;
&lt;p&gt;This style of commenting makes it easier to read the code casually, because when you’re reading a line in the code you only need to think how it relates to the lines in its section, and not how it relates to the lines in the different sections.&lt;/p&gt;
&lt;h3&gt;Until challenged&lt;/h3&gt;
&lt;p&gt;“Until challenged” is a short two-word comment that communicates a common programming idiom:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;    def __lt__(self, other):
        found_strict_difference = False # Until challenged.
        all_elements = set(other) | set(self)
        for element in all_elements:
            if self[element] &amp;gt; other[element]:
                return False
            elif self[element] &amp;lt; other[element]:
                found_strict_difference = True
        return found_strict_difference&lt;/pre&gt;
&lt;p&gt;We’ve all written algorithms where we set a variable to a boolean, and then later we might flip it and we might not depending on some condition, and eventually we’re going to check the value of that variable and possibly return it. Writing a comment “Until challenged” after a variable assignment communicates that we’re using this idiom.&lt;/p&gt;
&lt;p&gt;It might be unclear to people who aren’t familiar with it, so it’s a compromise between brevity and understandability. If you want to make it more universally understandable, you can add a few words like “Set to False until we possibly discover a difference and set it to True”.&lt;/p&gt;
&lt;h3&gt;Establishing current state&lt;/h3&gt;
&lt;p&gt;Also known as, “the manual assert.” Sometimes it’s useful to make a comment somewhere in the middle of the function that describes what we’ve accomplished by this point, what is the current state, and what we’re going to do now. Example:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;    # ...
    
    if self.is_degreed and (perm.degree not in self.degrees):
        raise ValueError
    
    # At this point we know the permutation contains the correct items, and
    # has the correct degree. Now, to calculate its index number.
    if perm.is_dapplied:
        return self.undapplied.index(perm.undapplied)
    # ... &lt;/pre&gt;
&lt;p&gt;I love this kind of comment. What all good comments have in common is that they’re saying what your internal monologue would say if you tried to read the code and understand it without comments, and this comment is no different.&lt;/p&gt;
&lt;h3&gt;Clarifying else keyword&lt;/h3&gt;
&lt;p&gt;One thing that can be confusing when reading Python code is when looking at the &lt;code&gt;else&lt;/code&gt; part of a long &lt;code&gt;if-else&lt;/code&gt; clause, and not being sure what condition it is. This is where I like to add a comment reiterating the condition:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;    if actual_item_test is None:
        if isinstance(single_or_sequence, collections.Sequence):
            return tuple(single_or_sequence)
        elif single_or_sequence is None:
            return tuple()
        else:
            return (single_or_sequence,)
    else: # actual_item_test is not None
        if actual_item_test(single_or_sequence):
            return (single_or_sequence,)
        elif single_or_sequence is None:
            return ()
        else:
            return tuple(single_or_sequence)&lt;/pre&gt;
&lt;p&gt;Note the comment after the middle &lt;code&gt;else&lt;/code&gt;. It tells you which condition should be true for this &lt;code&gt;else&lt;/code&gt; clause to be executed, so you don’t have to trace it back to the original &lt;code&gt;if&lt;/code&gt; line.&lt;/p&gt;
&lt;hr&gt;&lt;p&gt;That’s all I’ve got for now. I’ll be happy to hear your code commenting tips!&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/103051530508</link><guid>https://blog.ram.rachum.com/post/103051530508</guid><pubDate>Wed, 19 Nov 2014 19:42:51 +0200</pubDate><category>python</category><category>planetpython</category><category>programming</category></item><item><title>My new open-source project: Combi, the Pythonic package for combinatorics</title><description>&lt;h2&gt;My new open-source project: Combi, the Pythonic package for combinatorics&lt;/h2&gt;&lt;p&gt;I’m proud to announce the first release of my new open-source project: Combi!&lt;/p&gt;
&lt;p&gt;Combi is a &lt;a href="http://en.wikipedia.org/wiki/Combinatorics"&gt;combinatorics&lt;/a&gt; package for Python.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/cool-RR/combi"&gt;Combi on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pypi.python.org/pypi/combi"&gt;Combi on PyPI&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://combi.readthedocs.org/en/stable/"&gt;Combi documentation.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Combi is awesome. It’s like a marshmallow that was slowly and carefully roasted at just the right temperature to make it melt inside, but not too hot as to burn it; except instead of being a marshmallow, it’s a Python package.&lt;/p&gt;
&lt;p&gt;Installation:&lt;/p&gt;
&lt;pre&gt;    $ pip install combi&lt;/pre&gt;
&lt;p&gt;&lt;figure data-orig-height="363" data-orig-width="231" data-orig-src="https://i.imgur.com/3FNk4O6.jpg"&gt;&lt;img align="right" src="https://64.media.tumblr.com/e7604ee0446b6a05fb71167acea3683e/tumblr_inline_pk004tYJgj1qzywlj_540.jpg" data-orig-height="363" data-orig-width="231" data-orig-src="https://i.imgur.com/3FNk4O6.jpg"/&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is Combi good for?&lt;/strong&gt; Combi lets you explore spaces of &lt;a href="http://en.wikipedia.org/wiki/Permutation"&gt;permutations&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Combination"&gt;combinations&lt;/a&gt; as if they were Python sequences, but without generating all the permutations/combinations in advance. It also lets you specify a lot of special conditions on these spaces. This is helpful both for scientific computing, and for general-purpose programming, as combinations and permutations are concepts that come up when solving many different kinds of programming problems.&lt;/p&gt;
&lt;p&gt;(I developed Combi while doing research for a bigger project of mine that’s going to remain a secret for a while. I call it Project SK. If you want to get updates on it when it becomes public, &lt;a href="http://eepurl.com/6Gtn5"&gt;sign up here&lt;/a&gt;.)&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;Let’s look at the simplest example of using Combi. Check out this $5 padlock in the picture. I use this padlock for my gym locker, so people won’t steal my stuff when I’m swimming in the pool. It has 8 buttons, and to open it you have to press down a secret combination of 4 buttons. I wonder though, how easy is it to crack?&lt;/p&gt;
&lt;pre&gt;    &amp;gt;&amp;gt;&amp;gt; from combi import *
    &amp;gt;&amp;gt;&amp;gt; padlock_space = CombSpace(range(1, 9), 4)
    &amp;gt;&amp;gt;&amp;gt; padlock_space
    &amp;lt;CombSpace: range(1, 9), n_elements=4&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;padlock_space&lt;/code&gt; is the space of all possible combinations for our padlock. At this point, the combinations weren’t really generated; if we’ll ask for a combination from the space, it’ll be generated on-demand:&lt;/p&gt;
&lt;pre&gt;    &amp;gt;&amp;gt;&amp;gt; padlock_space[7]
    &amp;lt;Comb, n_elements=4: (1, 2, 4, 7)&amp;gt;&lt;/pre&gt;
&lt;p&gt;As you can see, &lt;code&gt;padlock_space&lt;/code&gt; behaves like a sequence. We can get a combination by index number. We can also do other sequence-y things, like getting the index number of a combination, or slicing it, or getting the length using &lt;code&gt;len&lt;/code&gt;. This is a huge benefit because then we can explore these spaces in a declarative rather than imperative style of programming. (i.e. we don’t have to think about generating the permutations, we simply assume that the permutation space exists and we’re taking items from it at leisure.) Let’s try looking at the length of &lt;code&gt;padlock_space&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;    &amp;gt;&amp;gt;&amp;gt; len(padlock_space)
    70&lt;/pre&gt;
&lt;p&gt;Only 70 combinations. That’s pretty lame… At 3 seconds to try a combination, this means this padlock is crackable in under 4 minutes. Not very secure.&lt;/p&gt;
&lt;p&gt;In the example above, I used &lt;code&gt;CombSpace&lt;/code&gt;, which is a space of combinations. It’s a thin subclass over &lt;code&gt;PermSpace&lt;/code&gt;, which is a space of permutations. A combination is like a permutation, except order doesn’t matter.&lt;/p&gt;
&lt;p&gt;Now, because the permutations/combinations are generated on-demand, I can do something like this:&lt;/p&gt;
&lt;pre&gt;    &amp;gt;&amp;gt;&amp;gt; huge_perm_space = PermSpace(1000)
    &amp;gt;&amp;gt;&amp;gt; huge_perm_space
    &amp;lt;PermSpace: 0..999&amp;gt;&lt;/pre&gt;
&lt;p&gt;This is a perm space of all permutations of the numbers between 0 and 999. It is ginormous. The number of permutations is around 10**2500 (a number that far exceeds the number of particles in the universe.) I’m not even going to show its length in the shell session because the length number alone would fill this entire blog post. And yet you can fetch any permutation from this space by index number in a fraction of a second:&lt;/p&gt;
&lt;pre&gt;    &amp;gt;&amp;gt;&amp;gt; huge_perm_space[7]
    &amp;lt;Perm: (0, 1, 2, 3, 4, ... 997, 996, 999, 998)&amp;gt;&lt;/pre&gt;
&lt;p&gt;Note that the permutation &lt;code&gt;huge_perm_space[7]&lt;/code&gt; is a sequence by itself, where every item is a number in &lt;code&gt;range(1000)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Combi lets you specify a myriad of options on the the spaces that you create. For example, you can make some elements be fixed:&lt;/p&gt;
&lt;pre&gt;    &amp;gt;&amp;gt;&amp;gt; fixed_perm_space = PermSpace(4, fixed_map={3: 3,})
    &amp;gt;&amp;gt;&amp;gt; fixed_perm_space
    &amp;lt;PermSpace: 0..3, fixed_map={3: 3}&amp;gt;
    &amp;gt;&amp;gt;&amp;gt; tuple(fixed_perm_space)
    (&amp;lt;Perm: (0, 1, 2, 3)&amp;gt;,
     &amp;lt;Perm: (0, 2, 1, 3)&amp;gt;,
     &amp;lt;Perm: (1, 0, 2, 3)&amp;gt;,
     &amp;lt;Perm: (1, 2, 0, 3)&amp;gt;,
     &amp;lt;Perm: (2, 0, 1, 3)&amp;gt;,
     &amp;lt;Perm: (2, 1, 0, 3)&amp;gt;)&lt;/pre&gt;
&lt;p&gt;This limits the space and makes it smaller. This is useful when you’re making explorations on a huge &lt;code&gt;PermSpace&lt;/code&gt; and want to inspect only a smaller subset of it that would be easier to handle.&lt;/p&gt;
&lt;p&gt;There are many more variations that you could have on a &lt;code&gt;PermSpace&lt;/code&gt; or a &lt;code&gt;CombSpace&lt;/code&gt;. You can specify a custom domain and a custom range to a space. You can constrain it to permutations of a certain degree (e.g. &lt;code&gt;degrees=1&lt;/code&gt; to limit to transformations only.) You can do &lt;a href="https://en.wikipedia.org/wiki/Permutation#k-permutations_of_n"&gt;k-permutations&lt;/a&gt; by specifying the length of the desired permutations as &lt;code&gt;n_elements&lt;/code&gt;. You can have the permutation objects be of a custom subclass that you define, so you could provide extra methods on them that fit your use case. You can provide sequences that have some items appear multiple times and Combi would be smart about it and consider multiple occurrences of the same item to be interchangable. You can also toggle that behavior so it would treat them as unique. It’s very customizable :)&lt;/p&gt;
&lt;p&gt;Combi has a bunch more useful features that are beyond the scope of this blog post (click for links to documentation):&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="https://combi.readthedocs.org/en/stable/other_classes.html#mapspace"&gt;&lt;code&gt;MapSpace&lt;/code&gt;&lt;/a&gt; is like Python’s builtin &lt;code&gt;map&lt;/code&gt;, except it’s a sequence that allows index access.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://combi.readthedocs.org/en/stable/other_classes.html#productspace"&gt;&lt;code&gt;ProductSpace&lt;/code&gt;&lt;/a&gt; is like Python’s &lt;code&gt;itertools.product&lt;/code&gt;, except it’s a sequence that allows index access.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://combi.readthedocs.org/en/stable/other_classes.html#chainspace"&gt;&lt;code&gt;ChainSpace&lt;/code&gt;&lt;/a&gt; is like Python’s &lt;code&gt;itertools.chain&lt;/code&gt;, except it’s a sequence that allows index access.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://combi.readthedocs.org/en/stable/other_classes.html#selectionspace"&gt;&lt;code&gt;SelectionSpace&lt;/code&gt;&lt;/a&gt; is a space of all selections from a sequence, of all possible lengths.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://combi.readthedocs.org/en/stable/bags.html#bag"&gt;&lt;code&gt;Bag&lt;/code&gt;&lt;/a&gt; class is like Python’s &lt;code&gt;collections.Counter&lt;/code&gt;, except it offers far more functionality, like more arithmetic operations between bags, comparison between bags, and more. (It can do that because unlike Python’s &lt;code&gt;collections.Counter&lt;/code&gt;, it only allows natural numbers as keys.)&lt;/li&gt;
&lt;li&gt;Classes &lt;a href="https://combi.readthedocs.org/en/stable/bags.html#frozenbag"&gt;&lt;code&gt;FrozenBag&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://combi.readthedocs.org/en/stable/bags.html#orderedbag"&gt;&lt;code&gt;OrderedBag&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://combi.readthedocs.org/en/stable/bags.html#frozenorderedbag"&gt;&lt;code&gt;FrozenOrderedBag&lt;/code&gt;&lt;/a&gt; are provided, which are variations on &lt;code&gt;Bag&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I hope that the Combi package will be useful for you!&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/102876345228</link><guid>https://blog.ram.rachum.com/post/102876345228</guid><pubDate>Mon, 17 Nov 2014 17:16:00 +0200</pubDate><category>planetpython</category><category>python</category><category>combi</category><category>math</category><category>programming</category></item><item><title>Another silly Python riddle</title><description>&lt;h2&gt;Another silly Python riddle&lt;/h2&gt;&lt;p&gt;Do you think of yourself as an experienced Python developer? Do you think you know Python’s quirks inside and out? Here’s a silly riddle to test your skills.&lt;/p&gt;
&lt;p&gt;Observe the following Python code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
    def f(x):
        return x == not x
    
    f(None)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The question is: &lt;strong&gt;What will the call &lt;code&gt;f(None)&lt;/code&gt; return?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Think carefully and try to come up with an answer without running the code. Then check yourself :)&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/98581775828</link><guid>https://blog.ram.rachum.com/post/98581775828</guid><pubDate>Sun, 28 Sep 2014 01:08:00 +0300</pubDate><category>planetpython</category><category>python</category></item><item><title>Observational comedy and tickling</title><description>&lt;h2&gt;Observational comedy and tickling&lt;/h2&gt;&lt;p&gt;I had a nice thought today.&lt;/p&gt;
&lt;p&gt;I was thinking about comedy; about what makes people laugh. It’s something I think about a lot, especially that what makes people laugh the most is when you’re being your genuine self, and not apologizing about it.&lt;/p&gt;
&lt;p&gt;I was thinking about what is called &lt;a href="https://en.wikipedia.org/wiki/Observational_comedy"&gt;observational comedy&lt;/a&gt;. It’s the kind of comedy Seinfeld became famous for; it’s candid observations about everyday life that we all experience but never talk about. If you’ve ever seen one of Jerry Seinfeld’s standups on his shows, you know what I’m talking about. Here are a few random observations of his:&lt;!-- more --&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;“You know you’re getting old when you get that one candle on the cake. It’s like, ‘See if you can blow this out.’”&lt;/li&gt;
&lt;li&gt;“I am so busy doing nothing… that the idea of doing anything - which as you know, always leads to something - cuts into the nothing and then forces me to have to drop everything.”&lt;/li&gt;
&lt;li&gt;“Men don’t care what’s on TV. They only care what else is on TV.”&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;You see these kind of jokes a lot in internet memes. The beloved Louis C.K. also does a lot of gags in this style.&lt;/p&gt;
&lt;p&gt;These are things we experience in our lives, but don’t think about; so when a talented comedian comes along and voices these thoughts that we’ve been harboring for years, possibly with a nice word play or a joke on top, we can’t help but laugh. Those previously-unvoiced thoughts are like regions of our mind that was always there, but that we never think about. When someone finally sheds light on them, we laugh in delight, as we are reassured that they exist, and that other people have them too.&lt;/p&gt;
&lt;p&gt;Then it hit me: Observational comedy is very similar to tickling! If someone is tickling your foot with his finger, he’s touching a part of your body that you use all the time, but that never gets any kind of sensation other than the idiotic, montonous pounding that is walking. Suddenly, the foot that became desensitized to touch experiences a small finger touching it gently; and we laugh. Observational humor is the equivalent of tickling, except for our minds. Thoughts that we took for granted before, that we never thought about, suddenly get probed by the comedian. So we laugh.&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/95559753828</link><guid>https://blog.ram.rachum.com/post/95559753828</guid><pubDate>Sat, 23 Aug 2014 20:03:00 +0300</pubDate></item><item><title>Fun with etymology</title><description>&lt;h2&gt;Fun with etymology&lt;/h2&gt;&lt;p&gt;In Hebrew, we have an expression &amp;quot;radiophonic voice&amp;quot;. If someone has a radiophonic voice, it means they have a pleasant voice and good diction, much like a radio announcer would. &lt;/p&gt;
&lt;p&gt;&lt;figure data-orig-height="180" data-orig-width="240" data-orig-src="https://64.media.tumblr.com/88532c82dfc4ad6d8fa4592bf60b5aa8/tumblr_inline_n8grye1xlm1qzywlj.jpg"&gt;&lt;img align="right" alt="image" src="https://64.media.tumblr.com/88532c82dfc4ad6d8fa4592bf60b5aa8/tumblr_inline_pk0mgqmGpp1qzywlj_540.jpg" title="Copyright Garry Knight cc-by-sa 2.0 https://www.flickr.com/photos/garryknight/6187921147" data-orig-height="180" data-orig-width="240" data-orig-src="https://64.media.tumblr.com/88532c82dfc4ad6d8fa4592bf60b5aa8/tumblr_inline_n8grye1xlm1qzywlj.jpg"/&gt;&lt;/figure&gt; This expression makes sense to me, and I was kinda surprised when I learned that it didn’t exist in English.&lt;!-- more --&gt;&lt;/p&gt;

&lt;p&gt;But then I thought about the origin of the word radio/radius in &amp;quot;radiophonic voice&amp;quot;, and realized it made quite a funny journey.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It used to mean “the spoke of a wheel”; then &lt;/li&gt;
&lt;li&gt;Because the spoke of a wheel goes from the center to the edge of the circle, it also meant what we call radius, which is the abstract geometric idea of a line from a center of a circle to its edge. (Note: I may be wrong the order of these two first meanings.) Then&lt;/li&gt;
&lt;li&gt;&lt;figure data-orig-height="160" data-orig-width="152" data-orig-src="https://64.media.tumblr.com/f6384ac6812f6f97920953be637734e3/tumblr_inline_n8gs1bYCpB1qzywlj.jpg"&gt;&lt;img align="right" alt="image" src="https://64.media.tumblr.com/f6384ac6812f6f97920953be637734e3/tumblr_inline_pk0mgq7sWr1qzywlj_540.jpg" data-orig-height="160" data-orig-width="152" data-orig-src="https://64.media.tumblr.com/f6384ac6812f6f97920953be637734e3/tumblr_inline_n8gs1bYCpB1qzywlj.jpg"/&gt;&lt;/figure&gt;Because electromagnetic radiation comes from a center point outwards in a sphere, it was given the name “radiation”. It’s interesting to note that the international sign for radiation is quite similar to the aforementioned wheel.&lt;/li&gt;
&lt;li&gt;Because of the name “radiation”, the device used for listening to music using electromagnetic radiation was called a radio; and&lt;/li&gt;
&lt;li&gt;“Radiophonic voice” came to mean (in Hebrew) a voice that’s pleasant enough that you’d want to listen to it on the radio.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Quite an interesting journey through the ages from “spoke of a wheel” to “pleasant voice” :)&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/91288023728</link><guid>https://blog.ram.rachum.com/post/91288023728</guid><pubDate>Thu, 10 Jul 2014 00:39:00 +0300</pubDate></item><item><title>Ridiculous</title><description>&lt;h2&gt;Ridiculous&lt;/h2&gt;&lt;p&gt;I needed to buy coconut milk.&lt;/p&gt;
&lt;p&gt;I went into the nature store that’s on the ground floor of the apartment building that I live in. Since it’s in the same building I live in, and I like buying natural foods, I tend to buy a lot in this store; I always say hi to the cashiers who work there, and they usually give me a discount.&lt;/p&gt;
&lt;p&gt;As I was picking the can of coconut milk and getting ready to pay, I took a look at the impressive variety of roasted nuts that’s on display between me and the cashier. Among them were pistachios.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class="tmblr-full" data-orig-height="341" data-orig-width="500" data-orig-src="https://64.media.tumblr.com/9c1817cb228025824d1f30947983a77f/tumblr_inline_n6ytv4jq2s1qzywlj.jpg"&gt;&lt;img alt="image" src="https://64.media.tumblr.com/3c14cbdfef69f7df6d88ff02c275a39a/tumblr_inline_pk0mgrXMi61qzywlj_540.jpg" title="Copyright Maciej Lewandowski CC-by-sa 2.0 https://www.flickr.com/photos/macieklew/176146762" data-orig-height="341" data-orig-width="500" data-orig-src="https://64.media.tumblr.com/9c1817cb228025824d1f30947983a77f/tumblr_inline_n6ytv4jq2s1qzywlj.jpg"/&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;I hankered to buy me some pistachios to eat. I decided to go for it. I love pistachios. Then I remembered that some places sell them peeled, so you don’t have to peel them one-by-one, which is awesome if you’re the kind of person who wants to take a bag of pistachios and just pour them down your mouth.&lt;/p&gt;
&lt;p&gt;I am that kind of person.&lt;/p&gt;
&lt;p&gt;After making some small talk with the goateed dude manning the register, I asked him:&lt;/p&gt;
&lt;p&gt;“Do you have any peeled pistachios?”&lt;/p&gt;
&lt;p&gt;He points to these pistachios:&lt;/p&gt;
&lt;p&gt;&lt;figure class="tmblr-full" data-orig-height="281" data-orig-width="500" data-orig-src="https://64.media.tumblr.com/1bf5fd4a134e39a885be0b555ca5cd26/tumblr_inline_n6ytvr29PU1qzywlj.jpg"&gt;&lt;img alt="image" src="https://64.media.tumblr.com/572cf26ab4ebb04408eee070a952ad39/tumblr_inline_pk0mgrgCh41qzywlj_540.jpg" title="Copyright THOR CC-by 2.0 https://www.flickr.com/photos/geishaboy500/4278800358" data-orig-height="281" data-orig-width="500" data-orig-src="https://64.media.tumblr.com/1bf5fd4a134e39a885be0b555ca5cd26/tumblr_inline_n6ytvr29PU1qzywlj.jpg"/&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;“These are peeled,” he says.&lt;/p&gt;
&lt;p&gt;I look into the dude’s eyes. He looks at mine. I look at the pistachios, which seem pretty damn unpeeled to me.&lt;/p&gt;
&lt;p&gt;At this point, I want to say, “Um, these are not peeled.” But I decide to consult my brain first.&lt;/p&gt;
&lt;p&gt;Hi brain, I say. We’re in a bit of a pickle here. I want to get peeled pistachios, and he says these pistachios are peeled.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Which pistachios?&lt;/em&gt; These ones right here. &lt;em&gt;Um, these are definitely not peeled. The guy’s an idiot.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hold your judgement, brain. I know this guy’s been working here from the time I moved in to the building, which is almost two years ago. Think about it brain: Dude’s been spending hours every day for the last 2 years selling natural food to people, so he probably knows more about the nuts in his display than I know about the nuts in my boxers. Plus he has a very neatly trimmed goatee so there’s that.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Okay, I take your point. So the pistachios are peeled, and yet… They are not peeled.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yes, and I can’t say that they’re not peeled, because they’re obviously peeled, so I’ll look like a raging idiot.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fuck.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is important, brain. We have to figure this one out, and we’ve got only a few seconds before we need to reply to this dude, otherwise it’s gonna be weird. We have to figure it out fast.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Don’t worry, we’ve got this. We’re good. We’re smart.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yes we are. Got anything?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Yes, okay, listen to this. Taking another look at the pistachios here, their peels do seem to be just a bit more open than how pistachios normally are. Do you see that?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yeah, now that you’re mentioning it, they do look pretty easy to open. I think I know where you’re going with this brain!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Yeah, I told you we’re smart :) So anyway, here’s my working theory. People are okay with peeling pistachios, but they don’t like it when the peels are shut really tight, because then you have to use your nails or teeth or something, and sometimes it hurts and that sucks.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yeah, totally.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Okay, so people who sell pistachios, they sell so-called “peeled” pistachios, which are pistachios that have really easy to open peels. I guess they either sort the pistachios into easy-to-peel and difficult-to-peel, and sell just the former under the title of peeled pistachios. Or maybe they use some kind of heat-based process to get the pistachio peels to open up so they’ll be easy to peel. Whatever. So “peeled” pistachios are not really peeled, but just easy to peel.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Makes sense brain! I mean, it’s kinda fucked up, but it’s the best we’ve got.&lt;/p&gt;
&lt;p&gt;“Ah, peeled, you meant peeled. No, sorry, we don’t have any of those,” says the goatee.&lt;/p&gt;
&lt;p&gt;Well fuck me.&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/88393636823</link><guid>https://blog.ram.rachum.com/post/88393636823</guid><pubDate>Tue, 10 Jun 2014 21:33:00 +0300</pubDate></item><item><title>Introducing git cascade and git forward-merge</title><description>&lt;h2&gt;Introducing git cascade and git forward-merge&lt;/h2&gt;&lt;p&gt;Hi ho!&lt;/p&gt;
&lt;p&gt;I just released as open-source two Git scripts that I’ve been using for a while. They were born out of my frustrations with Git over the years. They are awesome and I love them.&lt;/p&gt;
&lt;p&gt;Check them out on GitHub:&lt;/p&gt;
&lt;p&gt;     &lt;a href="https://github.com/cool-RR/git-cascade"&gt;https://github.com/cool-RR/git-cascade&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The project contains two scripts:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;code&gt;git cascade&lt;/code&gt; - Cascade changes from each branch to its dependents.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git forward-merge&lt;/code&gt; - Merge branches without checking them out.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Click the GitHub link above to read all about them and start using them.&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/81379238429</link><guid>https://blog.ram.rachum.com/post/81379238429</guid><pubDate>Tue, 01 Apr 2014 13:29:34 +0300</pubDate></item><item><title>SmartGit: My favorite GUI interface for Git </title><description>&lt;h2&gt;SmartGit: My favorite GUI interface for Git &lt;/h2&gt;&lt;p&gt;I wanted to give a shoutout to one of my favorite tools that I’ve been using for the last few years: &lt;a href="http://www.syntevo.com/smartgithg/"&gt;SmartGit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.syntevo.com/images/smartgit-galery/hg-log.png"&gt;&lt;figure class="tmblr-full" data-orig-height="375" data-orig-width="500" data-orig-src="https://64.media.tumblr.com/160c69ef9bc75973e9d3dd6907d2e1cb/tumblr_inline_n2ozpr5NxQ1qzywlj.png"&gt;&lt;img src="https://64.media.tumblr.com/29060a9e0f400f5298639492b0f88947/tumblr_inline_pk03s7ushg1qzywlj_540.png" data-orig-height="375" data-orig-width="500" data-orig-src="https://64.media.tumblr.com/160c69ef9bc75973e9d3dd6907d2e1cb/tumblr_inline_n2ozpr5NxQ1qzywlj.png"/&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SmartGit is a GUI interface to the Git version control system. (I assume that Git itself needs no introduction, but if you’re not familiar with it: It’s one of the best version control systems used in software development.) Actually, the full name of the software is SmartGit/HG, because it’s also able to handle Mercurial repositories.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;In the last few years that I’ve used SmartGit, I found it to be a highly reliable, efficient and customizable piece of software. I use it to manage my work repositories, the repositories of my personal projects, and the repositories of open-source projects that I occasionally contribute to; all in all around 30 repositories. I do still use the &lt;code&gt;git&lt;/code&gt; command outside of the GUI, for the few custom Git scripts that I have, and of course SmartGit has no problem with that: you can use &lt;code&gt;git&lt;/code&gt; in the shell in parallel to SmartGit with no issue.&lt;/p&gt;
&lt;p&gt;I can say in confidence that using the keyboard shortcuts provided in SmartGit, I’m able to execute Git commands faster than if typing them in the command line. (I hope not to get into a CLI vs. GUI discussion here… &lt;a href="http://blog.ram.rachum.com/post/9875143930/guis-kick-clis-asses"&gt;Here’s my take on the CLI vs. GUI matter.&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I’m not going to go over all the features of the program since you can find &lt;a href="http://www.syntevo.com/smartgithg/"&gt;a good overview&lt;/a&gt; of those on the official website, but I’ll add my own two cents: The makers of SmartGit, a German company called Syntevo, have proven themselves to be a great vendor of software development tools. They keep pushing out new versions consistently with new meaningful features. (The most recent one is support for making GitHub comments within the GUI.) Whenever I send questions to their support email their response is quick and helpful, and when I report bugs they are usually fixed quickly.&lt;/p&gt;
&lt;p&gt;In conclusion: If you’re a regular Git user, and you’re open to using a GUI interface for Git, I’d strongly recommend &lt;a href="http://www.syntevo.com/smartgithg/"&gt;downloading the trial version of SmartGit&lt;/a&gt; and giving it a try.&lt;/p&gt;</description><link>https://blog.ram.rachum.com/post/80076102815</link><guid>https://blog.ram.rachum.com/post/80076102815</guid><pubDate>Wed, 19 Mar 2014 18:43:37 +0200</pubDate><category>planetpython</category><category>git</category></item></channel></rss>