Where parallels cross

Interesting bits of life

Something I missed: point free composition in Elisp!

I enjoy writing code in a functional style. This means that, yes, I am a fan of point-free composition. This means writing functions without defining their arguments.

It is not the most readable approach, but is terse. If you come up with good function names it is pretty good. Also no need to test point-free functions because they are covered by the tests of their components.

Anyway I just realized I can do that in Elisp! I was just improving my function to download YouTube scripts to get the results into a file. My first go:

(defun yt-transcript-to-file (url)
  (--> (get-youtube-transcript url)
       (--map (plist-get it :text) it)
       (s-join "\n" it)
       (write-region it nil "/tmp/yt-transcript.txt"))  

While developing it I thought: "it would be cool to write in point-free style".

First split the functions:

(defun extract-text-from-yt-video (transcript-plist)
  "Make a transcript string out of youtube TRANSCRIPT-PLIST."
  (--> transcript-plist
       (--map (plist-get it :text) it)
       (s-join "\n" it)))

(defun text-to-file (text)
  (write-region text nil "/tmp/yt-transcript.txt"))

Note that each function above does its own independent transformation. Data transformation is the core of functional programming. This is a great setup for function composition.

(-compose 'text-to-file
          'extract-text-from-yt-video
          'me-get-youtube-transcript)

That uses dash.el -compose function.

Then I tried to make a named function of that:

(setq extract-file-out-of-yt-video (-compose 'text-to-file
                                             'extract-text-from-yt-video
                                             'me-get-youtube-transcript))

This fails! Indeed, setq assigns values to variable symbols. These symbols cannot be treated as functions.

Instead you can assign function symbols with fset!

(fset 'extract-file-out-of-yt-video (-compose 'text-to-file
                                              'extract-text-from-yt-video
                                              'me-get-youtube-transcript))

And that makes our point-free function! Note that composition is reversed: the last function is the first to run.

The last thing I need to discover is how to attach some doc-string to that function... Something for another day!

Happy point-free-ing!

Comments