From: Xah Lee
Subject: how to avoid nested mapcar? (Emacs Lisp)
Date: 
Message-ID: <1185918954.203026.283740@m37g2000prh.googlegroups.com>
In the following code, it prints a HTML table of emacs keybindings on
the Dvorak layout. (see
http://xahlee.org/emacs/emacs_kb_shortcuts.html
)

My question is, how do i reduce the nesting in the
function print-keybinding-html-table-dvorak?
In it, i have used nested mapcar with 2 lambdas each.

(setq keyboard-layout-dvorak
'(
  (("1" "2" "3" "4" "5")
   ("6" "7" "8" "9" "0" "[" "]" "<backspace>"))
  (("'" "," "." "p" "y")
   ("f" "g" "c" "r" "l" "/" "=" "\\"))
  (("a" "o" "e" "u" "i")
   ("d" "h" "t" "n" "s" "-" "<RET>"))
  (("\;" "q" "j" "k" "x")
   ("b" "m" "w" "v" "z"))
  )
)


(defun html-line-for-kb-shortcut (key)
  "Takes input arg and output a string for html. The key is a ascii
char in string form"
(concat "<td><span class=\"key\">"
key
"</span><br><span class=\"C\">"
(format "%S" (key-binding (read-kbd-macro (concat "C-" key))))
"</span><br><span class=\"M\">"
(format "%S" (key-binding (read-kbd-macro (concat "M-" key))))
"</span></td>\n")
)


(defun print-keybinding-html-table-dvorak ()
  "returns a HTML table (as string) of current keybindings on the
Dvorak layout."
  (interactive)
  (let (output)
    (setq output "<table>")
(mapcar
 (lambda (x)
   (progn
     (setq output (concat output "<tr>\n"))

     (mapcar
      (lambda (y)
        (progn
          (setq output (concat output "<td>"))
          (setq output (concat output
                (apply 'concat (mapcar 'html-line-for-kb-shortcut y))
                ))
          (setq output (concat output "</td>\n"))
          )
        )
      x
      )
     (setq output (concat output "</tr>"))
     )
   )
 keyboard-layout-dvorak
 )
(setq output (concat output "</table>"))
output ;; need to replace <> by &lt; etc.
)
)


Thanks.

  Xah
  ···@xahlee.org
∑ http://xahlee.org/

From: Dan Bensen
Subject: Re: how to avoid nested mapcar? (Emacs Lisp)
Date: 
Message-ID: <f8ou6j$270$1@wildfire.prairienet.org>
Xah Lee wrote:
> My question is, how do i reduce the nesting in the
> function print-keybinding-html-table-dvorak?

Pull the lambdas out and define them separately.

-- 
Dan
www.prairienet.org/~dsb/
From: David Kastrup
Subject: Re: how to avoid nested mapcar? (Emacs Lisp)
Date: 
Message-ID: <851weo3zm0.fsf@lola.goethe.zz>
Xah Lee <···@xahlee.org> writes:

> In the following code, it prints a HTML table of emacs keybindings on
> the Dvorak layout. (see
> http://xahlee.org/emacs/emacs_kb_shortcuts.html
> )
>
> My question is, how do i reduce the nesting in the
> function print-keybinding-html-table-dvorak?
> In it, i have used nested mapcar with 2 lambdas each.
>
> (setq keyboard-layout-dvorak
> '(
>   (("1" "2" "3" "4" "5")
>    ("6" "7" "8" "9" "0" "[" "]" "<backspace>"))
>   (("'" "," "." "p" "y")
>    ("f" "g" "c" "r" "l" "/" "=" "\\"))
>   (("a" "o" "e" "u" "i")
>    ("d" "h" "t" "n" "s" "-" "<RET>"))
>   (("\;" "q" "j" "k" "x")
>    ("b" "m" "w" "v" "z"))
>   )
> )
>
>
> (defun html-line-for-kb-shortcut (key)
>   "Takes input arg and output a string for html. The key is a ascii
> char in string form"
> (concat "<td><span class=\"key\">"
> key
> "</span><br><span class=\"C\">"
> (format "%S" (key-binding (read-kbd-macro (concat "C-" key))))
> "</span><br><span class=\"M\">"
> (format "%S" (key-binding (read-kbd-macro (concat "M-" key))))
> "</span></td>\n")
> )
>
>
> (defun print-keybinding-html-table-dvorak ()
>   "returns a HTML table (as string) of current keybindings on the
> Dvorak layout."
>   (interactive)
>   (let (output)
>     (setq output "<table>")
> (mapcar
>  (lambda (x)
>    (progn
>      (setq output (concat output "<tr>\n"))
>
>      (mapcar
>       (lambda (y)
>         (progn
>           (setq output (concat output "<td>"))
>           (setq output (concat output
>                 (apply 'concat (mapcar 'html-line-for-kb-shortcut y))
>                 ))
>           (setq output (concat output "</td>\n"))
>           )
>         )
>       x
>       )
>      (setq output (concat output "</tr>"))
>      )
>    )
>  keyboard-layout-dvorak
>  )

Repeatedly appending to a string is inefficient.  Use a buffer here.
(let ((old-buffer (current-buffer)))
(with-temp-buffer
  (insert "<table>")
  (dolist (sublist keyboard-layout-dvorak (insert "</table>\n"))
     (insert "<tr>\n")
     (dolist (elt sublist (insert "</tr>"))
        (insert "<td>"
                (with-current-buffer old-buffer
                  (mapconcat 'html-line-for-kb-shortcut elt ""))
                "</td>\n")))
  (buffer-string))

> (setq output (concat output "</table>"))
> output ;; need to replace <> by &lt; etc.
> )
> )


-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum
From: Rainer Joswig
Subject: Re: how to avoid nested mapcar? (Emacs Lisp)
Date: 
Message-ID: <joswig-E4828E.03231201082007@news-europe.giganews.com>
In article <························@m37g2000prh.googlegroups.com>,
 Xah Lee <···@xahlee.org> wrote:

> In the following code, it prints a HTML table of emacs keybindings on
> the Dvorak layout. (see
> http://xahlee.org/emacs/emacs kb shortcuts.html
> )
> 
> My question is, how do i reduce the nesting in the
> function print-keybinding-html-table-dvorak?
> In it, i have used nested mapcar with 2 lambdas each.
> 
> (setq keyboard-layout-dvorak
> '(
>   (("1" "2" "3" "4" "5")
>    ("6" "7" "8" "9" "0" "[" "]" "<backspace>"))
>   (("'" "," "." "p" "y")
>    ("f" "g" "c" "r" "l" "/" "=" "\\"))
>   (("a" "o" "e" "u" "i")
>    ("d" "h" "t" "n" "s" "-" "<RET>"))
>   (("\;" "q" "j" "k" "x")
>    ("b" "m" "w" "v" "z"))
>   )
> )
> 
> 
> (defun html-line-for-kb-shortcut (key)
>   "Takes input arg and output a string for html. The key is a ascii
> char in string form"
> (concat "<td><span class=\"key\">"
> key
> "</span><br><span class=\"C\">"
> (format "%S" (key-binding (read-kbd-macro (concat "C-" key))))
> "</span><br><span class=\"M\">"
> (format "%S" (key-binding (read-kbd-macro (concat "M-" key))))
> "</span></td>\n")
> )
> 
> 
> (defun print-keybinding-html-table-dvorak ()
>   "returns a HTML table (as string) of current keybindings on the
> Dvorak layout."
>   (interactive)
>   (let (output)
>     (setq output "<table>")
> (mapcar
>  (lambda (x)
>    (progn
>      (setq output (concat output "<tr>\n"))
> 
>      (mapcar
>       (lambda (y)
>         (progn
>           (setq output (concat output "<td>"))
>           (setq output (concat output
>                 (apply 'concat (mapcar 'html-line-for-kb-shortcut y))
>                 ))
>           (setq output (concat output "</td>\n"))
>           )
>         )
>       x
>       )
>      (setq output (concat output "</tr>"))
>      )
>    )
>  keyboard-layout-dvorak
>  )
> (setq output (concat output "</table>"))
> output ;; need to replace <> by &lt; etc.
> )
> )
> 
> 
> Thanks.
> 
>   Xah
>   ···@xahlee.org
> ∑ http://xahlee.org/


You really need to post your code more often, so that you
can learn a bit Lisp programming from feedback. Above function
does definitely not have the lambda nature, yet.

* why is the formatting so fucked?
* what are those lonely closing parentheses? Is that C?
* why do you need PROGN?
* why do you use CONCAT over and over in a totally inefficient way?
* learn about 'buffers' (in elisp) or streams (in CL)
* learn about FLET
* learn about APPLY vs. REDUCE
* learn about MAPCAR vs. MAPC vs. DOLIST

-- 
http://lispm.dyndns.org