From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: fgallina@gnu.org Newsgroups: gmane.emacs.devel Subject: Sweeter Emacs Lisp Date: Sat, 13 Jul 2013 23:22:31 -0300 Message-ID: <8738rh6ftk.fsf@gnu.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: ger.gmane.org 1373768541 23670 80.91.229.3 (14 Jul 2013 02:22:21 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 14 Jul 2013 02:22:21 +0000 (UTC) To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Jul 14 04:22:23 2013 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1UyBx8-000885-Qn for ged-emacs-devel@m.gmane.org; Sun, 14 Jul 2013 04:22:23 +0200 Original-Received: from localhost ([::1]:60465 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UyBx8-0004Ey-Ci for ged-emacs-devel@m.gmane.org; Sat, 13 Jul 2013 22:22:22 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:36807) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UyBx3-0004Es-9e for emacs-devel@gnu.org; Sat, 13 Jul 2013 22:22:20 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UyBx0-0004xz-JR for emacs-devel@gnu.org; Sat, 13 Jul 2013 22:22:17 -0400 Original-Received: from fencepost.gnu.org ([2001:4830:134:3::e]:46556) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UyBx0-0004xv-GF for emacs-devel@gnu.org; Sat, 13 Jul 2013 22:22:14 -0400 Original-Received: from ol144-145.fibertel.com.ar ([24.232.145.144]:49650 helo=localhost) by fencepost.gnu.org with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1UyBwz-0002eZ-45; Sat, 13 Jul 2013 22:22:13 -0400 User-agent: mu4e 0.9.9.5; emacs 24.3.1 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::e X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:161861 Archived-At: 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 "

" "

")) (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 test ;;------------------------- ;; 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 "

" "

")) (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 "

") (puthash tags :span "") (gethash :span tags) ; -> "

" ;; clojuresque version (setq tags {:p "

" :span ""}) (:p tags) ; -> "

" (tags :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 "") ; -> "" 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/ -- Regards, Fabián