Working Remotely at Ars Technica

Over the next few weeks, Ars Technica will be running a series of articles on the future of work. They’ve started off with a long and detailed article on working remotely at Ars Technica. Actually, working at Ars Technica means working remotely because they have an all digital newsroom. The entire editorial staff works remotely—there is no physical editorial office. Ars Technica is owned by Condé Nast, which does, of course, have offices and which takes care of the business side of things—things like sales, marketing, legal, and HR. That leaves the editorial staff free to concentrate on finding and writing stories. The folks at Ars Technica are used to the arrangement; They’ve been operating that way for 20 years.

The editorial staff at Ars Technica enjoys remarkable autonomy. Each member chooses his own technology and is not forced into using a company standard. Their choices do, of course, have to support the common applications that the staff uses but there aren’t very many of those. They use WordPress as their CMS so writers can use whatever tool they choose to write their copy and then upload it to WordPress.

Oddly, rather than use one of the shiny new communication apps, Ars Technica depends on email for most of its day-to-day communication. That has the advantage of providing a permanent record of “conversations” as well as not ripping a writer out of flow by demanding their immediate attention. They use Gmail because it works with all of the systems that the staff uses.

They also use Slack and spreadsheets to keep track of who’s doing what and stories in progress. The article has a long section on their workflow, which I found very interesting. There’s a lot more in the article so be sure to take a look if you’re interested in remote work.

The Ars Technica example is particularly interesting to me because they’re an edge case: they’re not an “also-remote workplace” or a “remote-first workplace”, they’re a “remote-only workplace.” My take is that all-in-all that makes things easier. There’s no “office people are more tuned in” problems or the other difficulties of that sort. It’s really matter of having some agreed upon technology for communication and some simple procedures to make everyone work for the common goal.

Posted in General | Tagged | Leave a comment

Zamansky 66: An Eshell Switcher

Mike Zamansky has another video up in his Using Emacs Series. The video is about his trying to use eshell more and building an eshell switcher so that he can easily switch among his active eshell instances. I really like this video because it offers another example of the joys and strengths of what I call “interactive programming.” By interactive programming, I mean the ability to try out small snippets of code, see what they return, and combine these into ever bigger pieces until you have the desired functionality.

Zamansky starts off by mentioning the exec-path-from-shell package, Steve Purcell’s excellent package to make Emacs aware of your PATH and other environment variables. If you’re running on MacOS, this package is pretty much mandatory if you don’t want Emacs to drive you crazy with “Not Found” messages. Zamansky’s use is the first time I’ve seen it used on a Linux system so it has wider applicability than I thought.

The rest of the video shows Zamansky building his switcher app. It’s a wonderful demonstration of how nice Elisp development can be. Even if your Elisp is rusty—as Zamansky says his is—you can experiment by trying various functions until you find one that returns what you need. He literally builds the function brick by brick by continually adding small snippets of code until he has a working function.

I’ve used eshell for a long time but I’ve never felt the need for multiple instances. Perhaps this video will inspire me to expand my horizons. The video is 23 minutes, 43 seconds long so you’ll probably need to schedule some time but if you’re interested in eshell or in Elisp programming, you should definitely find the time to watch it.

Posted in General | Tagged , | Leave a comment

Finding Intersections Redux

Last month, I published a post on Finding The Intersection of Two Lists. The impetus for the post was an Emacs Stack Exchange question asking if there was a better way to find the intersection of two lists than looping over both of them. I thought putting the entries of the first list in a hash table and checking the entries of the second list against it was a better solution and I wrote some code to check out that hypothesis. You can see the details in the original post.

I got some gentle pushback from two Elisp luminaries, Chris Wellons and Alphapapa. Wellons noted that I could get a small speed increase by using dolist instead of mapc. More importantly, he noted that I should have compiled my code with lexical mode as that makes a large difference in running time.

Alphapapa, commenting as NoonianAtall, noted that I wasn’t eliminating duplicates and pointed me at some macros that make benchmarking this type of thing easier. He published a gist that showed one of those macros in action.

Naturally, I had to check all this out. I wrote a new version of hash-intersection that used dolist instead of mapc and also made a small change (hash-intersection-dedup) to the algorithm so that duplicates were eliminated. Finally, I stole Alphapapa’s version of the code that uses the loop macro instead dolist.

Here’s all the code, including the bit to generate random lists, for reference:

(require 'epdh)
(require 'dash-functional)
(defun make-random-list (n)
  (let ((l nil))
    (dotimes (i n l)
      (push (random 1500) l))))

(defconst lst1 (make-random-list 1000))
(defconst lst2 (make-random-list 1000))

(defun hash-intersection-orig (l1 l2)
  (let ((ht (make-hash-table :test #'equal))
        (acc nil))
    (mapc (lambda (x) (puthash x t ht)) l1)
    (mapc (lambda (x) (if (gethash x ht nil)
                          (push x acc)))
          l2)
    acc))

(defun hash-intersection-dolist (l1 l2)
  (let ((ht (make-hash-table :test #'equal))
        (acc nil))
    (dolist (l l1)
      (puthash l t ht))
    (dolist (l l2)
      (if (gethash l ht nil)
          (push l acc)))
    acc))

(defun hash-intersection-dedup (l1 l2)
  (let ((ht (make-hash-table :test #'equal))
        (acc nil))
    (dolist (l l1)
      (puthash l t ht))
    (dolist (l l2)
      (when (gethash l ht nil)
        (puthash l nil ht)              ;only one to a customer
        (push l acc)))
    acc))

;; From Alphapapa
(defun hash-intersection-loop (l1 l2)
  (let ((ht (make-hash-table :test #'equal) ))
    (cl-loop for e1 in l1
             do (puthash e1 t ht))
    (cl-loop for e2 in l2
             when (gethash e2 ht)
             collect it)))

Now we’re ready to test Wellons’ claims. First, I used the bench-dynamic-vs-lexical-binding macro to measure the difference that compiling with lexical bindings made:

(bench-dynamic-vs-lexical-binding
  :times 100
  :forms (("hash-intersection-orig"   (progn
                                        (defun hash-intersection-orig (l1 l2)
                                          (let ((ht (make-hash-table :test #'equal))
                                                (acc nil))
                                            (mapc (lambda (x) (puthash x t ht)) l1)
                                            (mapc (lambda (x) (if (gethash x ht nil)
                                                                  (push x acc)))
                                                  l2)
                                            acc))
                                        (hash-intersection-orig lst1 lst2)))))
Form x faster than next Total runtime # of GCs Total GC runtime
Lexical: hash-intersection-orig 1.25 0.027208 0 0
Dynamic: hash-intersection-orig slowest 0.033979 0 0

Just as Wellons promised, the lexical version is 25% faster. Next, I compared all the implementations (as well as seq-difference) compiled with lexical bindings. There were a couple of surprises. First, the deduping version ran slightly faster than the dolist version. That was a pretty consistent result across several runs of the comparison. The only reason for it that I can see is that eliminates the push for all the duplicates.

A bit more surprising is that the dolist version ran 28% faster than the mapc version. That seems pretty high but the numbers did jump around a bit between different runs so perhaps it’s just an anomaly. If you want to play around with Alphapapa’s macros (they’re here) that would be a good experiment to run. There are more macros than I’ve mentioned here so they should meet whatever your benchmarking needs are.

(bench-multi-lexical
  :times 100
  :forms (("hash-intersection-orig"   (progn
                                        (defun hash-intersection-orig (l1 l2)
                                          (let ((ht (make-hash-table :test #'equal))
                                                (acc nil))
                                            (mapc (lambda (x) (puthash x t ht)) l1)
                                            (mapc (lambda (x) (if (gethash x ht nil)
                                                                  (push x acc)))
                                                  l2)
                                            acc))
                                        (hash-intersection-orig lst1 lst2)))
          ("hash-intersection-dolist"   (progn
                                          (defun hash-intersection-dolist (l1 l2)
                                            (let ((ht (make-hash-table :test #'equal))
                                                  (acc nil))
                                              (dolist (l l1)
                                                (puthash l t ht))
                                              (dolist (l l2)
                                                (if (gethash l ht nil)
                                                    (push l acc)))
                                              acc))
                                          (hash-intersection-dolist lst1 lst2)))
          ("seq-intersection" (seq-intersection lst1 lst2))
          ("hash-intersection-loop"   (progn
                                        (defun hash-intersection-loop (l1 l2)
                                          (let ((ht (make-hash-table :test #'equal) ))
                                            (cl-loop for e1 in l1
                                                     do (puthash e1 t ht))
                                            (cl-loop for e2 in l2
                                                     when (gethash e2 ht)
                                                     collect it)))
                                        (hash-intersection-loop lst1 lst2)))
          ("hash-intersection-dedup"   (progn
                                         (defun hash-intersection-dedup (l1 l2)
                                           (let ((ht (make-hash-table :test #'equal))
                                                 (acc nil))
                                             (dolist (l l1)
                                               (puthash l t ht))
                                             (dolist (l l2)
                                               (when (gethash l ht nil)
                                                 (puthash l nil ht) ;only one to a customer
                                                 (push l acc)))
                                             acc))
                                         (hash-intersection-dedup lst1 lst2)))))
Form x faster than next Total runtime # of GCs Total GC runtime
hash-intersection-dedup 1.02 0.021943 0 0
hash-intersection-loop 1.09 0.022341 0 0
hash-intersection-dolist 1.28 0.024367 0 0
hash-intersection-orig 315.94 0.031197 0 0
seq-intersection slowest 9.856230 0 0

Finally, I should mention that the macros are part of Alphapapa’s Emacs Package Developer’s Handbook, which has a wealth of useful information—even if you aren’t writing packages—and is definitely worth taking a look at if you haven’t already.

Update [2020-02-08 Sat 11:22]: NoonianAtall (Alphapapa) says that I should have included cl-intersection and -intersection in my comparisons. Fortunately, he’s already done that in the gist that I mentioned so you can check them out there. Cl-intersection is, of course, included with Emacs and -intersection is from Dash which you probably also have since it’s a dependency of many popular packages.

Posted in General | Tagged , | Leave a comment

Restoring the Elfeed Default Filter

I’m a very happy user of Chris Wellons’ excellent RSS reader, elfeed. It has a very powerful search/filter function that lets you control what entries will be displayed and to search for an older entry that you want to revisit. Elfeed has a useful default filter that displays unread items younger than six months old. You can configure the default filter, of course, but the built-in one works well for me so I use it.

The problem is that I can never remember the syntax for the default filter so when I do a search, I always have to look up the incantation to restore the filter to “unread items from the last six months.” A consequence of that is that I didn’t use the search function as often as I otherwise would have. I’ve just discovered that I’ve been doing things the hard way. It turns out that if you clear the current filter, the default is restored. I don’t know if this is a recent addition or if it’s always been that way and I just missed it when I was learning to use Elfeed.

In either case, you can call elfeed-search-clear-filter or use the shortcut c to clear the current filter and restore the default. It’s embarrassing to admit that I was ignorant of a feature that makes the Elfeed experience so much better for this long. If you’re an Elfeed user and didn’t know this, you’re welcome.

Posted in General | Tagged | Leave a comment

Thought of the Day

From Karl Voit, we have this bit of wisdom:

You can take this in two ways:

  1. Development of Emacs in ongoing and robust.
  2. Emacs is infinitely extensible so even in the absence of point 1, you can make it adapt to new situations.

Regardless, until there is a huge paradigm shift in computing, I expect Emacs will continue to be a relevant and useful tool.

Pouya Abbassi also has some appropriate words along the same lines:

Posted in General | Tagged | Leave a comment

Palindromes With a Sufficiently Smart Compiler

Those of you who enjoyed my post on palindrome predicates may also like Joe Marshall’s follow-up to his original post that inspired mine. In it, he considers the two implementations—recursive and iterative—and what it would take for a sufficiently smart compiler to generate code for the recursive algorithm that’s as efficient as that for the interative algorithm.

He does that by imagining a series of steps that such a compiler might take to transform the recursive solution into the iterative one. The lowest hanging fruit is, of course, to get rid of the string copying that the substring function does in most implementations of Scheme (and all conforming implementations of Common Lisp). The Guile Scheme implementation almost does this—see the discussion by Chris Wellons in my original post. That single optimization produces a dramatic improvement in performance. When I ran the same test with Chez Scheme, which does not implement copy-on-modify semantics for stringcopy the execution went from a little over 9 seconds to over an hour and a half.

Marshall doesn’t stop there. He continues with a set of more or less reasonable steps that a smart compiler might make until the two implementations are the same. (One of those steps is unlikely to be made by a compiler, regardless of how smart it is, but is nevertheless possible.) Marshall doesn’t mean for his post to be taken as a serious suggestion: it’s more of a thought experiment. It’s an interesting exercise in understanding how some simple steps can make code significantly better.

Posted in General | Leave a comment

Zamansky 65: Live Python

Mike Zamansky has another video up in his Using Emacs Series. This time the video is about the live-py-plugin. The link takes you to the master GitHub repository that has code for Emacs, PyCharm, and Sublime Text. There’s a tutorial by the author for using it with Emacs here.

The idea is that as you type Python statements, the results are shown in another window. What gets shown can be quite complex. For instance, the code

for i in range(5):
    print(i+1)

will show the result for each value of i. That’s not too surprising but

def factorial (n):
    if (n==1):
        return 1
    else:
        return n*factorial(n-1)

factorial(5)    

will show you the results of factorial(5), factorial(4),⋯, factorial(1) so it’s a nice way of seeing what your code is doing. Zamansky shows the factorial example and a slightly more complex case of the first example so you can see the live-py results in action. It’s a nice package and worth taking a look at if you’re a Python programmer.

The video is comparatively short—about 8 and a half minutes—so you should be able to fit it in easily.

Posted in General | Tagged | Leave a comment

Today is a Palindrome

Today’s date, 02022020, is a palindrome. Palindromic dates happen all the time but today is special. So special that it’s unique. First of all, today is a palindromic date everywhere. Because of the silly date format that either the U.S. or Europeans use (take your choice), it’s almost always the case that a date that’s palindromic in the U.S. is not palindromic in Europe and vice versa. Dates that work for both are very rare, and today is one of them. The last time it happened was 909 years ago.

But as Steve Jobs used to say, “One more thing.” Today is also a palindromic split in that it’s the 33 day of the year and there are 333 days left. A day that is both a universal palindromic date and a palindromic split is unique: there’s only one and today is it.

Here’s a video by Matt Parker, the Stand-up Mathematician, that explains all this in more detail:

Posted in General | Tagged | Leave a comment

Keeping a Table Header Fixed While Scrolling

Bastien Guerry tweeted about a really awesome new Org-mode feature:

A little further down in the thread, Guerry notes that, “As of this morning, it’s now called M-x org-table-header-line-mode RET” so if you’re living on the edge, use that name instead.

He doesn’t say when it will be officially released but since it’s in Master the next release will probably have it. This isn’t, of course, a huge deal but it does eliminate one annoying aspect of working with tables. Now you can lock the header in place and be able see what each column means. Very nice.

Posted in General | Tagged , | Leave a comment

Spacemacs for Writers

Frank Jonen has an interesting GitHub repository to help non-technical people use Spacemacs for writing. Jonen says that his interest in using Emacs for writing and the resulting repository were inspired by Jax Dixit’s talk for the New York Emacs Meetup on Emacs for writers.

As you all know, I’m always interested in the way non-technical people use Emacs so of course I had to check it out. The previous examples of Emacs-for-writers that I’ve written about all involved using vanilla Emacs so this instance is noteworthy for advocating Spacemacs.

The repository consists mainly of Jonen’s .spacemacs configuration file and a README that’s part inspiration and part installation guide. The installation segment covers installing Emacs, Spacemacs, and Jonen’s configuration.

I don’t know if Spacemacs is a good choice for a new user—not a Vim immigrant, where it’s obviously a good choice—but, say, a Word immigrant. Irreal is fortunate in having some passionate Spacemacs users as readers so perhaps one of them can weigh in on whether Spacemacs is the optimal choice for a new, non-technical user. Regardless, it’s a choice that’s working for Jonen and may work for other writers looking to escape the yoke of Word and its evil siblings. If you’re a writer who would like to experience the joy of text-based editing that doesn’t insist you do things its way, take a look at Jonen’s README. Perhaps you’ll be inspired.

Posted in General | Tagged | Leave a comment