freenode/#lisp - IRC Chatlog
Search
8:46:08
myrmidon
Hi! I'm trying to make a macro produce a backtick list with some ,@(when ...) forms in it, but all I can get is ,(when ...) forms: https://ptpb.pw/PVsQ/lisp -- any advice?
8:54:39
no-defun-allowed
double backquotes aren't my strong point but i think you'd need to backquote-splice twice
8:59:01
jackdaniel
you may splice it shallow or deep and even CL implementations are not consistent here
9:00:49
jackdaniel
if you are interested in details, check out this thread: http://web.archive.org/web/20130622010232/http://sourceforge.net/p/ecls/bugs/251/
9:04:59
aeth
At this point I'd just use helper functions or at least move most of it to a let at the top to try to make it a little readable
9:06:24
aeth
When the macro gets complicated I tend to do (let ((some-piece `(foo ,(bar 42) baz)) (another-piece ...)) ...)
9:06:40
aeth
At the very least, even if it doesn't help too much with readability, you avoid most ,,s that way
9:08:26
aeth
Whether it makes more sense in a helper function or a let at the top (or both, where the let at the top is just calling a function) is hard to say, of course.
9:10:09
myrmidon
,@(append ,@(...)) is working but I think you're right it's a bit messy, i'll try to rework it
9:39:09
makomo
jackdaniel: i've read the thread you linked but i don't get how ``(,@,@foo) corresponds to the `,@foo case which is undefined
9:46:38
makomo
jackdaniel: right, but that's kinda "handwavy", as it's not how it is formally defined, no?
9:46:53
jackdaniel
I don't have time to discuss it right now, sorry. I have said everything I had to say.
9:47:38
makomo
jackdaniel: ah, ok. i'm just interested in interpreting the formal rules that the spec gives fpr backquote and figuring out exactly where it fails
9:47:55
makomo
jackdaniel: if you come up with an idea, let me know (and i'll do the same if i figure it out)
9:48:17
jackdaniel
I think that all there is about ,@,@ is covered in this thread, so I find hard to add anything to it
9:49:39
makomo
jackdaniel: ahhh never mind, i see it now. you have to do the expansion by hand using the formal rules to see it
10:07:42
makomo
jackdaniel: hm, i said that too quickly, without actually doing it by hand but just thinking that it would surely show up
10:08:31
makomo
jackdaniel: however, regarding your ",@foo is defined, if foo is a list", take this example "(let ((var 10)) `(,@var))"
10:09:58
makomo
afaict, that is a valid backquote template according to the formal rules, because, even though the final forms are implementation-defined, the semantics still have to match with the forms that are used in the formal rules
10:11:00
makomo
using the formal rules, the above expands into "(let ((var 10)) (append var))" which is valid, because APPEND takes any object as its last argument
10:12:03
makomo
jackdaniel: using these rules: http://www.lispworks.com/documentation/lw70/CLHS/Body/02_df.htm
10:12:30
makomo
the bullet "* `(x1 x2 x3 ... xn . atom) may be interpreted to mean (append [ x1] [ x2] [ x3] ... [ xn] (quote atom)) (...)"
10:14:17
makomo
the spec says "`#(x1 x2 x3 ... xn) may be interpreted to mean (apply #'vector `(x1 x2 x3 ... xn))"
10:14:23
jackdaniel
I don't see direct implication on `(,@var) -> (append var), in fact evaluating `(,@3) gives me three, not (append 3)
10:14:50
makomo
jackdaniel: evaluating, yes, but i was talking about the "expansion", i.e. what the backquote template is read in (using the forms given in the standard)
10:15:26
jackdaniel
OK, as I said I have no time to dive into spec. it is not that I disagree or anything, I've just pointed out that ,@,@ is undefined since I saw it
10:15:55
jackdaniel
(I know that I'm not physically forced to discuss that, but all these highlights certainly make me feel so)
10:16:54
makomo
jackdaniel: sorry if i was being a bother, i won't ping you anymore :-). but yeah, if you get the time in the future, let me know
10:17:34
jackdaniel
I want to point out, that I'm not also especially interested in discussing such things unless it is a mean towards implementing something correctly
10:17:57
jackdaniel
I can spend such time on other thigns (also beneficial to CL community), like fixing bugs
10:19:10
makomo
jackdaniel: sure, i understand. s/if you get the time/if you feel like discussing it/ is what i meant :-)
11:35:15
pjb
makomo: on 2.4.6, 4th star (*), [,@form] is interpreted as form. `(foo `(x1 ,@,@form x3)) --> `(foo (x1 ,@form x3)) ; seems legit to me. (let ((form '((1) (2) (3)))) `(foo `(x1 ,@,@form x3))) #| --> (foo (list* 'x1 (append (1) (2) (3) '(x3)))) |#
11:36:37
makomo
pjb: can you perform the expansion bit by bit and show the intermediate results? the thread that jackdaniel linked says that the behavior of ,@,@ is undefined
11:37:06
pjb
makomo: I don't think it's undefined. clhs 2.4.6 has a rule for it, which means that: `(foo `(x1 ,@,@form x3)) --> `(foo (x1 ,@form x3))
11:37:21
pjb
therefore ccl evaluating successfully this form: (let ((form '((1) (2) (3)))) `(foo `(x1 ,@,@form x3))) #| --> (foo (list* 'x1 (append (1) (2) (3) '(x3)))) |#
11:37:42
pjb
seems to confirm that there's a meaning for it, and given it's specified, it seems to be conforming.
11:37:51
makomo
pjb: you can't just collapse it like it. i think you're reading it out of context -- read all of the rules for `(...)
11:38:15
makomo
this one "* `(x1 x2 x3 ... xn . atom) may be interpreted to mean(append [ x1] [ x2] [ x3] ... [ xn] (quote atom))"
11:39:32
makomo
therefore, ``(hello ,@,@there) == `(append (list `hello) ,@there) == `(append (list 'hello) ,@there) == `(append (list `append) (list `(list 'hello) there), no?
11:39:59
makomo
but that's not the result i expected. i expected a `,@foo to show up, which is undefined by bullet 3
11:40:04
pjb
(quote `(foo `(x1 ,@,@form x3))) #| --> (list* 'foo (list (list* 'list* (list* ''x1 (list (list* 'append (append form '('(x3))))))))) |#
11:42:50
makomo
but hm, yeah, i guess it might be wrong, because i can't see what's undefined about it (**using the formal rules!**)
11:45:46
makomo
i do it in small steps, fully expanding all the inner ` before going onto the outer `
11:46:42
makomo
that's how the algorithm works anyway, except it does it recursively. because we're humans, i prefer to do it iteratively. the result is the same, as the innermost backquote is always fully expanded before the outermost one
12:05:48
pjb
(let ((there '((list :x 1) (list :y 2)))) ``(hello ,@,@there)) #| --> (list* 'hello (list :x 1) (list :y 2)) |#
12:06:44
pjb
(list* a d) = (cons a d) (list* a1 a2 a3 .. an d) = (cons a1 (cons a2 (cons a3 … (cons an d))))
12:08:49
pjb
(APPEND (LIST 'HELLO) (LIST :X 1) (LIST :Y 2)) #| --> (hello :x 1 :y 2) |# same result.
12:09:22
pjb
(eval (let ((there '((list :x 1) (list :y 2)))) ``(hello ,@,@there))) #| --> (hello (:x 1) :y 2) |#
12:09:54
pjb
(eval (let ((there '((list :x 1) (list :y 2)))) ``(hello ,@,@there foo))) #| --> (hello :x 1 :y 2 foo) |#
12:10:01
pjb
(let ((there '((list :x 1) (list :y 2)))) ``(hello ,@,@there foo)) #| --> (list* 'hello (append (list :x 1) (list :y 2) '(foo))) |#
12:10:28
pjb
(let ((there '((list :x 1) (list :y 2)))) ``(hello ,@,@there)) #| --> (list* 'hello (list :x 1) (list :y 2)) |#
12:11:15
pjb
(let ((there '((list :x 1) (list :y 2) nil))) ``(hello ,@,@there)) #| --> (list* 'hello (list :x 1) (list :y 2) nil)|#
12:12:24
pjb
Yes, because (append [ x1] [ x2] [ x3] ... [ xn] (quote atom)) means that xn is not the last argument to append. If you have a proper list, then atom is nil.
12:12:54
pjb
So (let ((there '((list :x 1) (list :y 2)))) ``(hello ,@,@there)) should be the same as (let ((there '((list :x 1) (list :y 2) nil))) ``(hello ,@,@there))
12:13:07
pjb
(values (eval (let ((there '((list :x 1) (list :y 2)))) ``(hello ,@,@there))) (eval (let ((there '((list :x 1) (list :y 2) nil))) ``(hello ,@,@there)))) #| --> (hello (:x 1) :y 2) ; (hello (:x 1) (:y 2)) |#
12:13:55
makomo
i've been forgetting about that (quote atom) (or rather (quote nil)) at the end this whole time
12:23:32
pjb
Either formally, or fundamentaly like in this case. Formally in the case of prog2, implementations don't do what's written but what was meant.
12:26:22
flip214
the first has a CDR of NIL, the second has a _list_element_ of NIL (with a CDR of NIL, too)
12:26:44
makomo
flip214: i'm only following the rules given by http://www.lispworks.com/documentation/HyperSpec/Body/02_df.htm
12:26:56
flip214
and my experiments some time ago showed me that ,@,@ is most often wrong - ,',@ is sane ;)
12:27:47
flip214
pjb: makomo: well, AFAIK the CLHS isn't the final standard - and even if it were, it might contain errors.
12:28:17
makomo
flip214: well, that's just speculation i guess. these formal rules have been described by Steele as well
12:28:51
makomo
i agree the standard isn't pefect, but this section in particular being wrong seems highly unlikely to me
12:30:32
flip214
and the first form replaces the last CDR by NIL (which it already was), and so returns the same thing. got ya.
12:39:52
makomo
pjb: ah nice, i was just about to ask whether you were going to open another issue for the `(,@var) thing
12:41:53
makomo
if ccl goes with the changes then i might do it, because i'll have more evidence to point to
12:47:19
makomo
"first it has all the bugs straightened out, including dark corner cases (some implementations still get the simple ``(foo ,@,@bar) wrong);"
13:11:18
russellw
I don't suppose there is anything like a way to tell loop to do one more iteration? Specifically, I'm trying to implement a read-line function as something along the lines of (loop until(eql(peek-char #\newline)) collect(read-char)) but then that doesn't collect the actual newline
13:17:04
makomo
`(,@foo) is technically incorrect but fare-quasiquote accepts it by default in the name of interoperability and consensus. there's a feature you can use to make it signal an error
13:18:08
makomo
jackdaniel: just to let you know: we concluded that ,@,@var is well-defined defined but that `(,@var) is not (contrary to what i said the first time -- i forgot the ". nil")
14:12:32
jackdaniel
and despite reading whole thread I didn't change my mind, but I'm not motivated enough to defend that claim
14:17:21
jackdaniel
it is because a) it is the last argument, b) all preceding lists are null (and dragons and whatever), because it is an empty cave of knights ;-)
14:31:37
makomo
jackdaniel: yeah, true, and that is why `(,@10) => 10 is incorrect. `(,@foo) actually reduces to `(,@foo . nil) which then expands into (append foo 'nil)
14:31:57
makomo
since foo is 10, that APPEND call should fail, but it seems like most implementations have broken backquote simplifiers
14:38:17
beach
The SICL implementation of the macro ECLECTOR.READER:QUASIQUOTE expands the form returned by Eclector to (APPEND 10 'NIL)
14:38:32
jackdaniel
"If a comma is immediately followed by an at-sign, then the form following the at-sign is evaluate" – that means that defined behavior applies only to at-signs followed by forms. and I'm not diving into that discussion any further, I kind of regret that I said anything about ,@,@ earlier. If I'm wrong - so be it.
14:41:54
makomo
jackdaniel: yes, right, but that applies to a single level of backquote. n nested backquotes require n evaluations to fully process. the spec is at all times talking about a single level of quotation, and the rest have to be handled recursively
14:43:32
jackdaniel
does anyone know dejavu ttf fonts which have vmtx table defined? (for testing font renderer)
14:44:33
makomo
beach: and what about (let ((there '((list :x 1) (list :y 2)))) ``(hello ,@,@there))?
14:45:05
makomo
woop,s you'll have to evaluate the result of that once again to get the final result
14:48:19
beach
It's interesting how I can evaluate SICL code even though SICL doesn't exist, isn't it? :)
14:51:41
makomo
beach: speaking of bootstrapping. CL has various functions which are primitives and cannot really be implemented by the user. stuff such as CAR, CDR, APPLY, +, -, etc. now, thinking about meta-circular interpreters, would it ever be possible to write an interpreter for a language L in L, but without relying on L's primitives?
14:53:31
Bike
you can implement lisp in lisp without using host lisp structures to represent client lisp structures.
14:53:34
makomo
ggole: hm, but let's say we take + for example. how would you avoid using + within the interpreter itself?
14:53:47
russellw
makomo, sure, you could reimplement numbers using church numerals or whatever. It's just that it would be very slow
14:54:05
makomo
russellw: aha, that's what came to my mind to, but wouldn't you still have to rely on "incrementing" somewhere?
14:55:02
Bike
the client would only be able to access them as client numbers, though. non porous abstraction
14:55:13
ggole
And within the implementation of object-language primitives, you could use + (if the semantics were correct)
14:56:02
beach
makomo: You can't avoid using host functions for the interpreter itself. You have to have access to the computation machinery.
14:56:05
Bike
einstein thought about the dude with a flashlight because ehe was wondering about relativity
14:56:21
makomo
Bike: yeah, i'm trying to sort out the meaning of "meta-circular" from the various subtly conflicting definitions i've read
14:56:24
ggole
Programming without certain primitives is possible up to a point, but you need to encode your logic into something in the host language
14:56:47
makomo
ggole: mhm, true, but i just want to avoid using the exact same primitive to implement the feature of the object language
14:57:57
Bike
i mean the client lisp will be unable to treat church numerals except as numbers. it won't be able to FUNCALL them or anything.
14:58:26
makomo
Bike: and as another example, let's take closures. these would also be implementable without using host's closure, but using a separate "hand-written" data structure, right?
14:59:08
beach
makomo: You would have a representation of a function as a structure containing "code" and "environment".
14:59:13
Bike
well, it might use host closures internally, depending on how the implementation works, but it doesn't have to BE a host closure
14:59:49
makomo
ggole: right, true. in this case i'm using L to implement L (L being Lisp in this example), but of course, you could implement Lisp in assembler and assembler obviously doesn't have closures
15:00:13
ggole
The object language should not be able to tell the difference (except in operational senses such as time taken)
15:00:38
Bike
if you can implement lisp in assembler you're not using lisp functions, so there's no way it would be required to use lisp functions.
15:01:34
makomo
i mean, wouldn't using assembler's INC or ADD (assuming some common assembler) qualify as circular? i'm not sure
15:04:27
makomo
we've talked about this before, what i really want to do is figure out why the name is "meta-circular" and not just "circular". i've come to the conclusion that (1) it's "meta" because it's L implementing L and (2) it's "circular" because you're reusing the host's primitives to implement the object's primitives
15:04:55
makomo
i could throw away the circularity and just have an L implemented in L, a "metainterpreter" i guess
15:05:00
Bike
i hope you realize there's a decent chance it's "metacircular" because a mildly drunk programmer thought it sounded cooler.
15:05:17
beach
Maybe you are putting too much interpretation into a name that might have been chosen quite arbitrarily.
15:05:44
Bike
"The term itself was coined by John C. Reynolds, and popularized through its use in the book [SICP]" so maybe there's an explanation, i don't remember.
15:06:13
makomo
Bike: sicp does mention it (of course), but it's like there's an implicit assumption that the implementation reuses host's primitives
15:06:40
Bike
that's just because it's what sicp is about. it should be obvious it's not required or programming would be impossible.
15:07:03
beach
makomo: I don't think the term is sufficiently well defined to determine whether using host primitives is acceptable.
15:07:09
Bike
as far as i remember, as sicp goes on the host-client link gets more and more distant.
15:07:19
makomo
4.1 says "An evaluator that is written in the same language that it evaluates is said to be metacircular."
15:14:54
makomo
Bike: that paper explicitly mentions the circularity part, "We have coined the word “meta-circular” to indicate the basic character of this interpreter: It defines each feature of the defined language by using the corresponding feature of the defining language."
17:14:27
jcowan
can anyone talk about practical examples of degenerate arrays, either of rank 0 or of no elements?