Programing Language: A Ruby Illustration of Lisp Problems
Here's a interesting toy problem posted by Drew Krause to comp.lang.lisp:
OK, I want to create a nested list in Lisp (always of only integers) from a text file, such that each line in the text file would be represented as a sublist in the 'imported' list.
Example of input
3 10 2 4 1 11 18example of output:
((3 10 2) (4 1) (11 18))
Here's a emacs lisp version:
(defun read-lines (file) "Return a list of lines in FILE." (with-temp-buffer (insert-file-contents file) (split-string (buffer-string) "\n" t) ) ) (mapcar (lambda (x) (mapcar (lambda (y) (string-to-number y) ) (split-string x " ") ) ) (read-lines "blob.txt") )
The above coding style is a typical maintainable elisp.
In a show-off context, it can be reduced to by about 50%, but still far verbose than ruby or say perl (which is 1 or 2 lines. (python would be 2 or 3)).
Ruby, Python
# -*- coding: utf-8 -*- # ruby # by w_a_x_…@yahoo.com, William James IO.readlines("blob.txt").map{|line| line.split.map{|s| s.to_i }}
# -*- coding: utf-8 -*- # python # by Михаил Осипов and other [map(int, line.split()) for line in open("blob.txt").readlines()]
That's really the beauty of Ruby.
This Ruby code illustrates 2 fundamental problems of lisp, namely, the cons problem, and the nested syntax pain. Both of which are practically unfixable. 〔see Fundamental Problems of Lisp〕
The lisp's cons fundamentally makes nested list a pain to work with. Lisp's nested syntax makes functional sequencing cumbersome.
In the Ruby code, its post-fix sequential notation (as a side effect of its OOP notation) brings out the beauty of functional sequencing paradigm (sometimes known as functional chain, sequencing, filtering, unix piping). 〔see OOP Dot Notation, Dot Before Data or After?〕
more example: LISP Syntax Problem of Piping Functions
Daniel Weinreb wrote:
Your claim that this shows something wrong with lists is completely unclear, although if I read your paper (I'll try) I might have some idea what you're getting at.
More specifically, 2 fundamental problems of lisp i feel this ruby example illustrates well:
- The cons impedes many aspects of lists. For example, difficult to learn, confusing, hard to use, prevent development of coherent list manipulation functions.
- Nested syntax impedes the functional programing paradigm of function chaining, especially when each function has 2 or more arguments (For example, map).
Here's a short summary of the nesting problem:
(map f x) ; 1 function (map g (map f x)) ; a sequence of 2 functions (map h (map g (map f x))) ; a sequence of 3 functions
compare:
x | f | g | h unix pipe x // f // g // h Mathematica h @ g @ f @ x Mathematica x.f.g.h various OOP langs, especially 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.
For more detail on the cons problem, see the section “The Cons Business” at Fundamental Problems of Lisp .
For more detail on the nested syntax problem for function chaining, see the section “How Purely Nested Notation Limits The Language's Utility” at Concepts and Confusions of Prefix, Infix, Postfix and Lisp Notations .
For a pespective on the fact that cons prevents lisp from developing a coherent list/tree processing library, see: Why Lisp Do Not Have A Generic Copy-List Function .
Lisp Cons Problem
Its list, like all modern high level langs such as Perl, PHP, JavaScript, Python, don't have the lisp's cons problem. The cons destroys the usability of lists up-front, untill you have some at least 2 full-time years of coding lisp to utilize cons properly. (and even after that, it is still a pain to work with, and all you gain is a bit of speed optimization in rare cases that requires largish data, most of which has better solutions such as a database.)