5 ms·
I think one reason to add characters and streams is so you can implement read and print, the R and the P in a Lisp REPL. The original Lisp assumes s-expressions
by akkartik 2y ago
I think one reason to add characters and streams is so you can implement read and print, the R and the P in a Lisp REPL. The original Lisp assumes s-expressions are given, but provides no mechanism for creating them out of characters read from keyboard or printed to screen. Bel is taking the same axiomatic approach of the original Lisp but to a more realistic system.
Similarly, ccc exists so onerr can exist, which exists so saferead can exist, which exists so the REPL can show errors on screen.
That hangs together for me. But I still don't understand the distinction you're making between representing as lists vs being lists.
- lisper 2y ago> so the REPL can show errors on screen And how do you formalize the screen? (BTW, this is just speculation on your part. The word "screen" doesn't actually appear anywhere in the article.) You can't have it both ways. Either you are going to formalize everything, or you're going to punt at some point and yield to practical considerations. And formalizing I/O is particularly hard. > I still don't understand the distinction you're making between representing as lists vs being lists. (lambda () t) is a list. In McCarthy's original lisp, as in Bel, this list IS a function. This would work: (setq l '(lambda () t)) (l) --> T But in modern Lisps you have to EVALUATE this list in order to get a function that you can call. In Scheme: ts> (define l '(lambda () #t)) l ts> l (lambda () #t) ts> (l) Error: illegal function ts> (define p (eval l)) p ts> p #<CLOSURE> ts> (p) #t ts> (procedure? l) #f ts> (procedure? p) #t ts> (list? l) #t ts> (list? p) #f
- akkartik 2y ago> (lambda () t) is a list. This is not right, and it's a very basic thing to get wrong. I don't think you understand what you're criticizing. Even replacing the Bel name, this is not right: > (fn () t) is a list You _do_ have to eval it. bel> (eval '(fn () t)) (lit clo nil () t) I see the returned list as akin to a serialization format. It's an s-expression rather than some opaque representation that can't be printed. That seems nice, more debuggable. I don't see what makes it harder to compile than an opaque representation. You can compile it just fine, you're just carrying around the source code in say a debug segment of the image. > (BTW, this is just speculation on your part. The word "screen" doesn't actually appear anywhere in the article.) Look, you asked what the point of streams was. I pointed out what the metacircular source code does with streams. If someone asks what the purpose of stdout is in Unix, it seems reasonable (and a hoary tradition) to justify it in terms of printing to screen. stdout is about much more than a screen, but "screen" is an easy answer to "why does my program need stdout?"
- lisper 2y ago> I don't think you understand what you're criticizing. Oh, I'm pretty sure I do. Functions are represented using lists. For example, here is a function that takes one argument, and returns that plus 1. (lit clo nil (x) (+ x 1)) The first element, lit, says that this is a literal object, not to be evaluated.
- akkartik 2y agoI don't know where the disconnect is, but I'll stop here. The statement you just quoted disagrees with what you said on two occasions before: > It's fine to represent functions as lists, but having functions actually be lists rather than a first-class primitive is a huge mistake. > (lambda () t) is a list You said this would work in Bel: (setq l '(lambda () t)) (l) --> T This is false even after fixing the Bel names for things.
- lisper 2y agoThe disconnect is that PG misuses the word "represented". Functions in Bel are not just represented as lists, they are lists. Specifically, they are lists whose first element is the symbol LIT and whose second element is the symbol CLO. Functions can also be represented as lists that start with the symbol FN. You would not ordinarily express a function using its literal representation. Usually you'd say (fn (x) (+ x 1)) which yields the function above. [i.e. (lit clo nil (x) (+ x 1))] So a list that starts with FN represents a function, but it is not a function. It has to be evaluated to produce a function, but the function that it produces is just another list, one which starts with LIT rather than FN.
- akkartik 2y agoIn Bel you have to eval (fn (x) (+ x 1)) before you can call it. Do you agree? Following your terms in https://news.ycombinator.com/item?id=40409467 https://news.ycombinator.com/item?id=40409467, in this respect Bel feels like a modern lisp. In other words, this quoted passage of yours is not correct: (lambda () t) is a list. In McCarthy's original lisp, as in Bel, this list IS a function. This would work: (setq l '(lambda () t)) (l) --> T This would not work in Bel.
- kazinator 2y agoWhy would you need read and print in a language that isn't yet intended to program computers? You don't need I/O in order to describe input and output in an abstract language. Literals, including quoted lists, are enough to encode input into the program as part of its body. The result of a function can be described using a notation like (+ 2 2) -> 4. It's not actually running so nothing needs to print that.