Functional Programming

close up photo of person typing on laptop
Photo by Christina Morillo on Pexels.com

Late last year I set myself some goals to tackle in 2023. These goals fell into three areas in which I am seeking improvement: (1) consolidation, (2) simplification, and (3) automation. In setting those goals, I wrote the following:

I believe I can get away with two primary work product formats: plain text files used in conjunction with Obsidian; and Wolfram Language notebooks (.nb files) used in conjunction with Wolfram Language and Mathematica.

Halfway through 2023, I think I have been largely successful. My daily notes and all things related to events in my life (and that of my family) are recorded in Obsidian. Meanwhile, working notes, coding, writing, and automation has happened primarily in Wolfram notebooks, and using the Wolfram Language as my primary framework.

I’ve been a hobbyist user of Mathematica and Wolfram Language since 2009. I like its all-encompassing scope, its ability notional that nearly everything is computable, and its coding framework . A great thing about the Wolfram Language is that it can be used for complex mathematical experiments, or simply to copy files from folder A to folder B. It is a language that can be used for any task and that is how I have been using it. In the six months since setting my goals, for instance, I’ve done the following using Wolfram Language notebooks and scripts:

  • Created a script that adds work products for a given day to my Daily Notes file in Obsidian. Work products are defined as any file that I created or edited that day: notes, scripts, spreadsheets, etc. The script runs automatically each night and in the morning, I can see the files that I worked on the previous day.
An example of my Daily Notes file with the “Today’s work products” section generated automatically by my script
  • Created a script that selects a random article from the magazines I read and emails me the article the evening. I read a feature article each day and this script eliminated some decision fatigue while simultaneously adding a little spontaneity and surprise to the day — I never know what will get selected.
  • Create a script that exports my current reading list to an Obsidian vault, complete with charts and stats. This vault is published to the web using Obsidian Publish. For decades this was a manual task for me and now it is fully automated. All I have to do is keep my spreadsheet up-to-date.

I learned to write code in the early 1980s by trial and error. And from that first foray with BASIC through this year, I’ve been a procedural programming — a method by which a set of procedures are called in step-by-step fashion. Those procedures might be functions, events or anything that can be called at any point during the program’s execution. Wolfram Language can do procedural programming, but its real power comes from its ability to do functional programming. After a lifetime of procedural programming, I have begun to teach myself functional programming.

Over the weekend, I began exploring the use of stylesheets in Wolfram Notebooks. I created a simple stylesheet for writing, with styles and elements that I use frequently. There is a folder location with the Mathematica framework for these custom stylesheets to be stored. I had several choices:

  1. I could simply save my custom stylesheet to the folder in question.
  2. I could store the stylesheet in one place and copy it to the folder in question whenever I made a change.
  3. I could automate the process.

One of the things I’ve learned as a professional software developer is that it is worth spending the time to do things the right way the first time. I opted, therefore, for option 3.

In my Documents folder, I have a folder called Settings, where I keep my preferences for all of the software I use. This includes things like settings files, templates, stylesheets, preferred fonts, etc. This is the source for my personal preferences and when I get a new machine, it makes it easy to apply all my settings to that machine.

My settings folder

I placed my newly created Writing.nb notebook in the Mathematica folder in my Settings folder. Whenever I updated my stylesheet, this is the file I’d update. But for the file to appear in Mathematica, it needs to live in a special folder in my library. For that, I write a Wolfram Language script. The script does the following:

  • makes a list of all files in my StyleSheets folder (a sub-folder of my Mathematica folder)
  • for each of the files in the list:
    • checks to see if the file exists in the Mathematical library
    • if it exists, it checks to see if my master copy has been update more recently than the version in the library folder; if it has, it copies the updated version to the library folder

I wrote the code as I have written most of my Wolfram Language code, procedurally. It looks as follows:

Do[
 If[FileExistsQ[
   FileNameJoin[{customStyleSheetDestPath, customStyleSheets[[i]]}]],
  If[FileDate[customStyleSheets[[i]], "Modification"] > 
    FileDate[
     FileNameJoin[{customStyleSheetDestPath, customStyleSheets[[i]]}, 
      "Modification"]],
   CopyFile[customStyleSheets[[i]], 
    FileNameJoin[{customStyleSheetDestPath, 
      FileBaseName[customStyleSheets[[i]]] <> "." <> 
       FileExtension[customStyleSheets[[i]]]}], OverwriteTarget -> True
    ]
   ],
  CopyFile[customStyleSheets[[i]], 
   FileNameJoin[{customStyleSheetDestPath, 
     FileBaseName[customStyleSheets[[i]]] <> "." <> 
      FileExtension[customStyleSheets[[i]]]}],
   OverwriteTarget -> True
   ]
  ],
 {i, Length[customStyleSheets]}
 ]

Having written and tested the code, I decided that this was a simple enough task for me to try to rewrite the code as a functional program instead of a procedural one. To my surprise, I’d was able to do it fairly quickly. I was further surprised that it worked on the first try. Here is the same program, written as a functional program:

If[FileExistsQ[FileNameJoin[{customStyleSheetDestPath, #}]],
    If[FileDate[#, "Modification"] > 
      FileDate[FileNameJoin[{customStyleSheetDestPath, #}], 
       "Modification"],
     CopyFile[#, 
      FileNameJoin[{customStyleSheetDestPath, 
        FileBaseName[#] <> "." <> FileExtension[#]}], 
      OverwriteTarget -> True]],
    CopyFile[#, 
     FileNameJoin[{customStyleSheetDestPath, 
       FileBaseName[#] <> "." <> FileExtension[#]}], 
     OverwriteTarget -> True]
    ] & /@ customStyleSheets;

It looks much shorter, and is probably a bit more difficult to read if you are not used to working with functional programs. Essentially, this version of the program defines the entire procedure as an anonymous (i.e. Lambda) function and then maps that function over the list of style sheet files.

While this likely seems obscure and insignificant to most people, it was an important milestone for me. I did this early Saturday morning, and I was excited about the results all weekend. Indeed, I was excited enough by the results to want to tell people about it in a post. This was a milestone for me. Something about functional programmed had clicked in my head and, it seemed, I suddenly got it.

This isn’t the first time something like this has happened to me. I remember in late 1994 or early 1995 when I was teaching myself Perl, I looked at regular expressions as utter gibberish, something I would never understand. A year later, I recall, to my amazement, that I could in almost-realtime craft regular expressions for a pattern in my head. Like functional programming, it just clicked one day.

There is a lesson here. I set about my Saturday morning with a practical task in mind: creating a stylesheet for writing in Wolfram Notebooks. I came away with that stylesheet, but much more important, I had new confidence in my ability, and now I am eager to try flex my functional programming muscles even further.

Written on June 26, 2023.

Did you enjoy this post?
If so, consider subscribing to the blog using the form below or clicking on the button below to follow the blog. And consider telling a friend about it. Already a reader or subscriber to the blog? Thanks for reading!

Follow Jamie Todd Rubin on WordPress.com

One comment

  1. This is excellent. I too used Mathematica to teach myself functional programming a few years ago. I changed jobs however and lost my license for Mathematica. I know the wolfram landscape has shifted since I was a user and I’m very curious what you setup is. Seems you use it local and not through WolframAlpha. Do you mind sharing your setup in a future post? Thank you and thanks for this post. Appreciate it.

Comments

This site uses Akismet to reduce spam. Learn how your comment data is processed.