libera/#commonlisp - IRC Chatlog
Search
8:16:37
Krystof
I should go to work, but: I think there's a case that keyword arguments should be tested for in the expanded code, not in the macro function
8:16:53
Krystof
so for pushnew, that's fairly easy because there's a natural expansion for pushnew in terms of adjoin
8:17:34
Krystof
for things like (with-open-stream (s ...) ...) you have to imagine a notional "(defun call-with-open-stream (s &key ...) ...)" even if that's not how you're actually implementing it
8:22:45
beach
Ah, yes, I see. That's in fact a good way to implement it. Then the code for checking the keyword arguments would be in one place, in the compiler for functions.
12:16:29
beach
So (defmacro foo (bar &key baz) `(list ,bar ,baz)) and then (let ((x :baz)) (foo 22 x 33)) signals an error in SBCL.
12:39:31
jackdaniel
how can you parametrize a macro with keyword arguments if they are allowed to be available only at the runtime (i.e they are not constantp at compile time)?
12:41:26
beach
I just can't see how both those examples could be correct. And I don't recall reading anything in the standard that suggests that one or the other is incorrect.
12:43:23
jackdaniel
defmacro specification says: "The parameter variables in lambda-list are bound to destructured portions of the macro call.", how can they be bound if we accept that they are not constant so they are available only at runtime?
12:45:40
phoe
"If the operator names a macro, its associated macro function is applied to the entire form and the result of that application is used in place of the original form."
12:46:22
jackdaniel
I can see that some macros could do something like (defmacro foo ((&rest args) &body body) `(call-with-foo (lambda () ,@body) ,@args))), but in this case the parameter args is not further destructured, so it may have arbitrary (runtime-available) keys
12:47:51
jackdaniel
phoe: I don't see the contradiction - it does not say that you apply an evaluated form (and that would be in fact rather impossible at compile time)
12:51:07
jackdaniel
if a macro /implementation/ accepts some wildcard "args", then it may pass it forward without destructuring. if the macro lists keys then they must be destructured at compile time
12:51:26
jackdaniel
as of why sbcl's pushnew accepts runtime arguments it is implicit from the definition here https://github.com/search?q=repo%3Asbcl%2Fsbcl%20defmacro%20pushnew&type=code
12:52:54
jackdaniel
that's why I've said /implementation/ - you could argue that what sbcl does is a bug
12:53:33
jackdaniel
but on the defmacro level these things seem clear - form is expected to be destructured at compile time against the /actual/ macro lambda list
12:53:34
beach
Oh, I know what SBCL does. But that's not what I am interested in. I am interested in what is conforming behavior.
12:56:26
beach
I was looking for: "if a macro /implementation/ accepts some wildcard "args", then it may pass it forward without destructuring. if the macro lists keys then they must be destructured at compile time"
12:56:44
beach
and "form is expected to be destructured at compile time against the /actual/ macro lambda list"
12:58:15
jackdaniel
I think that with such attitude this is going nowhere, so I'll just get back to whatever I was doing until now.
13:01:03
jackdaniel
I wouldn't say that sarcasm is wrong, but it is not the most productive approach
13:01:13
phoe
I think that jackdaniel paraphrased the spec, and beach was looking for the parts of the standard that are the sources of this paraphrase
13:02:09
scymtym
this is pretty weak evidence but the definition of WITH-OPEN-FILE avoids keyword parameters in the macro lambda list and explicitly delegates the keyword processing to OPEN: https://novaspec.org/cl/f_with-open-file
13:02:43
phoe
(and, from what I know beach, he's not sarcastic, he's just getting more and more focused on the task at hand with each passing year)
13:04:11
beach
scymtym: And that's also what SBCL PUSHNEW does. But if the lambda list has to be destructured at compile time, and the keywords must be present in the macro call form as such, then that approach is wrong.
13:04:51
scymtym
beach: i think he mentioned WITH-OPEN-STREAM which does not involve keyword parameters. WITH-OPEN-FILE may be interesting because it does involve keyword parameter and also explicitly discusses the delegation to OPEN
13:06:12
beach
scymtym: Is that discussion in the standard or in the SBCL implementation of WITH-OPEN-FILE?
13:06:35
scymtym
beach: right, i got that. i meant that the way WITH-OPEN-STREAM is defined is weak evidence that delegating to ADJOIN is indeed incorrect for PUSHNEW
13:06:46
contrapunctus
Is there a library like this for Common Lisp? I looked through awesome-cl and Cliki, but didn't find anything. https://wiki.call-cc.org/eggref/5/fmt
13:07:00
phoe
beach: it's in the standard page for WITH-OPEN-FILE: "OPTIONS are used as keyword arguments to OPEN"
13:08:17
phoe
contrapunctus: this looks like cl:format except on steroids, with the format control being a s-expression-esque DSL rather than a string
13:09:15
beach
OK, so back to square one. The good news is that my implementation of PARSE-MACRO does the right thing and destructures at macro-expansion time.
13:09:43
scymtym
beach: it would be better to derive a conclusion from the specified evaluation semantics for macro lambda lists, of course. that's why i called the above weak evidence
13:12:13
beach
Thanks again for this discussion. This is more evidence that we need this website that I have been referring to as "Common Lisp for language implementers".
13:13:43
phoe
the invention of printing has put many scribes out of their jobs, this is why almost nobody uses CL:WRITE anymore
13:56:29
beach
knusbaum: Me? Yes, indirectly. I am extracting (and often rewriting) SICL modules to separate libraries.
13:57:07
beach
Constrictor is the extraction (and almost complete rewrite) of the SICL Conses module.
14:25:16
knusbaum
That's too bad. It's been on my radar for a very long time. How much of the standard is implemented now?
14:26:25
beach
Yes, so there is a lot of code now that could (and should) be delegated to external libraries, so that's what I am working on.
14:26:54
beach
Plus, scymtym is working on the s-expression-syntax library, which will make it possible to delete lots of SICL code.
14:35:20
beach
So, for instance, for SICL, I took the portable conditions system that phoe wrote, and modified it to be an "intrinsic" system, but what I now want to do is to create a separate library with phoe's code, so that it can be configured to be either "extrinsic" (pretty much phoe's code) or "intrinsic" (so that it can be use in a new implementation). Right now, it is just my version of some of phoe's stuff, and it is not pretty.
15:05:37
phoe
;; note: I didn't fully write it myself, I merely adapted and modernized the original sources that Kent Pitman wrote
15:19:04
beach
Basically "extrinsic" = "cross", i.e., something that can be loaded into an implementation that already has its own implementation of the same thing. And "intrinsic" means native to an implementation, presumably one that is being created.
15:20:04
beach
I came up with those terms. They are not ideal, but I couldn't think of anything better. I mean "cross" is not an adjective, at least not with the right meaning.
15:24:03
knusbaum
I see. Would the extrinsic version replace the existing implementation, or would you have to reference it explicitly with, like, (myconditions:define-condition ...)
15:26:13
beach
Other Common Lisp implementations already have their own versions and don't particularly want to change. Plus, their bootstrapping techniques probably won't allow the use of the intrinsic versions we write now.
15:26:50
beach
I mentioned Clasp, because Bike seems to be moving in the direction of the SICL bootstrapping technique.
15:31:03
beach
Clasp can do it because the entire idea with Clasp is interoperability with C++, and the official LLVM API is in C++.
15:32:05
beach
Plus, apparently LLVM is very slow. Not the code it generates, but the code that does the generation.
15:32:46
beach
Both kind of. The VM is defined in terms of intermediate code, but we then generate machine code.
15:33:30
beach
It shouldn't be surprising that LLVM is slow really. As I have often pointed out, it is impossible to write a C++ program that is both modular and fast. They must have chosen modular.
15:52:14
knusbaum
I'm finding it very weird that prepare-statement will return cached instances, since they are stateful and if two things use the same statement at once it ruins the results for both.
15:55:40
knusbaum
hmm, actually it looks like they don't go in the cash until they're "finalized". I must have done something dumb, it's working as expected now.
16:20:17
semz
Does a form have to be a tree or does a DAG suffice? I know cyclic forms are an express ticket to hell, but is something like e.g. (let ((foo #1=(make-foo #| lots of options here |#))) (lambda () (when (bar) (setf foo #1#)) (baz foo))) legal?
16:21:37
beach
We had that discussion the other day with pjb and didn't come to any conclusion, other than that it is unlikely that the compiler will check for sharing, so it will probably work.
16:35:22
phoe
like, I don't think the specification says anything about the compiler or evaluator being allowed to behave in non-obvious manners upon encountering forms that are EQ to one another