Discussion:
reading file to list
(too old to reply)
Xah Lee
2009-01-17 17:16:07 UTC
Permalink
comp.lang.lisp,comp.lang.scheme,comp.lang.functional,comp.lang.python,comp.lang.ruby

Here's a interesting toy problem posted by Drew Krause to
comp.lang.lisp:

------------------------
On Jan 16, 2:29 pm, Drew Krause wrote [paraphrased a bit]:

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 a file's content

3 10 2
4 1
11 18

example of programing behavior
(make-list-from-text "blob.txt") => ((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-substring-no-properties 1 (point-max)) "\n" t)
)
)

(defvar mylist '() "result list" )
(setq mylist '()) ; init in case eval'd again

(mapc
(lambda (x) (setq mylist
(cons (split-string x " ") mylist )) )
(read-lines "xxblob.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 3 or 5)).

Note that the result element is string, not numbers. There's no easy
way to convert them on the fly. 3 or so more lines will be needed to
do that.

The “read-lines” function really should be a built-in part of elisp.
It is not so mostly because emacs people have drawn themselves into a
elitist corner, closing off to the outside world. (i am sending a
suggestion to the official emacs dev list on adding read-line now.)

-----------------

***@yahoo.com gave a ruby solution:

IO.readlines("blob.txt").map{|line| line.split }

augumented by Jilliam James for result to be numbers:

IO.readlines("blob.txt").map{|line| line.split.map{|s| s.to_i }}

Very beautiful.

-------------------

That's really the beauty of Ruby.

This problem and ruby code illustrates 2 fundamental problems of lisp,
namely, the cons problem, and the nested syntax pain. Both of which
are practically unfixable.

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).

its list, like all modern high level langs such as perl, php, python,
javascript, 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.)

Both of these problems i've published articles on.

For more detail on the cons problem, see
the section “The Cons Business” at

• Fundamental Problems of Lisp
http://xahlee.org/UnixResource_dir/writ/lisp_problems.html

For more detail on the nested syntax problem for function chaining,
see
the section “How Purely Nested Notation Limits The Language's Utility”
at:

• The Concepts and Confusions of Prefix, Infix, Postfix and Fully
Nested Notations
http://xahlee.org/UnixResource_dir/writ/notations.html

Xah
∑ http://xahlee.org/


Xah Lee
2009-01-17 17:34:39 UTC
Permalink
Post by Xah Lee
Here's a interesting toy problem posted by Drew Krause to
...
The code in my previous elisp code got a bump. It should be:

(defun read-lines (file)
"Return a list of lines in FILE."
(with-temp-buffer
(insert-file-contents file)
(split-string
(buffer-substring-no-properties 1 (point-max)) "\n" t)
)
)

(mapcar
(lambda (x) (split-string x " ") )
(read-lines "xxblob.txt")
)

The article is now archived at:

• A Ruby Illustration of Lisp Problems
http://xahlee.org/UnixResource_dir/writ/lisp_problems_by_ruby.html

Xah
∑ http://xahlee.org/


Xah Lee
2009-01-17 17:55:43 UTC
Permalink
Post by Xah Lee
...
• A Ruby Illustration of Lisp Problems
http://xahlee.org/UnixResource_dir/writ/lisp_problems_by_ruby.html
Sorry again. More correction:

(defun read-lines (file)
"Return a list of lines in FILE."
(with-temp-buffer
(insert-file-contents file)
(split-string
(buffer-substring-no-properties 1 (point-max)) "\n" t)
)
)

(mapcar
(lambda (x)
(mapcar
(lambda (y) (string-to-number y) )
(split-string x " ")
)
)
(read-lines "xxblob.txt")
)

this is last post of correction.

Xah
∑ http://xahlee.org/


André Thieme
2009-01-17 20:30:49 UTC
Permalink
Post by Xah Lee
comp.lang.lisp,comp.lang.scheme,comp.lang.functional,comp.lang.python,comp.lang.ruby
Here's a interesting toy problem posted by Drew Krause to
------------------------
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 a file's content
3 10 2
4 1
11 18
example of programing behavior
(make-list-from-text "blob.txt") => ((3 10 2) (4 1) (11 18))
IO.readlines("blob.txt").map{|line| line.split }
IO.readlines("blob.txt").map{|line| line.split.map{|s| s.to_i }}
Very beautiful.
-------------------
That's really the beauty of Ruby.
This problem and ruby code illustrates 2 fundamental problems of lisp,
namely, the cons problem, and the nested syntax pain. Both of which
are practically unfixable.
*Of course* Xah is wrong, as always.
Who would expect anything else?
In the Lisp style Clojure for example one does exactly the same as
Jillian James (JJ) did in Ruby:
(map #(map (fn [s] (Integer/parseInt s)) (.split % "\\s")) (line-seq
(reader "blob.txt")))

This is slightly longer, simply because the functions have longer names.
Integer/parseInt vs to_i

Also the function split takes a regexp, so I have to add the "\\s" here.
I don’t know though if Jillians version also handles any kind of
whitespac per line.
And the last thing is, that the function reader returns a BufferedReader.
So in general this is more valuable in real programs as opposed to one-
line scripts. If we combine line-seq and reader into readline and apply
the two other changes we would say:
(map #(map (fn [s] (to_i s)) (.split %)) (readlines "blob.txt"))
vs
IO.readlines("blob.txt").map{|line| line.split.map{|s| s.to_i }}

So, obviously Xah is far away from any reality.
It took him hours of his life to write up all his ideas about Lisp.
Sad to see that all that time was wasted. All of it was wrong.
Poor Xah :(


And btw, Drew Krause is just a Lisp newbie. No Lisper would ever store
data for his programs in the format
3 10 2
4 1
11 18

but instead as
(3 10 2)
(4 1)
(11 18)

And then read it back into the program with:
(map read-string (line-seq (reader "blob.txt")))


André
--
Xah Lee
2009-01-18 00:30:24 UTC
Permalink
Post by Xah Lee
• A Ruby Illustration of Lisp Problems
http://xahlee.org/UnixResource_dir/writ/lisp_problems_by_ruby.html
On Jan 17, 12:30 pm, André Thieme <address.good.until.
Post by Xah Lee
In the Lisp style Clojure for example one does exactly the same as
(map #(map (fn [s] (Integer/parseInt s)) (.split % "\\s")) (line-seq
(reader "blob.txt")))
Note that you have nested map. This is a problem of function chaning
as i detailed.

The other problem of cons, is commonly seen. Just about every week, we
see some perhaps beginning lisper asking how to do various trivial
list
manipulation problem, which you don't see such question or frequency
in any of modern high level lang forms.

The frequently asked list manipulation question we see include how to
append, prepend, or anything involving nested list such as
partitioning, reordering sublists, getting leaves, interpretation of
leaves, etc. This is caused by the cons.

associated lisp problem compound the issue. Namely, the not exactly
regular syntax, and the eval model of sometimes symbol sometimes
uneval'd symbol, e.g. “'(...)”, “`(...,@ ...)” things.

The clojure example you gave above, apparently inherited the irregular
syntax problem. (you see the #, [], % things, which is breaks the
lisp's sexp idea) Also, all modern lisp basically all get fucked up by
inheriting the cons (e.g. clojure, NewLisp, Arc lisp, Liskell). Often,
they change the semantic a bit apparently as a mesaure towards solving
the cons problem. (and Qi Lisp creates a huge bag of ad hoc, extremely
ugly, syntax soup)

Advice: if you are creating a lispy lang, two things:

• stick to a _pure_ nested syntax, no exception whatsoever. (e.g. no
more ` ' # % shits) If you want, add a transparent layer on top to
support arbitrary algeraic notation. (e.g. look at Mathematica, CGOL)

• get rid of the cons. (you can still implement the so-called linked
list, but no where it should be shown to the programer)

Further readings:

• Fundamental Problems of Lisp
http://xahlee.org/UnixResource_dir/writ/lisp_problems.html

Xah
∑ http://xahlee.org/


André Thieme
2009-01-18 01:25:00 UTC
Permalink
Post by Xah Lee
Post by Xah Lee
• A Ruby Illustration of Lisp Problems
http://xahlee.org/UnixResource_dir/writ/lisp_problems_by_ruby.html
On Jan 17, 12:30 pm, André Thieme <address.good.until.
Post by Xah Lee
In the Lisp style Clojure for example one does exactly the same as
(map #(map (fn [s] (Integer/parseInt s)) (.split % "\\s")) (line-seq
(reader "blob.txt")))
Note that you have nested map. This is a problem of function chaning
as i detailed.
Yes, Jillian also has nested maps:
IO.readlines("blob.txt").map{|line| line.split.map{|s| s.to_i }}
Post by Xah Lee
The other problem of cons, is commonly seen. Just about every week, we
see some perhaps beginning lisper asking how to do various trivial
list
manipulation problem, which you don't see such question or frequency
in any of modern high level lang forms.
You see questions about trivial problems every week in all forums about
programming languages.
It has nothing to do with conses. Wrong road.
Post by Xah Lee
The frequently asked list manipulation question we see include how to
append, prepend, or anything involving nested list such as
partitioning, reordering sublists, getting leaves, interpretation of
leaves, etc. This is caused by the cons.
Yes, same with all containers in all programming languages.
Post by Xah Lee
The clojure example you gave above, apparently inherited the irregular
syntax problem. (you see the #, [], % things, which is breaks the
lisp's sexp idea)
My code used 8 “mysterious symbols”:
( ) # [ ] . " %

The Ruby version had these 7:
( ) | { } . "

And of course, neither in Ruby nor Clojure they break any idea.
Post by Xah Lee
Also, all modern lisp basically all get fucked up by
inheriting the cons (e.g. clojure, NewLisp, Arc lisp, Liskell). Often,
they change the semantic a bit apparently as a mesaure towards solving
the cons problem. (and Qi Lisp creates a huge bag of ad hoc, extremely
ugly, syntax soup)
Funny.
What you write is an english text with words that most people can
understand.
You trick them into thinking that it actually makes sense what you say.
It is so technical, that a random would believe it.
But what you really say is about as meaningful as saying that it is
impossible to write good programs in Python, because it adds whitespace
to its syntax.
Post by Xah Lee
• Fundamental Problems of Lisp
http://xahlee.org/UnixResource_dir/writ/lisp_problems.html
You wasted lots of your time. Or was this maybe generated by a bot?
Maybe http://pdos.csail.mit.edu/scigen/ or something like that?
I also found this paper that you wrote:
http://apps.pdos.lcs.mit.edu/scicache/184/scimakelatex.7076.Xah+Lee.html
Another crap posting of you. But a random person might be impressed.


André
--
Xah Lee
2009-01-18 03:07:24 UTC
Permalink
the issue here, is not about whether Ruby has nested map or not. It is
about illustrating a lisp problem. In particular, nested syntax
impedes the functional programing paradigm of function chaining.

• A Ruby Illustration of Lisp Problems
http://xahlee.org/UnixResource_dir/writ/lisp_problems_by_ruby.html
Post by André Thieme
( ) # [ ] . " %
( ) | { } . "
The issue here is not about which lang employs more special chars. The
issue is about the irregularities in lisp's syntax damaged its power
of its otherwise believed superior regular syntax.

• Fundamental Problems of Lisp
http://xahlee.org/UnixResource_dir/writ/lisp_problems.html

Xah
∑ http://xahlee.org/


William James
2009-01-18 23:29:57 UTC
Permalink
Post by André Thieme
Post by Xah Lee
comp.lang.lisp,comp.lang.scheme,comp.lang.functional,comp.lang.pytho
n,comp.lang.ruby
Here's a interesting toy problem posted by Drew Krause to
------------------------
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 a file's content
3 10 2
4 1
11 18
example of programing behavior
(make-list-from-text "blob.txt") => ((3 10 2) (4 1) (11 18))
IO.readlines("blob.txt").map{|line| line.split }
IO.readlines("blob.txt").map{|line| line.split.map{|s| s.to_i }}
Very beautiful.
-------------------
That's really the beauty of Ruby.
This problem and ruby code illustrates 2 fundamental problems of
lisp, namely, the cons problem, and the nested syntax pain. Both of
which are practically unfixable.
*Of course* Xah is wrong, as always.
Who would expect anything else?
In the Lisp style Clojure for example one does exactly the same as
(map #(map (fn [s] (Integer/parseInt s)) (.split % "\\s")) (line-seq
(reader "blob.txt")))
That fails when numbers are separated by more than one space.
And what about leading or trailing space?
Post by André Thieme
This is slightly longer, simply because the functions have longer
names. Integer/parseInt vs to_i
Also the function split takes a regexp, so I have to add the "\\s"
here. I don’t know though if Jillians version also handles any
kind of whitespac per line.
irb(main):003:0> puts " foo \t bar "
foo bar
=> nil
irb(main):004:0> " foo \t bar ".split
=> ["foo", "bar"]
irb(main):005:0> "foo...bar?-!hoo".split /\W+/
=> ["foo", "bar", "hoo"]
Post by André Thieme
And the last thing is, that the function reader returns a
BufferedReader. So in general this is more valuable in real programs
as opposed to one- line scripts. If we combine line-seq and reader
(map #(map (fn [s] (to_i s)) (.split %)) (readlines "blob.txt"))
That is not a complete program.
Post by André Thieme
vs
IO.readlines("blob.txt").map{|line| line.split.map{|s| s.to_i }}
That is the complete program.
Post by André Thieme
So, obviously Xah is far away from any reality.
It took him hours of his life to write up all his ideas about Lisp.
Sad to see that all that time was wasted. All of it was wrong.
Poor Xah :(
And btw, Drew Krause is just a Lisp newbie. No Lisper would ever store
data for his programs in the format
3 10 2
4 1
11 18
but instead as
(3 10 2)
(4 1)
(11 18)
Perhaps the data was stored by someone else. Understand?
Post by André Thieme
(map read-string (line-seq (reader "blob.txt")))
You make a very strong case that Lisp is very feeble at
processing data. I'm almost convinced.

Ruby isn't feeble, so data like this is fine:


shall we begin?
or lotus135? 1984 times!
The 3 stooges: COBOL,LISP,FORTRAN.
3.14, si11y L00KING


Extracting the unsigned integers:

IO.readlines('data').map{|s| s.scan(/\d+/).map{|s| s.to_i}}
==>[[], [135, 1984], [3], [3, 14, 11, 0]]
André Thieme
2009-01-19 02:24:22 UTC
Permalink
Post by William James
You make a very strong case that Lisp is very feeble at
processing data. I'm almost convinced.
I somehow don’t believe you :-)
Post by William James
shall we begin?
or lotus135? 1984 times!
The 3 stooges: COBOL,LISP,FORTRAN.
3.14, si11y L00KING
IO.readlines('data').map{|s| s.scan(/\d+/).map{|s| s.to_i}}
==>[[], [135, 1984], [3], [3, 14, 11, 0]]
Just take the program I posted before and replace
(.split % "\\s")
with
(re-seq #"\d+" %)


Now that I was so kind to give you what you asked for, you will
probably do the same for me and show me your Ruby code, in which you
define a variable that contains the Fibonacci sequence.

(def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs))))


(nth fibs 70) ==> 190392490709135

One requirement is that when you look at the n'th fib the results up
to n must be memoized, so that nothing needs to be calculated again
when you ask for a fib between 0 and n. And when you ask for the n+1'th
it will start the calculation right from point n.

Example:
user> (time (nth fibs 900))
"Elapsed time: 16.898726 msecs"

user> (time (nth fibs 901))
"Elapsed time: 0.268603 msecs"


André
--
William James
2009-02-22 08:13:11 UTC
Permalink
Post by André Thieme
(map #(map (fn [s] (Integer/parseInt s)) (.split % "\\s")) (line-seq
(reader "blob.txt")))
An error results:

java.lang.Exception: Unable to resolve symbol: reader in this context

This works:

(map #(map (fn [s] (Integer/parseInt s)) (.split % "\\s"))
(.split (slurp "junk") "\r?\n"))
n***@hotmail.com
2009-02-24 15:00:41 UTC
Permalink
comp.lang.lisp,comp.lang.scheme,comp.lang.functional,comp.lang.python,comp.­lang.ruby
Here's a interesting toy problem posted by Drew Krause to
------------------------
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 a file's content
3 10 2
4 1
11 18
example of programing behavior
(make-list-from-text "blob.txt") => ((3 10 2) (4 1) (11 18))
-----------------
(defun read-lines (file)
"Return a list of lines in FILE."
(with-temp-buffer
(insert-file-contents file)
(split-string
(buffer-substring-no-properties 1 (point-max)) "\n" t)
)
)
(defvar mylist '() "result list" )
(setq mylist '()) ; init in case eval'd again
(mapc
(lambda (x) (setq mylist
(cons (split-string x " ") mylist )) )
(read-lines "xxblob.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 3 or 5)).
Note that the result element is string, not numbers. There's no easy
way to convert them on the fly. 3 or so more lines will be needed to
do that.
The “read-lines” function really should be a built-in part of elisp.
It is not so mostly because emacs people have drawn themselves into a
elitist corner, closing off to the outside world. (i am sending a
suggestion to the official emacs dev list on adding read-line now.)
scheme:

(define (read-line port)
(define (rec-read-line port line)
(define next-char (peek-char port))
(define number #f)
(cond ((eof-object? next-char) '())
((char=? next-char #\newline) (read-char port) line)
((char-numeric? next-char)
(set! number (read port))
(cons number (rec-read-line port line)))
((char=? next-char #\space)
(read-char port)
(rec-read-line port line))
(else (error (string-append "bad character \""
(string next-char) "\"")))
))

(rec-read-line port '())
)

(define (make-int-list port)
(define line (read-line port))
(if (null? line)
'()
(cons line (make-int-list port))))

(define (make-list-from-text file)
(make-int-list (open-input-file file)))
-----------------
IO.readlines("blob.txt").map{|line| line.split }
IO.readlines("blob.txt").map{|line| line.split.map{|s| s.to_i }}
Very beautiful.
-------------------
That's really the beauty of Ruby.
This problem and ruby code illustrates 2 fundamental problems of lisp,
namely, the cons problem, and the nested syntax pain. Both of which
are practically unfixable.
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).
its list, like all modern high level langs such as perl, php, python,
javascript, 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.)
Both of these problems i've published articles on.
For more detail on the cons problem, see
the section “The Cons Business” at
• Fundamental Problems of Lisp
http://xahlee.org/UnixResource_dir/writ/lisp_problems.html
For more detail on the nested syntax problem for function chaining,
see
the section “How Purely Nested Notation Limits The Language's Utility”
• The Concepts and Confusions of Prefix, Infix, Postfix and Fully
Nested Notations
http://xahlee.org/UnixResource_dir/writ/notations.html
n***@hotmail.com
2009-02-25 11:24:07 UTC
Permalink
Post by n***@hotmail.com
Post by Xah Lee
Here's a interesting toy problem posted by Drew Krause to
------------------------
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 a file's content
3 10 2
4 1
11 18
example of programing behavior
(make-list-from-text "blob.txt") => ((3 10 2) (4 1) (11 18))
<snip>
Post by n***@hotmail.com
(define (read-line port)
    (define (rec-read-line port line)
        (define next-char (peek-char port))
        (define number #f)
        (cond ((eof-object? next-char) '())
              ((char=? next-char #\newline) (read-char port) line)
              ((char-numeric? next-char)
                   (set! number (read port))
                   (cons number (rec-read-line port line)))
              ((char=? next-char #\space)
                   (read-char port)
                   (rec-read-line port line))
              (else (error (string-append "bad character \""
                              (string next-char) "\"")))
    ))
    (rec-read-line port '())
)
(define (make-int-list port)
    (define line (read-line port))
    (if (null? line)
        '()
        (cons line (make-int-list port))))
(define (make-list-from-text file)
    (make-int-list (open-input-file file)))
an assignment-free version

(define (read-line port)
(define (rec-read-line port line)
(let ((next-char (peek-char port)))
(cond ((eof-object? next-char) '())
((char=? next-char #\newline) (read-char port) line)
((char-numeric? next-char)
(let ((number (read port)))
(cons number (rec-read-line port line))))
((char=? next-char #\space)
(read-char port)
(rec-read-line port line))
(else (error (string-append "bad character \""
(string next-char) "\""))))))

(rec-read-line port '()))

(define (make-int-list port)
(let ((line (read-line port)))
(if (null? line)
'()
(cons line (make-int-list port)))))

(define (make-list-from-text file)
(make-int-list (open-input-file file)))

(define (mk) (make-list-from-text "blob.txt"))

<snip>

number was originally define'd but I discovered there were
limits to where you could define things
n***@hotmail.com
2009-02-25 11:34:33 UTC
Permalink
comp.lang.lisp,comp.lang.scheme,comp.lang.functional,comp.lang.python,comp.­lang.ruby
<snip>
The lisp's cons fundamentally makes nested list a pain to work with.
Lisp's nested syntax makes functional sequencing cumbersome.
so hide it

(define (make-list stream eos?)
(let ((atom (stream)))
(if (eos? atom)
'()
(cons atom (make-list stream eos?)))))

(define (make-int-list port)
(make-list (lambda () (read-line port)) null?))

the nasty cons then only appears in a single function which
you can hide in a library
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).
its list, like all modern high level langs such as perl, php, python,
javascript, 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.)
is my code to build a list that bad?
Both of these problems i've published articles on.
For more detail on the cons problem, see
the section “The Cons Business” at
• 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?
Xah Lee
2009-02-25 18:18:17 UTC
Permalink
Post by n***@hotmail.com
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

---------
Post by n***@hotmail.com
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.

Xah
∑http://xahlee.org/


Xah Lee
2009-02-26 00:46:52 UTC
Permalink
Post by Xah Lee
Post by n***@hotmail.com
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
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
---------
Post by n***@hotmail.com
I read it. Your point seems to be "cons becomes difficult
with deeply nested structures". Could you give an example?
• 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
• 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).
(map f x) ; 1 level of chaining
(map g (map f x)) ; 2 levels
(map h (map g (map f x))) ; 3 levels
x | f | g | h ----> unix pipe
x // f // g // h ----> 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/



Continue reading on narkive:
Loading...