freenode/#lisp - IRC Chatlog
Search
21:03:20
elderK
I'm just trying to... match things up. I mean, how can reading be completely independent from... stuff. It can't just be a "typical lexer / scanner" because macro characters require us to invoke some function, that is potentially set by user.
21:03:47
elderK
so, in an interpreter, that would require us to then interpret that macro function so to continue the read.
21:07:29
Bike
and funcall doesn't need to invoke the reader in any way (unless you're calling, like, READ itself)
21:08:00
no-defun-allowed
All reasonable Lisps use recursive descent which makes these things quite trivial.
21:08:58
elderK
Bike: Right. But that implies that we can somehow "funcall" a function. Which means we need to have been able to read it, and somehow store it in a form we can call.
21:09:57
elderK
Yes, but the only way it could be there in memory, the function, is if we already read it, no?
21:10:13
no-defun-allowed
It's more appropriate than lexing/parsing, and I've heard it called that before.
21:11:27
Xach
elderK: it would still be pretty normal to separate reading and evaluation in not-lisp
21:11:48
no-defun-allowed
For example, the Unix Hater's Handbook compares it to the contextual grammar of C++, calling Lisp's parser "recursive descent, meaning you can write it on a piece of paper" from memory.
21:12:09
elderK
no-defun-allowed: There's parsing, then there's lexing. to me, they are independent.
21:12:16
Xach
evaluation is what makes the system do stuff, like create function objects and maybe associate them with a global name.
21:13:00
elderK
Bike: Right. My main problem isn't with the fact that, lexing/parsing is basically "all in one." I've seen lexerless parsers.
21:14:10
Bike
being "dynamic" pretty much just means the table is an object in memory rather than an off-line thing.
21:14:55
elderK
Yeah, I get that. I'm just thinking of the necessity to have some way to actually read code in the first place, so that the user's code that sets a new reader macr-function can be understood and patched in :P
21:16:34
elderK
Bike: Which is to say, when you start the Lisp implementation - say from the standard image - everything is in place to read and understand standard Lisp. If it reads stuff, evaluates stuff, that changes that, well, okay, because it started off with the base syntax.
21:21:33
elderK
I really want to learn how to make a lisp implementation. Toy to start with, but increasing complex and non-toy-ish.
21:21:47
elderK
But I'm not really sure how to best start. Finishing LiSP and studying RABBIT, maybe,
21:23:21
Xach
elderK: Lisp in Small Pieces is a good book on the topic. i like the progression it follows from simple to complicated
21:23:45
Bike
i mean a basic metacircular interpreter is like a page long, if you just have scheme special oeprators
21:24:38
elderK
:) I wonder if I can do like, all the stuff it covers, but in CL rather than Scheme.
21:25:51
elderK
I also need to learn how to do ... like, usual lexing in Lisp. I'm used to implementing lexers in C using transition tables and stuff. Basically state[current_state][input_category] is the next state.
22:37:25
pjb
elderK: about *readtable* and reader macros, note that *readtable* is a special variable, therefore it has dynamic scope. lexical = WHERE, dynamic = WHEN. So the question is WHEN the reader macro is executed, what binding has the *readtable*. Of course, if the reader macro function is called thru the *readtable*, by reading the macro character, at that time, the *readtable* is bound to the readtable that contains the mapping of
22:38:08
pjb
elderK: and once the reader macro function is executing, nothing prevents you to bind *readtable* to another readtable!
22:38:49
pjb
elderK: for an example of this: https://github.com/informatimago/lisp/blob/master/objcl/objcl.lisp#L88
22:39:36
pjb
Notice how the reader macro functionr ead-objcl-expression binds the *readtable* to *objc-readtable*.
22:40:43
pjb
elderK: the syntax is [object messageWith: (foo) andWith: bar] where messageWith:andWith: must be read case sensitively amongst other things.
22:42:28
pjb
elderK: but if object is not a special identifier super, then it must be read as a lisp expression: [(if foo obj1 obj2) getIt] hence the other binding to *lisp-readtable*.
22:43:56
elderK
pjb: Of course, when the macro function is compiled, the syntax that is in effect... then, is set. Like, just beacuse you change the readtable, doens't mean the macro function suddenly gets recompiled, right?
22:45:20
pjb
White_Flame: it was developed about at the same time. Remember that Fortran was defined earlier tha LISP. Backus and Naur formalized the BNF for ALGOL 58 in 1959.
22:47:32
pjb
elderK: And yes, you can also mutate the readtable bound to *readtable* itself while reading. Ie. you can write a reader macro function that will set macro-chracters while reading.
22:48:58
pjb
White_Flame: However, the syntax of LISP (1959) was very simple. Basically, a lexer to read symbols, strings and numbers, and a parser for the sexp syntax.
22:49:58
pjb
White_Flame: elderK: yep, when the source code is compiler, it's the readtable that is bound to *readtable* in the compilation environment that is used. It can be the standard readtable, or something completely different. For example, if you write your reader macro in vacietis!
22:52:58
pjb
White_Flame: and in CL, the lisp reader is clearly defined in two parts: the basic lisp reader algorithm specifies the lexer (which is a tad more complex than what you'd do in general with lex (but you could do it in lex, there are states)), and then it defines the standard reader macros of which there are two kinds: macros such as #\" scan tokens such as strings, and macros such as #\( parse s-exps. Again, not much syntax here (
23:15:38
buhman
if I had a list of flags, and a flag I wanted to "toggle" by adding it or removing it from the list, is there a fancy way to do that?
23:21:10
pjb
(if (zerop i) (setf (car list) (not (car list))) (let ((cell (nthcdr (1- i) list))) (setf (car cell) (not (car cell))))) is slightly faster.
23:23:58
pjb
(defun neg (x) (if (zerop x) 1 0)) (define-modify-macro negf () neg) (let ((flags (make-array 50 :element-type 'bit :initial-element 0))) (negf (aref flags (random 50))) flags) #| --> #*00000000000000000000000000000000010000000000000000 |#
23:24:51
pjb
Then you could just mutate the list (unless you do it a lot in an inner loop and need the speed).
23:28:17
pjb
(let ((flags (list :carry :zero))) (deletef flags :carry) (pushnew :minus flags) flags) #| --> (:minus :zero) |#
23:29:20
pjb
and you can use find to test: (let ((flags (list :carry :zero))) (deletef flags :carry) (pushnew :minus flags) (values flags (find :carry flags))) #| --> (:minus :zero) ; nil |#
23:30:36
pjb
On the other hand, with bitvectors, you can mask off flags more easily and efficiently than with sets (lists). (intersection flags mask) vs. (bit-and flags mask)
2:01:28
PuercoPop
Does (nth-value 0 ...) has any benefit? Does it make it easier for the compiler to avoid unnecessary allocations?
2:02:56
no-defun-allowed
with (SPEED 3) on sbcl, FLOOR and whatever other int maths you have don't play nice without a VALUES or NTH-VALUE in the middle
2:03:36
no-defun-allowed
see https://gitlab.com/Theemacsshibe/cl-vep/blob/master/outside-world/image.lisp#L9 for example
2:05:30
PuercoPop
no-defun-allowed: I don't see (nth-value 0 ), but I'm guessing the extra (values ) is also a way to 'convince' the compiler that there is only one value
2:07:25
Bike
they are semantically identical, since VALUES is just a normal function and its argument forms have values past the primary discarded.
3:54:22
beach
I know what you mean. But in two weeks it turns again, provided you are on the northern hemisphere, of course.
4:10:42
beach
If anyone is good with LaTeX, I would like to see the dpANS document(s) converted to a single LaTeX file. Any takers?
4:12:40
beach
esper0s: It is just that there is so much to do in the Common Lisp world that I am trying to direct attention to it, in the hopes that some of it will get done by someone other than me.
4:15:26
beach
Now, if we can turn the dpANS into a LaTeX document, we could slowly turn it into a specification of WSCL (which means Well Specified Common Lisp, and is pronounced like "whistle").
4:26:59
beach
I am not complaining though. Lots of good work is getting done on McCLIM on a daily basis by jackdaniel, slyrus, loke, and several others. And I am convinced that McCLIM is going to be an essential part of any end-user application written in only Common Lisp.
5:08:37
no-defun-allowed
erm, i changed phone and my 2fa codes aren't working for gitlab.c-l.net, who should i contact about that?
6:05:17
slyrus
Hrm... That's an awfully big file. Seems to me the source should be lisp s-expressions (in one or many files) from which the LaTeX is generated.
6:09:41
beach
The source code for the dpANS is already TeX (but not LaTeX). Converting it to something else would be an even harder task.
6:11:38
no-defun-allowed
but since there isn't anything too modern like TikZ, i thought it'd be like collecting commands and bracketed things
6:11:52
beach
slyrus: Oh, I am sorry. I didn't mean a single LaTeX source file. I meant a single LaTeX document.
6:12:32
beach
slyrus: Currently, each chapter is a separate document, which makes things like cross referencing and citations hard.
8:12:22
asarch
One stupid question: is, the binary from SBCL, fast enough as any binary from any C/C++ compiler is?
8:38:56
aeth
asarch: You can expect a 3x to 5x slowdown at the worst case, probably for code that a C compiler would heavily optimize, e.g. vectorized code. You're also going to use a lot more RAM (at least 10x as much) and you have different performance tradeoffs with a garbage collector active.
8:40:23
aeth
(Obviously using more RAM won't be 10x as much if you e.g. load a 1 GB PNG file or something. It's not constantly 10x as much.)