5 ms·
> (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 t
by 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.
- lisper 2y agoYes, that's right, but you have missed the point. In McCarthy's Lisp, functions were lists whose first element was the symbol LAMBDA. In Bel, functions are lists whose first element is LIT and whose second element is CLO. But the details of what is in those lists is irrelevant. The point is, in both langauges, functions are lists. You can call CAR on a function and get a result. In McCarthy's Lisp, that result will be LAMBDA and in Bel it will be LIT. If you call CAR on a function in a modern Lisp you will get an error. ? (car (lambda () t)) > Error: The value #<Anonymous Function #x302000E7B61F> is not of the expected type LIST. Contrast with: ? (car '(lambda () t)) LAMBDA In addition, there is a special form in BEL called FN which, when evaluated, produces a function, i.e. a list whose first element is LIT and whose second element is CLO. McCarthy's original lisp had no such function. The special handling of functions, i.e. lists starting with LAMBDA, was hard-coded into the definition of EVAL. But that is also an irrelevant detail.
- kazinator 2y agoWhat you want in this kind of situation is for those symbols to be internal objects that cannot be written. Or perhaps symbols in a private system package, e.g.: (sys:lit sys:clo nil (x) (+ x 1)) No program using symbols in the ordinary namespace will produce this object by accident. It has to use the sys: stuff and when it does that, the language specification can say that it's sticking the proverbial fork into the proverbial toaster.
- lisper 2y agoThat doesn't help at all. These symbols don't have to be produced by the reader. All you need to do to get access to these symbols is to call FN once. That gives you a list whose first element is LIT and second element is CLO. So all you need to "stick a fork" in the Bel toaster is to be able to call FN and XAR.
- kazinator 2y agoYes. In a nutshell, the problem is that (consp x) being true does not rule out (functionp x), which it should. (Unless consp is hacked in an unspeakable way.) In a real implementation, you'd want a new kind of cons cell with a separate type tag so that it fails consp. It's okay if car and cdr like it.
- lisper 2y ago> (consp x) being true does not rule out (functionp x), which it should Exactly. That's what "punning lists" means. > It's okay if car and cdr like it. That's arguable. But the real problem is if XAR and XDR accept it. Functions, however they are implemented, should not be mutable. That way lies madness.