Vacuous Truth Development Site

Org Babel

Code Blocks

At the heart of Babel are Org code blocks. Code blocks are delimited with a special comment syntax. Here is an example code block in Elisp:

#+BEGIN_SRC elisp
  (defun mccarthy91 (n)
     "McCarthy 91 is used as a formal verification test case."
     (if (<= n 100)
         (mccarthy91 (mccarthy91 (+ n 11)))
       (- n 10)))
#+END_SRC

The basic form is simple. A chunk of code is surrounded by #+BEGIN_SRC lang#+END_SRC.

Code blocks can be modified with annotations, switches, and header arguments. The expanded structure follows

#+NAME: <name>
#+BEGIN_SRC <language> <switches> <header arguments>
 <body>
#+END_SRC

Especially useful are header arguments such as :session, :results, and :exports. Header arguments can be placed on the #+BEGIN_SRC line as follows

#+BEGIN_SRC elisp :exports code
 <body>
#+END_SRC

Or they can be placed as code block annotations as follows

#+HEADER: :exports code
#+BEGIN_SRC elisp
 <body>
#+END_SRC

Multiple header blocks can be used in either form.

#+BEGIN_SRC elisp :exports code :results replace table
 <body>
#+END_SRC

#+HEADER: :exports code
#+HEADER: :results replace table
#+BEGIN_SRC elisp
 <body>
#+END_SRC

The :exports header argument is incredibly useful. It controls how the code block is used when exporting. It can simply list its code in the exported document by using :exports code. Or it can evaluate the code and export just the results using :exports results. To include both the code and the results in the exported document use :exports both. Finally the code and the results can be excluded from the exported document using :exports none.

Code Block Variables in Elisp

Simple example shows setting a variable in a header comment.

#+NAME: square_el
#+HEADER: :var x=0
#+BEGIN_SRC elisp
  (* x x)
#+END_SRC

Now we can use #+CALL: to invoke the named code block.

#+CALL: square_el(x=6)

36

Code Block Variables in Python

Now a simple example in Python.

#+NAME: square_py
#+HEADER: :var x=0
#+BEGIN_SRC python
  return x * x
#+END_SRC

Likewise we can use #+CALL: to invoke the named Python code block.

#+CALL: square_py(x=5)

25

Inline Code Block

Code can be evaluated inline using src_lang{code}. Thus to get the current Emacs version use src_elisp{(format "%s" emacs-major-version)}. This document was prepared with Emacs 26.

Inline Code Block with Arguments

Inline code with arguments has the form src_lang[args]{code}. Thus we can assign a variable inline like so src_elisp[:var x=25]{(sqrt x)} can be used to show that \( \sqrt{25} = \) 5.0.

Named Inline Calls

Named code blocks can be called in a similar fashion and syntax used for inline code blocks. The form is call_name() or the expanded form call_name[inside-header-args](args)[end-header-args].

#+NAME: mcpython91
#+BEGIN_SRC python :var in_from_org=0 :exports none
 def mccarthy91(n):
     "McCarthy 91 is used as a formal verification test case."
     if n <= 100:
         return mccarthy91(mccarthy91(n + 11))
     else:
         return n - 10

 return mccarthy91(in_from_org)
#+END_SRC

The McCarthy 91 function with the argument 4 evaluates to 91 and with the argument 246 evaluates to 236.

Likewise the following are true

  • call_mcpython91(0) = 91

  • call_mcpython91(1) = 91

  • call_mcpython91(85) = 91

  • call_mcpython91(101) = 91

  • call_mcpython91(102) = 92

  • call_mcpython91(185) = 175

The McCarthy 91 function has the property \( \forall n \in \mathbb{N} \), if \( n \leq 100 \) then \( f(n) = 91 \) else \( f(n) = n - 10 \).

Use a Org table as Input

Take from Org Babel: Introduction.

Given this table of numbers

1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20

It is expressed in an Org file like so

#+TBLNAME: fibonacci-inputs
| 1 | 2 | 3 | 4 |  5 |  6 |  7 |  8 |  9 | 10 |
| 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 |

We can use the table named fibonacci-inputs as inputs to a Fibonacci function called while we "map" the rows' values to \( f(n) \).

  (defun fibonacci (n)
    (if (< n 2) n
      (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))

  (mapcar (lambda (row)
            (mapcar #'fibonacci row)) fib-inputs)

In an Org file that looks like so

#+NAME: fibonacci-seq
#+HEADER: :exports both
#+BEGIN_SRC elisp :var fib-inputs=fibonacci-inputs
 (defun fibonacci (n)
   (if (< n 2) n
     (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))

 (mapcar (lambda (row)
           (mapcar #'fibonacci row)) fib-inputs)
#+END_SRC

And produces the following table of Fibonacci numbers

1 1 2 3 5 8 13 21 34 55
1 3 8 21 55 144 377 987 2584 6765

Preview Variable or Tangle Expansion/Substitution

Use C-c C-v v or C-c C-v C-v to preview the expanded content with org-babel-expand-src-block.

Pascals Triangle in Python

Taken from a journal paper on reproducible research.

  def pascals_triangle(n):
      if n == 0:
          return [[1]]
      prev_triangle = pascals_triangle(n-1)
      prev_row = prev_triangle[n-1]
      this_row = map(sum, zip([0] + prev_row, prev_row + [0]))
      return prev_triangle + [this_row]

  return pascals_triangle(n)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

Grammar Checking in Emacs

⚠️ This post was actually written in 2013 and is out of date.

Grammar checking is apparently an error prone task. Or at least it has been claimed: http://faculty.washington.edu/sandeep/check

Looks like there is GNU diction, but it just highlights potentially misused words. It doesn't indicate where an error occurred. I'm not comfortable investing much time into getting this working with Emacs. Since there doesn't appear to be much return for the effort.

I came across Baoqiu Cui's EmacsWiki user page. Baoqui has created a grammar checker for Emacs and links to his package from his page. There aren't many details, but the screenshots on his user page appear promising. The package can be found here https://code.google.com/archive/p/bcui-emacs/source/default/source

This will be my attempt at getting it working with Emacs.

According to Baoqiu's README file the package uses the Link Grammar Parser. The first step looks like I should install the Link Grammar Parser. The parser is available from MacPorts.

$ sudo port install link-grammar

As can bee seen in the grammar.cc in Baoqui's package we need the link-includes.h file to be on our system. Let's verify that the MacPorts package included that file.

$ port contents link-grammar | grep "link-includes"
/opt/local/include/link-grammar/link-includes.h

So, yup this is included. The next thing we need to do is download Baoqui's package. We'll have to checkout the source code from its repo hosted on the now defunct Google Code. I like to keep third-party source code in my ~/src directory.

$ cd ~/src
$ svn checkout http://bcui-emacs.googlecode.com/svn/trunk/grammar grammar.svn
A    grammar.svn/grammar.el
A    grammar.svn/grammar.cc
A    grammar.svn/README
A    grammar.svn/Makefile
U    grammar.svn
Checked out revision 51.

We need to fix up the Makefile so that gcc knows where to find the include file we installed with MacPorts. This is as simple as changing one line in the Makefile.

INCDIRS = -I. -I/opt/local/include/link-grammar

Next we'll attempt to run make. Hopefully this will compile without incident.

$ make
g++ -g -I. -I/opt/local/include/link-grammar -c grammar.cc
In file included from grammar.cc:28:
/opt/local/include/link-grammar/link-includes.h:16:40: error:
link-grammar/link-features.h: No such file or directory
...
grammar.cc:30: error: expected constructor, destructor, or type conversion before ‘int’
make: *** [grammar.o] Error 1

Looks like we got a few screen fulls of errors. Let's investigate the first. gcc says it can't find the file link-features.h. The first thing I want to do is check that it was included when we installed the Link Grammar Parser with MacPorts.

$ port contents link-grammar | grep "link-features"
  /opt/local/include/link-grammar/link-features.h

Okay, the file exist in the MacPorts package. This means something else is wrong. I suspect that the path we changed in the include file is wrong for the way link-includes.h is expecting our includes to be setup. My guess is that link-includes.h references the missing file using its parent directory and then the include file, so it would look like #include “link-grammar/link-features.h". This is a common pattern in C. We can easily check this using sed.

$ sed -n 16,16p /opt/local/include/link-grammar/link-includes.h
#include <link-grammar/link-features.h>

So, my theory was correct. Well have to fix the Makefile and fix the grammar.cc file.

Makefile

INCDIRS = -I. -I/opt/local/include

grammar.cc

#include "link-grammar/link-includes.h"

Now we're ready to try running make again. This run should compile correctly.

$ make
g++ -g -I. -I/opt/local/include -c grammar.cc
g++ -g -llink-grammar -o grammar grammar.o
ld: library not found for -llink-grammar
collect2: ld returned 1 exit status
make: *** [all] Error 1

This one is easy, it's just a linker error. Since we're using MacPorts we need to tell the linker where to find Link Grammar Parser's library file. Since we installed the library with MacPorts we know the library will be in /opt/local/lib. We just need fix the Makefile.

First change: add a LDFLAGS variable to the Makefile right after the INCDIRS variables.

LDFLAGS=-L/opt/local/lib

Next change the all rule to use the new LDFLAGS variable.

all: $(objects)
    g++ -g $(LDFLAGS) -llink-grammar -o grammar $(objects)

Now this thing should finally compile.

$ make
g++ -g -L/opt/local/lib -llink-grammar -o grammar grammar.o

Awesome! It worked. Now we can move on to getting this working in Emacs.

Copy the files into your ~/.emacs.d/site-lisp directory.

 $ mkdir -p ~/.emacs.d/site-lisp/grammar
 $ cp grammar ~/.emacs.d/site-lisp/grammar
 $ cp grammar.el ~/.emacs.d/site-lisp/grammar

Then add the following to your ~/.emacs file.

;; Grammar Checker
(add-to-list 'load-path "~/.emacs.d/site-lisp/grammar")
(add-to-list 'exec-path "/Users/eddie/.emacs.d/site-lisp/grammar")
(autoload 'grammar-mode "grammar" nil t)

Now we can try out grammar-mode. Switch to a buffer for typing (*scratch* is as good as any). Turn on grammar-mode by typing M-x grammar-mode. Now try typing one of the examples from Baoqiu's user page. You'll have to type two spaces or a newline after you type the period to get grammar-mode to check the sentence. I did example 2.

The books is good for beginning reader.

You'll see the words “The”, “books”, “for”, and “reader” underlined with green. This means there are some grammar errors. You can, obviously, fix the errors by changing the sentence to the following. Remember you need to type two spaces or a newline after you type the period.

The books are good for beginning readers.

You can also use the mode's shortcut to run a check on the sentence before or at the current point. The shortcut is C-M-g.

Caveats: there isn't an interactive mode like ispell. So you have to check the grammar as you type it or one sentence at a time. You can't just type your document and as a final step check your grammar. The other big issue I have is that there is no description of the error. The last issue I have, which is least important, is that there are no suggestions for correcting the errors.

Locate an Unknown non-ASCII Multi-byte Character in a File

Problem

Some program or API is failing because of a rouge multi-byte character in a file. So how do you locate the unknown character without examining every character in the file?

Answer (annoying, but correct)

Every search points to -P with grep, but that's GNU grep not BSD grep that macOS ships with. Get over it and install goddamn GNU grep. 1

$ brew install grep

When brew is done it will inform you that any command (binary) installed will have the prefix “g” for GNU.

All commands have been installed with the prefix "g".

Thus to use GNU grep on macOS type ggrep. To find all occurrences of multi-byte character in badfile.txt input the following

$ ggrep --color='auto' -P -n '[^\x00-\x7F]' badfile.txt

  1. There definitely has to be a better way (something with non-GNU stuff). ↩︎