[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Sweeter Emacs Lisp

From: fgallina
Subject: Sweeter Emacs Lisp
Date: Sat, 13 Jul 2013 23:22:31 -0300
User-agent: mu4e; emacs 24.3.1

Hello all,

The last months I've been playing with Clojure[0] a lot, within its
primitives I found the following functionality exquisite and I think it
may be time for Emacs Lisp to evolve and provide similar stuff making
easier/more-fun to write code in it. Here's a detailed list with
examples of what I would want to see as part of core Emacs Lisp:

  + The *threading* macros "->" and "->>":

  ;; clojure.core/->
  ;; ([x] [x form] [x form & more])
  ;; Macro
  ;;  Threads the expr through the forms. Inserts x as the
  ;;  second item in the first form, making a list of it if it is not a
  ;;  list already. If there are more forms, inserts the first form as the
  ;;  second item in second form, etc.

  (setq tag (cons "<p>" "</p>"))

  (defun tag-desc (tag)
    (concat (upcase (car tag)) "."))

  (defun tag-desc-stripped (tag)
    (upcase (replace-regexp-in-string "[<\\/> ]" "" (car tag))))

  ;; with threading macros
  (defun tag-desc (tag)
    (-> (car tag) (upcase) (concat ".")))

  (defun tag-desc-strip (tag)
    (->> (car tag) (replace-regexp-in-string "[<\\/> ]" "") (upcase)))

  + when-let, if-let:

  ;; clojure.core/when-let
  ;; ([bindings & body])
  ;; Macro
  ;;  bindings => binding-form test
  ;;  When test is true, evaluates body with binding-form bound to the value of 
  ;; clojure.core/if-let
  ;; ([bindings then] [bindings then else & oldform])
  ;; Macro
  ;;  bindings => binding-form test
  ;;  If test is true, evaluates then with binding-form bound to the value of
  ;;  test, if not, yields else

    (let ((pos (re-search-backward "regex" nil t)))
      (when pos
        (list pos (match-string-no-properties 0))))

    (when-let ((pos (re-search-backward "regex" nil t)))
       (list pos (match-string-no-properties 0)))

  + *we need a built-in core mapcan (could be called mapcat), filter and
  sequence concatenation (could be called cat?) function that doesn't
  depends on cl-lib*. This is fundamental stuff isn't it? Why is such a
  need to require a library for it?

  + Destructuring in defun and let: This looks weirder than I thought
  because of our (ab)use of parens everywhere, but I feel this is
  something brillant to have as part of the core language.

  ;; http://clojure.org/special_forms#binding-forms

  (setq tag (cons "<p>" "</p>"))

  (defun fmt-tag (tag)
    (let ((open (car tag))
          (close (cdr tag)))
      (format open close)))

  ;; defun destructuring
  (defun fmt-tag ((open close))
    (format open close))

  ;; let destructuring
  (defun fmt-tag (tag)
    (let (((open close) tag))
      (format open close)))

  + make `let` work like `let*`: "let's" stop confusing newcomers.

  + hash-tables: how come that working with hash-tables is such a pain?
    I love how they are function of themselves in clojure and that
    there's reader syntax for them.

  (setq tags (make-hash-table))
  (puthash tags :p "</p>")
  (puthash tags :span "</span>")
  (gethash :span tags) ; -> "</p>"

  ;; clojuresque version
  (setq tags {:p "</p>" :span "</span>"})
  (:p tags) ; -> "</p>"
  (tags :p) ; -> "</p>"
  (:html tags) ; -> nil
  (tags :html) ; -> signals error

  ;; Another option is just using the hash-table itself as a function
  ;; and don't signal an error if a third arg is provided as the
  ;; default.

  (tags :html) ; -> signals error
  (tags :html "<html>") ; -> "<html>"

This is a quick list from the top of my head but there's more (for
instance, cond with less parens and reader syntax for anonymous
functions), but I'd like to have some comments first WRT the
possibilities and acceptance.

My high level idea is that we'd have all this stuff in a single file and
my hope is that it could be implemented a such way that is compatible
with older versions of Emacs (say down to 22).

Users of older Emacs will just need to require this file in their .emacs
to use packages that use these new utilities, but in newer Emacs
releases, these things will be considered core stuff and no require will
be needed whatsoever.

I hope we can do some brainstorming a bit. My goal with this is to find
ways to evolve Emacs Lisp a bit further by providing facilities that
allow writting cleaner and more redeable code while allowing for
backwards compatibility.

[0] http://clojure.org/


reply via email to

[Prev in Thread] Current Thread [Next in Thread]