libera/#commonlisp - IRC Chatlog
Search
17:27:45
attila_lendvai
phoe, layered methods are just a defmethod with an extra, implicit object, the context, to which you can add and remove classes
17:32:41
Guest74
is there some convention for conditionally defining a method depending on whether a certain system/package is available? I'd like to be able to support all the various colour format libraries out there without loading every single library on a users computer.
17:45:49
Guest74
or is it even possible? I tried a toplevel (when (find-package 'some)(defmethod something((thing some:thing))... and it barfs on package not found.
17:49:58
pjb
Guest74: At read-time: #+#.(cl:if (cl:find-package 'some) '(:and) '(:or)) (defmethod something((thing some:thing))... and)
17:50:37
pjb
Guest74: At run-time: (when (find-package 'some) (eval (read-from-string "(defmethod something ((thing some:thing))...)")))
17:50:45
Guest74
oh, i thought that was only for features, or that was the impression I got from clhs.
17:51:47
pjb
Guest74: an alternative is to also define the package in your system, and test in the method, at run-time whether the dependency is available.
17:52:26
pjb
(defpackage "SOME" (:export "THING")) (defmethod something ((thing some:thing)) (if (some-runtime-test-to-see-if-some-has-been-loaded-p) (do-something) (warn "SOME unavailable")))
17:53:24
pjb
Well, there's some implementation dependent behavior, but in general implementations do the right thing.
17:55:05
pjb
If you test at read-time, you must ensure loading it at compilation time, and at run-time.
17:55:18
Guest74
yes, i've been thinking about that. What if person loads a colour library after my drawing library.
17:55:21
pjb
If you test at run-time, you must ensure it has been loaded at run-time, BEFORE you load you system.
17:59:30
Guest74
I'd say it places more burden on the user for something that feels like it shouldn't be the users burden.
18:00:39
pjb
(when (and (find-package "SOME") (find-symbol "DOSTUFF" "SOME")) (funcall (find-symbol "DOSTUFF" "SOME") :blah))
18:01:46
Guest74
this is different in that's specializing a method on a colour class from some colour library. funcall would be easier.
18:02:03
sm2n
The issue with all the other solutions is that you can have ordering issues, or have unnecessary runtime overhead
18:02:50
sm2n
like, you have a reader conditional and someone loads your library before one of the libraries you support, then it won't work
18:03:46
phoe
is there a portable way to check at macroexpansion time if some piece of code is being compiled via COMPILE or COMPILE-FILE rather than not?
18:04:11
Guest74
I guess I can do one system per library which depends on that library and transforms each colour to a specified format so that any other surfaces get automatic support for those colours.
18:04:27
phoe
COMPILE-FILE binds *COMPILE-FILE-PATHNAME*, so that's easier, but I need to find something COMPILE
18:05:53
pjb
You can do: (let ((*when* 'compile-file)) (compile-file "foo")) (let ((*when* 'compile)) (compile nil (lambda (…) …))) or (let ((*when* 'execute)) (eval '(…)))
18:10:15
phoe
yes, but I want the inverse - to check if a macro is being expanded by a compiler or an interpreter
18:12:22
pjb
Macros can be expanded at different times, and multiple times, so it sounds like a very bad design to depend on that.
18:16:22
phoe
my main gripe is the behavior of LOAD-TIME-VALUE that can differ between evaluated and compiled code
18:16:36
phoe
and I kind of wonder if I can actually depend on this behavior to detect this behavior
18:18:25
Inline
conceptually it sounds like at compile time the compiler would have to delay the init of stuff meant to be at load-time
19:08:41
phoe
I just realized that this can work as a poor man's "was this code minimally compiled" predicate
19:10:56
EdLangley[m]
Guest74: I think the most common way to do this is just to define new systems with names like "a/b" and put the methods in the files loaded by that system.
19:20:01
EdLangley[m]
I don't really like how its internals work, but the interface is something I like: automatically load a system based on the other systems that have been loaded
20:27:35
random-nick
some implementations also add a keyword argument to make-hash-table which makes it thread safe
22:30:21
EdLangley[m]
that is, just use load-time-value without checking and then document that the code has to be compiled to work correctly
22:31:54
phoe
EdLangley[m]: it's possible to (ab)use this behavior to detect code that wasn't minimally compiled and signal an error
22:32:21
phoe
it's very likely not portable and depends on unspecified behavior as you mentioned, but it seems to be reliable enough on modern implementations
22:32:27
EdLangley[m]
But, I think that sort of "defensive programming" in a macro like static-let causes more problems than it would help
22:32:53
EdLangley[m]
It's better, IMO, to document the situations in which static-let fails and just generate normal code
22:33:32
EdLangley[m]
Basically, this means that you can't portably use l-t-v for things like memoization
22:34:41
phoe
yes - thank goodness that ASDF compiles everything by default, so you don't really get to play with interpreted code outside REPLs of these four implementations
22:36:45
Bike
static-let is exactly the kind of thing that i'd expect to not happen in an evaluator, too
22:38:00
Bike
as in, i don't think an evaluator could reasonably be expected to have any kind of "static" semantics
22:38:53
EdLangley[m]
If you want this counter behavior, you should use the let over lambda pattern :)
22:39:24
phoe
EdLangley[m]: not a wrong thing from the perspective of LOAD-TIME-VALUE but a wrong thing from the perspective of an operator whose values are meant to persist across function calls in the same way closure values do
22:42:17
Bike
say, you have a macro function for static-let or whatever that returns the usual form the first time, and on subsequent expansions returns an error form
22:43:14
Bike
clearly you need to introduce another special operator to conditionalize on evaluation/compilation status.
22:44:09
Bike
although that could itself get tricky in situations like when the compiler runs the evaluator
22:44:21
EdLangley[m]
(defun foo () ...) (foo) is bad (defun foo () ...) (compile 'foo) (foo) is good
1:13:59
mrcom
What's the appropriate channel on Liberia for navel-gazing "how does Lisp compare and contrast with other languages"?
4:06:28
asarch
I have this list: (defparameter *the-list* '((:id 343 :name "foo" :date 3852308297) (:id 212 :name "bar" :date 3852308297) (:id 583 :name "baz" :date 3852308297) …)
4:11:40
beach
asarch: Since you have two lists, I think you may have to use INTERSECTION with some appropriate :KEY and :TEST arguments.
4:12:45
moon-child
beach: I think intersection does not guarantee which of its inputs it uses to make the output
4:13:00
moon-child
'The result list may share cells with, or be eq to, either list-1 or list-2 if appropriate'
4:56:18
mfiano
Bike: Reading the spec for *-D-C, it doesn't seem to matter which parameter I specialize in a :AFTER method, PREVIOUS, CURRENT, or both. Is this correct?
4:58:51
Bike
if you care about updates from one class specifically to another class you need to specialize both. if you care about updates from one class to anything you only specialize on that.
4:59:39
mfiano
I thought one is just a copy of the other, a they would both always be instances of the same direct class
5:00:14
Bike
No, previous is the copy, and it is a direct instance of whatever class the instance being changed used to have
5:05:57
mfiano
Bike: Unfortunately, this seems to have the same bad behavior as SHARED-INITIALIZE for me.
5:09:20
mfiano
The method in the above gist, should _only_ SETF those slot values to the supplied initargs when CHANGE-CLASS's NEW-CLASS-NAME argument matches that of the class I'm specializing on. In the printout, the CAR of the list in the printed represenation is that class name.
5:10:01
mfiano
As you can see, the second invocation, called CHANGE-CLASS with 'SRGB as the new-class-name. I want to ensure that this method is not invoked then.
5:12:03
Bike
okay, so the mop stuff is not helping clarity here. im wondering if there isn't something weird going on such as the actual color-storage3 class object being used both times but its list of mixins changing.
5:14:45
mfiano
c0/c1/c2 initargs update the instance correctly when the first mixin is added with #'MIX, but after the second one, the instance has been reset to the default state.
5:14:57
Bike
like, what you're describing here is your implementation not dispatching correctly, which is a deep enough problem that it seems unlikely