Hacker News new | ask | show | jobs
by lispm 746 days ago
You are on the surface. I'm talking about a computing paradigm defined by LISP. A foundational model at the core of the language, enabling us to understand how the List Processor actually works.

LISP has dialects which are not homoiconic, where programs are not written as s-expressions, ... But the core is the same: a specific List Processor. McCarthy himself did not want to write programs as s-expressions. He defined M-Expressions, where S-Expressions were only used for the data.

Check the book "Anatomy of LISP", which is a classic. All the code in the book is written in M-Expressions. Now, Racket gets a new syntax (-> Rhombus). But the language core mechanisms are still there. I'm a fan of the s-expression syntax, but I've also heard&read from many people (incl. McCarthy), that THEY preferred a different syntax. I've seen Apple defining Dylan (Dynamic Language) with an s-expression syntax and then changing the language to a different syntax for broader adoption. You (and me) think it is essential. McCarthy and others thought that it was the wrong syntax for getting wider adoption.

Btw., personally, I don't care that much what Rich Hickey says. I can think for myself.

1 comments

It is fallacious to suggest that in order to have generic iteration that supports non-list objects, we must abandon the classic list processing functions and give them alternative names and behaviors.

In the TXR Lisp dialect, classic functions like mapcar iterate over nonlists, without losing a shred of backward compatibility over lists.

For instance, we can iterate starting from an integer, in parallel with iterating over a list:

  1> (mapcar 'cons '(a b c) 0)
  ((a . 0) (b . 1) (c . 2))
What we do is pattern the iteration abstraction after the car/cdr model, so that car/cdr iteration falls out as a straightforward special case.

To do this we define an iteration API with four operations:

  iter-begin: construct the iterator from the sequence object
  iter-more: test the iterator whether it has more elements
  iter-item: if iter-more tested true, get the first item
  iter-step: calculate iterator of rest of sequence
iter-step may be functional or destructive, so the caller must capture the new iterator returned as a value and must stop using the old one.

Integer:

  1> (iter-begin 0)   ;; identity
  0
  2> (iter-more 0)    ;; true function: ignores argument, returns t.
  t
  3> (iter-item 0)    ;; identity
  0
  4> (iter-step 0)    ;; successor function
  1
String:

  5> (iter-begin "abc")   ;; opaque iterator returned
  #<seq-iter: a0bef50>
  6> (iter-more *5)
  t
  7> (iter-item *5)
  #\a
  8> (iter-step *5)       ;; destructively stepped
  #<seq-iter: a0bef50>
  9> (iter-item *8)       ;; let's refer to *8 anyway
  #\b
List:

  10> (iter-begin '(1 2 3))   ;; identity, like in integer case
  (1 2 3)
  11> (iter-more '(1 2 3))    ;; not-equal-to-nil test
  t
  12> (iter-item '(1 2 3))    ;; car
  1
  13> (iter-step '(1 2 3))    ;; cdr with check
  (2 3)
  14> (iter-step '(1 . 2))    ;; demo of check
  ** iter-step: 2 is not a cons
Without the check in (iter-step '(1 . 2)) we would get 2, and that would then iterate through 2, 3, 4, ...