libera/#lisp - IRC Chatlog
Search
14:57:59
x8dcc
Hello again. I have changed what you recommended me yesterday. I added an eval_args() function which is equivalent to SICP's list-of-values, and I call it on the arguments from `eval' before passing them to `apply'
14:58:36
x8dcc
However, my `quote' issue still remains. I am having a lot of trouble understanding how quoted expressions are passed through functions.
15:16:40
reb
x8dcc: Have you taken a look at: https://norvig.com/lispy.html The article describes how to write a Lisp interpreter in Python. In Norvig's code various special forms are handled directly by eval, including "if", "lambda", and "quote".
15:46:18
dbotton
https://www.reddit.com/r/lisp/comments/1c6zq1m/quick_start_of_a_game_in_clog_inspired_by_the/
16:39:53
x8dcc
reb: In both versions (lis.py and lispy.py), eval returns expr[1] for quotes. It's consistent with everything I have read about quotes, but I still feel like I am missing some key detail. If (quote +) evaluates to +, why wouldn't ((quote +)) work?
16:40:54
x8dcc
In my head it would evaluate the first element of the list, since it's a quote it would return the symbol + which would be looked up in the environment and found as a primitive
16:42:46
x8dcc
I know it's not the case, but it makes sense to me by looking at how the python example is implemented
16:43:36
reb
It does not because (quote +) evaluates to the symbol +. In the form (+ 1 2) the symbol + evaluates to a built-in function that adds numbers.
16:44:25
x8dcc
But what's different about the symbol + and the one it reads when parsing the second form?
16:46:33
reb
Let's walk through the evaluation of ((quote +) 1 2). The reader reads the text and converts it into a three element list. The elements are (quote x), 1, and 2.
16:47:52
reb
The evaluation rule says evaluate the head element of the list, then evaluate all of the remaining elements, then apply the result of evaluating the head element to the result of evaluating all the remaining elements.
16:52:01
x8dcc
Maybe my whole confusion was born because I thought after evaluating (quote x) to x, x still had to be evaluated... sometimes?
16:52:25
x8dcc
I think I understand more clearly now. I am going to try to implement it without using my expr->is_quote approach
16:57:52
reb
In Scheme the form you wrote above generates an error. ((lambda (x) x) (quote +)) evaluates to the symbol +
16:59:29
x8dcc
Yeah, I realize that, but if you pass it to `apply' it's evaluated again to the primitive
17:00:45
x8dcc
in scheme it evaluates to quote again... is it because it's somehow "simplifying" the identity lambda? I am guessing this is not the case and it's just how it's implemented
17:01:33
x8dcc
but since (quote x) evals to x, I find the first result more logical so I will stick with that
17:22:12
reb
I believe the difference is in how apply handles applying symbol + to the list 1,2,3. With Scheme it's an error. You can't apply symbol + because it's not a function. With Emacs Lisp and Common Lisp apply does something different. It looks up the symbol's "function binding" and uses that.
17:24:06
reb
The difference in behavior is part of the difference between Lisp-1 and Lisp-2 languages. Scheme is a Lisp-1, so symbols have one binding. Most Lisps associate two (or more) values with a symbol, a "normal value" and a "function value".
17:26:32
x8dcc
I see. I did know about Lisp-1 and Lisp-2 languages, but I always thought having a single binding (Lisp-1) was less confusing
17:28:24
reb
I think it is. It makes the evaluation rules simpler and more consistent. With Lisp-2 languages the head position of a list is treated specially when evaluating a list form. So when evaluating (A B C), forms B and C are evaluated one way and A is treated specially.
19:42:16
x8dcc
Now I am also thinking about my `define' function. It currently takes a symbol, which means it has to be quoted when calling it. Should I implement it as a "Special form" like `quote', or as a "wrapper"/macro that quotes the first argument?
19:50:07
aeth
a Lisp-style (define foo () bar) or Scheme-style (define (foo) bar) can assign (lambda () bar) to the global variable foo (if "Lisp-1", shared namespace) or the function name foo (if "Lisp-2", separate function and variable namespaces)
19:52:30
x8dcc
ieure: No, it doesn't have macros. I also have read some of that website but my project is very different. I don't want to use any external libraries and I use very different data structures.
19:53:37
x8dcc
Haven't even thought about macros yet, tbh. I might leave this "issue" for now and keep quoting the symbol. I still have a lot to add :)
19:58:19
aeth
just call it %define and keep quoting, then make your first macro define that exists to essentially unquote the quote as sugar
20:00:08
reb
x8dcc: If you look at Novig's Lisp interpreter you'll see that DEFINE is a special form, implemented directly in the eval procedure.
20:01:52
reb
Basically, whenever a form violates the standard evaluation rules, it needs to be handled specially somewhere, such as in eval ... or by a macro implementation.
21:22:08
x8dcc
For sure better than yesterday. I also bound eval and apply to the environment and it works fine https://dpaste.com/AE5DN477E