On Feb 25, 10:18 am, Xah Lee <xah...@gmail.com> wrote: > On Feb 25, 3:34 am, nick_keighley_nos...@hotmail.com wrote: > > > the nasty cons then only appears in a single function which > > you can hide in a library > > I think the following answers that. > > Q: If you don't like cons, lisp has arrays and hashmaps, too. > > A: Suppose there's a lang called gisp. In gisp, there's cons but also > fons. Fons are just like cons except it has 3 cells with 3 accessors: > car, cbr, cdr. Now, gisp is a old lang, the fons are deeply rooted in > the lang. Every some 100 lines of code you'll see a use of fons with > its extra accessor cbr, or any one of the cbaar, cdabr, cbbar, cbbbar, > etc. You got annoyed by this. You as a critic, complains that fons is > bad. But then some gisp fanatics retorts: “If you don't like fons, > gisp has cons, too!”. > > You see, by “having something too”, does not solve the problem of > pollution. Sure, you can use just cons in gisp, but every lib or > other's code you encounter, there's a invasion of fons with its cbar, > cbbar, cbbbar. The problem created by fons does not go away by “having > cons too”. > > above is from > > • Fundamental Problems of Lisp > http://xahlee.org/UnixResource_dir/writ/lisp_problems.html > > --------- > > > I read it. Your point seems to be "cons becomes difficult > > with deeply nested structures". Could you give an example? > > There are few examples in these articles: > > • The Concepts and Confusions of Prefix, Infix, Postfix and Fully > Nested Notations > http://xahlee.org/UnixResource_dir/writ/notations.html > > the above, 3rd section, gives detail about the problems of fully > nested syntax. In particular, it shows a source code snippet of > language with fully nested syntax, but is not lisp, so that lispers > can get a fresh impression. > > • A Ruby Illustration of Lisp Problems > http://xahlee.org/UnixResource_dir/writ/lisp_problems_by_ruby.html > > the above, is a concrete example of showing how full nesting is > cumbersome, by constrasting a simple program in Ruby and lisp. > > • Why Lisp Do Not Have A Generic Copy-List Function > http://xahlee.org/UnixResource_dir/writ/lisp_equal_copy_list.html > > the above, shows the cons problem, by looking Kent Pitman's article > with a different perspective. > > A short Plain Text Excerpt of the ruby article cited above follows. > ------------------------------ > > More specifically, 2 fundamental problems of lisp i feel this ruby > example illustrates well: > > • the cons impedes many aspects of lists. e.g. difficult to learn, > confusing, hard to use, prevent development of coherent list > manipulation functions. > > • nested syntax impedes the functional programing paradigm of function > chaining, esp when each function has 2 or more arguments (e.g. map). > > here's a short summary of the nesting problem: > > (map f x) ; 1 level of chaining > (map g (map f x)) ; 2 levels > (map h (map g (map f x))) ; 3 levels > > compare: > > x | f | g | h ----> unix pipe > x // f // g // h ----> Mathematica > h @ g @ f @ x ----> Mathematica > x.f.g.h -------> various OOP langs, esp Ruby, javascript > h g f x -------> some functional langs, Haskell, Ocaml > > The way the above works is that each of f, g, h is a lambda themselves > that maps. (that is, something like “(lambda (y) (map f y))”) > > Note, that any of the f, g, h may be complex pure functions (aka > lambda). Because in lisp, each lambda itself will in general have > quite a lot nested parens (which cannot be avoided), so this makes any > chaining of functions of 2 args, for more than 2 or 3 levels of > nesting, unusable for practical coding. One must define the functions > separately and just call their names, or use function composition with > lambda (which gets complex quickly). One major aspect of this problem > is that the scope of vars becomes hard to understand in the deep > nested source code. This is worse in elisp, because emacs is > dynamically scoped, so you have to avoid using var of same name.
Here's a actual lisp code. I don't consider it readable, due to the profusion of parens. (defun lisp-complete-symbol (&optional predicate) "Perform completion on Lisp symbol preceding point. Compare that symbol against the known Lisp symbols. If no characters can be completed, display a list of possible completions. Repeating the command at that point scrolls the list. When called from a program, optional arg PREDICATE is a predicate determining which symbols are considered, e.g. `commandp'. If PREDICATE is nil, the context determines which symbols are considered. If the symbol starts just after an open-parenthesis, only symbols with function definitions are considered. Otherwise, all symbols with function definitions, values or properties are considered." (interactive) (let ((window (get-buffer-window "*Completions*" 0))) (if (and (eq last-command this-command) window (window-live-p window) (window-buffer window) (buffer-name (window-buffer window))) ;; If this command was repeated, and ;; there's a fresh completion window with a live buffer, ;; and this command is repeated, scroll that window. (with-current-buffer (window-buffer window) (if (pos-visible-in-window-p (point-max) window) (set-window-start window (point-min)) (save-selected-window (select-window window) (scroll-up)))) ;; Do completion. (let* ((end (point)) (beg (with-syntax-table emacs-lisp-mode-syntax-table (save-excursion (backward-sexp 1) (while (= (char-syntax (following-char)) ?\') (forward-char 1)) (point)))) (pattern (buffer-substring-no-properties beg end)) (predicate (or predicate (save-excursion (goto-char beg) (if (not (eq (char-before) ?\()) (lambda (sym) ;why not just nil ? -sm (or (boundp sym) (fboundp sym) (symbol-plist sym))) ;; Looks like a funcall position. Let's double check. (if (condition-case nil (progn (up-list -2) (forward-char 1) (eq (char-after) ?\()) (error nil)) ;; If the first element of the parent list is an open ;; parenthesis we are probably not in a funcall position. ;; Maybe a `let' varlist or something. nil ;; Else, we assume that a function name is expected. 'fboundp))))) (completion (try-completion pattern obarray predicate))) (cond ((eq completion t)) ((null completion) (message "Can't find completion for \"%s\"" pattern) (ding)) ((not (string= pattern completion)) (delete-region beg end) (insert completion) ;; Don't leave around a completions buffer that's out of date. (let ((win (get-buffer-window "*Completions*" 0))) (if win (with-selected-window win (bury-buffer))))) (t (let ((minibuf-is-in-use (eq (minibuffer-window) (selected-window)))) (unless minibuf-is-in-use (message "Making completion list...")) (let ((list (all-completions pattern obarray predicate))) (setq list (sort list 'string<)) (or (eq predicate 'fboundp) (let (new) (while list (setq new (cons (if (fboundp (intern (car list))) (list (car list) " <f>") (car list)) new)) (setq list (cdr list))) (setq list (nreverse new)))) (if (> (length list) 1) (with-output-to-temp-buffer "*Completions*" (display-completion-list list pattern)) ;; Don't leave around a completions buffer that's ;; out of date. (let ((win (get-buffer-window "*Completions*" 0))) (if win (with-selected-window win (bury-buffer)))))) (unless minibuf-is-in-use (message "Making completion list...%s" "done"))))))))) Xah ∑ http://xahlee.org/ ☄ -- http://mail.python.org/mailman/listinfo/python-list