cireu / emacs-cell

Lisp value with extra informations.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Value with extra information

Introduction

This library provides a set of “Cell” for Elisp programming. A “Cell” is a container of single Lisp value, with extra information attached on it.

Currently there are 3 kinds of “Cell” in cell.el

Some

A Some Cell add the “existence” information for a lisp value.

Some Cell can be united with nil value to present a nullable value. When writing funtion to query a collection. You can use nil to present “Not found” and Some(x) to present your found value. When using nil to present “Not fonud” in tranditional Lisp programming style. The caller of your query function may hard to differentiate these two status: “Found and get a nil value” and “Not found”.

(defun clear-plist-get (plist key)
  (pcase (plist-member plist key)
    (`(,_k ,v)
      (cell-some v))
    (_
     nil)))

(let ((plist '(:key nil)))
  (plist-get plist :key)                ;=> nil
  (plist-get plist :val)                ;=> nil

  (clear-plist-get plist :key)          ;=> Some(nil)
  (clear-plist-get plist :val)          ;=> nil
  )

cell.el also provides some facility to operates on a Some(x) | nil union.

(let ((some (cell-some 1))
      (none nil))
  (cell-option-map some #'1+)           ;=> Some(2)
  (cell-option-map none #'1+)           ;=> nil

  (pcase some
    ((cell-some inner)
     (message "Some(%d)" inner))
    (_ (error "Unreachable!"))))

Box

A Box Cell is like a single-element vector, normally used as minimal mutable storage.

(let* ((box (cell-box "Emacs"))
       (lst (list box))
       (vec (vector box)))
  (cl-assert (eq (cell-box-inner (nth 0 lst))
                 (cell-box-inner (aref vec 0))))

  (setf (cell-box-inner (nth 0 lst)) "emacs")
  (cl-assert (eq (cell-box-inner (nth 0 lst))
                 (cell-box-inner (aref vec 0)))))

Weak

A Weak Cell is like weak pointer in other languages. The reference in Weak Cell will not be considered in GC. This can help you manage struct with cyclic reference.

When design a RAII style API in Emacs Lisp, Weak Cell can help you differentiate “first class” reference and “second class” reference. And make sure finalizer can be run as expected.

(let ((weakptr (cell-weak (list 1 2 3 4))))
  (cl-assert (equal (cell-weak-get weakptr)
                    (cell-option-some (list 1 2 3 4))))
  (garbage-collect)
  ;; value inside weakptr was GCed because nothing other than a weak cell
  ;; held its reference. So `cell-weak-get' will return a None.
  (cl-assert (equal (cell-weak-get weakptr)
                    (cell-option-none))))

About

Lisp value with extra informations.


Languages

Language:Emacs Lisp 100.0%