freenode/#lisp - IRC Chatlog
Search
10:41:47
nij
Is there a "safe" thread, meaning a thread that completely logs all output, and skip (but log) any errors when it's running?
10:43:22
nij
By a "safe" thread I mean a thread that does (1) all logging (2) all things I asked above automatically.
10:45:32
nij
This ==> (loop (tagbody :continue (handler-bind ((error (lambda (c) (log-error c) (go :continue))) (do-thing)))
10:49:00
phoe
there's a variant of handler-case that I described in one of the TCLCS appendices that executes the handler and only then unwinds, but it's not standard
12:28:44
beach
jnewton: Here is the link to the document about a Lisp OS that I mentioned on the phone: http://metamodular.com/closos.pdf
12:48:10
pjb
nij: if log error doesn't use implementation specific API to collect and report the backtrace, then you can use handler-case instead of handler-bind. (loop (handler-case (do-thing) ((error (c) (log-error c)))))
12:54:29
nij
Is there a tiny project that uses CFFI? I'm new to it and hope to see it working in action. Thanks :)
12:55:32
pjb
nij: https://github.com/informatimago/lisp/tree/master/clext/pkcs11 might be an example.
12:56:21
pjb
nij: it wraps a pkcs11 library in a low-level lisp package and a high-level lisp package, which is rather a classic way to do it.
12:57:36
pjb
nij: and pcks11.lisp wraps the low-level C function calls in lisp calls, processing error handling and parameter conversions, etc.
12:59:09
pjb
nij: notably, when you have a library with a consistent API, you can write macros to perform the work in a consistent way, so wrapping over is easy: https://github.com/informatimago/lisp/blob/master/clext/pkcs11/pkcs11.lisp#L2011
13:00:12
pjb
nij: an example of usage of this library is in https://github.com/informatimago/scquery (sources-cl, not sources, which contains the C version).
13:01:49
pjb
nij: I guess we could give a hello world example, but this wouldn't teach you anything more than the cffi manual.
13:03:02
nij
semz you mean this? https://common-lisp.net/project/cffi/manual/cffi-manual.html#Tutorial
13:03:24
beach
kali123: Like: /nick my-new-nick and be sure the slash is the first character on the line.
13:04:10
beach
nij: I strongly recommend you use Common Lisp exclusively if you possibly can. Using FFI makes everything much harder.
13:05:01
splittist
nij: how is asking questions about it on irc going to help you? I usually find trying things out - and with lisp that's usually very easy - much more likely to illuminate the particular areas of ignorance I want to address.
13:07:17
nij
splittist: I never know. Sometimes on some topics there will be super helpful advises. Sometimes no..
13:07:49
pjb
nij: for example, there's a clock() -> long (actually clock_t but it's a long) function in libc. (cffi:defcfun (clock "clock") :long) #| --> clock |# (clock) #| --> 147584979 |# (- (clock) (progn (sleep 1) (clock))) #| --> -110 |#
13:10:15
pjb
nij: another example, always in libc, there's a int chmod(const char*path,int mode) function: (cffi:defcfun (change-file-mode "chmod") :int (path :string) (mode :int)) (change-file-mode "/tmp/foo.c" #o444) #| --> 0 |# ls -l /tmp/foo.c # --> -r--r--r-- 1 pjb wheel 29 May 4 05:08 /tmp/foo.c
13:11:28
pjb
So you would have to read the C header file, or write a little C function to get it: #include <time.h> long clocks_per_sec(){return CLOCKS_PER_SEC;} and use cffi to call it.
13:12:18
pjb
nij: C APIs are often not designed to be used in foreign code, so they use things like C macros and other stuff that goes thru difficultly. You may have to write some C portability code sometimes.
13:13:09
pjb
nij: of course, there are more complex cases, eg. out or inout parameters. Then you may have to allocate temporary storage for them, and convert the data. See the pcks11 example for that.
13:13:58
nij
In the first example you gave, the output was an integer, which is easy to translate to Lisp.
13:14:20
pjb
nij: but there are special cases. For example, macOS uses some structures with #pragma packed , and cffi doesn't deal with that.
13:14:36
nij
I see. Say I'm using a function in some C library, I need to translate the structures defined in that C library by myself?
13:14:43
pjb
nij: so I find it easier and safer, to refer structures are mere memory blocks, and specify the offsets to the fields myself.
13:16:03
pjb
nij: an example with defcstruct forms: https://gitlab.com/patchwork/CoreMIDI/-/blob/master/coremidi-cffi.lisp
13:17:42
nij
Nilby: yeah. but most of the time I must translate the structures in to Lisp by using defcstruct, right?
13:20:22
Nilby
nij: You don't have to translate. But it depends how you want to use them. If you want to use them conveniently in Lisp code that doesn't use CFFI, then yes. Usually one would provide a higher level interface to C code.
13:23:09
pjb
It depends on the C API really. Sometimes, they use complex structures to be created by the client code, then it's more convenient to do that in lisp, and provide code to convert between lisp an C structures. Sometimes they use function calls to manipulate an internal state, and then it is easier, you just have to deal with the functions.
13:23:58
pjb
void* make_point(); void point_set_x(void* pt,int x); void point_set_y(void* pt,int y); int point_x(void* pt); int point_y(void* pt);
13:24:46
pjb
vs. typedef struct point {int x,y; } point_t; point_t* make_point(); void use_point(point_t* pt);
13:25:22
pjb
using point_set_x is simplier from a FFI point of view than having to know how the struct point is laid out, and how to store or read it.
13:26:23
pjb
Also, in terms of API, when the structure point evolves (they may add fields, or want to reorder them), code using point_set_x will always work, while code setting directly a structure may become incompatible.
14:10:21
jmercouris
however, this forces recompilation of systems on disk which are in NOT writable directories
14:15:14
jackdaniel
you may want to try harder to provide a reproducible test case; ("foo" "bar") is indeed an illegal function call
14:16:01
jackdaniel
asdf claims that it does some magic parsing of asd files, but it in reality reads them
14:19:26
Nilby
I've been living with the same problem for years. It's especially trouble when your not in control of the filesystem or quicklisp setup for the resulting images, and the REPL user may _want_ to reload some systems. I figured someday I would force asdf to do what I want.
14:27:55
delta
Hello! I am trying to spawn multiple infinite-running processes and then, at an input from a user, send sigint to all of those processes and then exit the program. Can I get some help? I've found inferior-shell to launch processes and bordeaux-threads to make threads, but I'm not sure how to achieve exactly what I want.
14:31:08
beach
delta: Presumably, to fork a process from a Common Lisp image, you would need to use some implementation-specific function, like the POSIX interface of SBCL.
14:31:27
delta
Right, but I can make a thread and then spawn a process from that thread using inferior-shell, right?
14:31:58
delta
Perhaps I'm getting myself turned around and should move back to square one and just spawn a regular unix process.
14:32:16
beach
I don't know what inferior-shell is. Sorry. You would typically have a Common Lisp REPL, and you don't have to create a thread from there to fork a process.
14:32:52
beach
So you are not trying to "spawn a regular unix process"? What other kinds of processes are there?
14:34:40
delta
inferior-shell is just a library I found from googling how to run a shell command basically. I am trying to spawn a regular unix process, I'm just trying to execute an infinitely running process and interrupt it when I choose to. I think I reached for Bordeaux too quickly because it seems to be the de facto multiprocessing thing, but really what I wanted all a long was to just fork and store the PID to eventually send SIGINT to.
14:35:57
beach
I see no reason to use a shell at all. You should be able to use the implementation-specific POSIX system to fork the Common Lisp process itself.
14:37:31
Nilby
With sbcl you can use run-program with :wait nil which usually puts them in the background, save the process-pid, and then call sb-posix:kill on them
14:38:24
jmercouris
I used (alexandria:define-constant ..) and now I want to override it in the REPL
14:38:58
Bike
you want to set it to an actually different value? your implementation might offer a restart for it
14:39:16
Bike
redefining a constant is dicey because the compiler might be using the value, i.e. previously compiled code referencing the constant will still be using the old value
14:45:18
Nilby
I seem to end up using the constant changing restart a lot. It doesn't always work. Worse, if you save images a lot it's possible to multiple generations of different wrong constants.
14:54:16
pjb
π, e, c are constants. (note PI, E and C are not, in implementations when the size of long-floats can be changed at run-time ;-))
15:03:31
Nilby
There's only a few standard Lisp character names, so I was surprised when one day instead of beeping I saw: 🔔
15:11:39
jnewton
I heard someone (don't remember who) that someone (don't remember who) claimed to be working on a Common Lisp like condition system in Python. Who said it and who said it?
15:15:33
beach
jnewton: Are you also aware that phoe gave a presentation to the Webassembly people concerning the control structures that are needed for a condition system?
15:18:05
jnewton
@beach, no but I recently realized that I don't understand the condition system when trying to figure out how to implement it in Scala. I wanted to have something in Scala to present to Scala experts to demonstrate why there are important exceptional situations other than Errors.
15:21:40
agumonkey
phoe recently said he might rewrite it a bit (after some voices saying the style needed work)
15:21:48
jnewton
I saw an announcement for the CL algorithms book, but I've never seen an announcement for the Condition System book. I sense that keeping it a secret on IRC is counterproductive
15:22:47
beach
jnewton: It is easy (but unproductive) for IRC-ers to assume that when it has been announced here, everybody knows it.
15:24:11
jackdaniel
beach: your friendly neighborhood moderator looked it up for you on the vast internet: https://www.apress.com/gp/book/9781484261330
15:24:54
jackdaniel
jnewton: that's not how real conversations work, is it? :) no, it is not slack, no time travel nor annotations of past messages
15:25:01
jnewton
@beach: I found the book on amazon. and apparently there's also a new lisp blockchain book.
15:25:51
beach
jnewton: The @ convention is not used on IRC, just type the nick of the person (using completion) followed by `:'.
15:28:07
jnewton
is there enough info in the book to implement the condition system in a JVM hosted language? If so, it could be really practical.
15:30:58
jnewton
is there a way to make the condition system work with lazily evaluated code? I.e., you might define an anonymous function within a certain stackframe, but when the function is called, the stackframe is long gone. This is one of the problems with dynamic variables and also of exception handling in both Scala and Clojure.
15:33:59
Odin-
Huh. I was not aware of that book, which is nevertheless very much within my field of interest.
15:52:24
agumonkey
not sure it's right what you asked for jnewton but https://github.com/IGJoshua/farolero is a condition system for clojure
15:57:57
jnewton
as I understand agumonkey, there are many conditions systems for clojure, many of which are inspired by CL. The problem (as I understand) is they are not compatible with each other, therefore no library wants to use one. If Library A used one, then the user might also include library B which uses a different one.
15:58:11
Nilby
srandon111: I don't know, but I do have lots of other trouble running sbcl on netbsd.
15:58:21
Nilby
Java has throw and catch, which is really all that's required. CL style conditions have to be able to be sometimes handled before the throw, which is of course possible, just not what Java usually does.
16:00:02
Nilby
They help, but you could simulate them with global variables, or any variables if need be.
16:00:15
jnewton
nilby: you need to somehow be able to look up the stack to find handlers and restarts.
16:01:13
jnewton
There is a Scala class called DynamicVariable which uses sort of an unwind-protect mechansims. the variables are lexical, so you can only reference them within a scope where it is lexically visible, but the value is dynamic.
16:02:02
beach
jnewton: When you want to bind a dynamic variable, you assign its value to a lexical one and then you modify the global value.
16:02:05
jnewton
There are two reasons I wanted to implement it. 1. because I'd like to show it to other Scala programmers. and 2. because implementing it would make me understand it.
16:03:02
beach
It doesn't work so well for implementing the full semantics of Common Lisp dynamic variables in the presence of threads.
16:04:49
Nilby
Even if you just have catch and throw, unwind-protect is just like a todo list before you throw or after normal return.
16:05:56
White_Flame
beach: or modify the thread-local one on write, and on read check if the thread-local one is unbound (some unique default singleton) and read the global value if it is
16:06:03
jnewton
The reason I stopped was because I didn't know what type all the objects needed to be. You need to somehow do it so the code is well typed. the task was beyond my capacity at the time. I'd on my list of things to revisit.
16:08:45
White_Flame
and of course another wrinkle in java would be the unwind mechanics around the binding scope
16:11:35
beach
And I don't know why Krystof said "almost 20 years". I am pretty sure he was there in 2000, which would make it 21 years this year.
16:14:10
White_Flame
but anyway, given java's thread local storage, is there any material difference to SBCL's strategy in implementing special variable bindings?
16:14:29
jackdaniel
cache invalidatation and off by one errors are three of the hardest problems in programming
16:15:23
Odin-
ACTION thought there were only two hard problems: Naming things, cache invalidation and off-by-one errors.
16:16:56
nij
Without reading phoe's book.. here am I asking a dumb question directly. I intend to let the error be echoed (using format) without triggering the debugger. But that's not the case. Why? https://bpa.st/6ZGQ
16:18:11
jackdaniel
nij: handler-bind allows you to do things in a dynamic context of the error and carry on with handling the error
16:18:48
Odin-
jnewton: You could think of it as an ephemeral shared append-only text file, rather than as similar to the modern bells-and-whistles systems.
16:18:57
jackdaniel
basically to continue after the error you must wrap each place so the program knows where to resume
16:19:30
beach
jnewton: Probably. It might be a bit overwhelming when there are multiple discussion threads going on simultaneously.
16:19:40
nij
Hmm.. what should I do for it to proceed without debugger, but report any info that a debugger would provide?
16:20:14
jackdaniel
(progn (handler-case (/ 1 0) (serious-condition (c) (Print c)) (print "after!"))
16:20:34
beach
jnewton: Oh, and one more important thing. You quickly learn what people are likely to say things you are interested in, and what people you can safely ignore.
16:21:11
jackdaniel
(progn (block hi! (handler-bind … (lambda (c) (print c) (return-from hi!)))) (print "bye")
16:22:14
jackdaniel
nij: you could have a macro that wraps each form in the body in such handler-bind, but it doesn't make much sense
16:22:37
jackdaniel
because when your form errors then it means, that your program basically doesn't work and requires special attention
16:26:16
nij
=> (progn (block hi! (handler-bind ((error (lambda (c) (print c) (return-from hi!)))) (/ 1 0))) (print "bye"))
16:27:56
Odin-
If you want to _generally_ just print the condition object and carry on, couldn't you intercept the debugger entry?
16:33:18
jackdaniel
(defmacro with-foolhardy-forms (&body body) `(let ((*debugger-hook* (lambda (c s) (print c s) (throw :foo)))) ,@(loop for form in body collect `(catch :foo ,form))))
16:33:29
Nilby
Just please don't mess with the global value of the *debugger-hook* or you could disble people's debuggers.
16:36:10
pjb
nij: if log error doesn't use implementation specific API to collect and report the backtrace, then you can use handler-case instead of handler-bind. (loop (handler-case (do-thing) (error (c) (log-error c))))
16:36:46
pjb
(defmacro repeat (n &body body) `(loop :repeat ,n :do (handler-case (progn ,@body) (error (err) (princ err *error-output*) (terpri *error-output*)))))
16:36:49
nij
I have the impression that handler-case is more general and could capture more error message.. is that correct?
16:37:12
pjb
(repeat 3 (/ 0)) #| --> nil |# with division-by-zero detected performing / on (1 0) three times on *error-output*.
16:37:40
pjb
handler-case it's executed AFTER unwinding the stack. handler-bind it's executed BEFORE.
16:38:04
pjb
usually you will use handler-case. Only if you want to do something in the context where the error is detected you will use handler-bind.
16:41:02
pjb
since we cannot answer this question in general, you have to write restart points in the procedure!
16:42:44
pjb
(handler-bind ((error (lambda (c) (invoke-restart 'continue)))) (with-simple-restart (continue "Continue") (+ 1 (with-simple-restart (continue "Continue") (/ 0))))) #| --> nil ; t |#
16:43:41
saturn2
any sensible compiler will rely on the assumption that it's impossible to return normally from an error
16:44:00
pjb
(handler-bind ((error (lambda (c) (invoke-restart 'continue)))) (with-simple-restart (continue "Continue") (if (with-simple-restart (continue "Continue") (/ 0)) 'ok 'send-the-missile))) #| --> send-the-missile |#
16:47:18
nij
Namely, if there's an error, either ignore it, or handle it. I basically just want to ignore it, and hope the procedure goes on. But that's not possible in general.
16:48:53
pjb
When there is an error, you want to avoid continuing doing blindly what you were doing, because it's useless or dangerous. Instead, you want to continue from a point where you know what consistent state you are in.
16:49:40
pjb
handler-bind is for when you want to enter the debugger, or invoke a restart, which are continuation points that have been designed in the program, that may be inside the scope of the handler-bind form.
16:49:41
nij
What does ignore-errors do when encountering an error? Stop the process, and return nil?
16:50:09
pjb
nothing is stopped. It just performs a non-local exit to its scope and return nil and the error.
16:52:01
pjb
(macroexpand-1 '(ignore-errors (/ 0))) #| --> (handler-case (progn (/ 0)) (error (condition) (values nil condition))) ; t |#
16:52:05
pjb
ie. (defmacro ignore-errors (&body body) `(handler-case (progn ,@body) (error (err) (values nil err))))
16:52:10
jcowan
pjb: Not always. In a server, for example, you probably want to abandon th thread on an error, not the whole program.
16:52:32
nij
It touches *debugger-hook* which I decide to take a look after considering handler-bind.
16:52:35
pjb
When we ask to disable the debugger, it's not the same as when we as to ignore the errors.
16:54:41
pjb
jcowan: in the sense that this is meaningless. You wrap handlers around scopes of code. There's no consideration of threads.
16:57:15
jcowan
I was talking about (make-thread (handler-case ... (foo)), where the handler-case traps errors.
16:58:59
pjb
vs. eg. (make-thread (lambda () (loop (handler-case (foo) (error (err) (princ err) (terpri))))))
16:59:54
pjb
As you can see, often you will want to wrap the body of the loop, not the body of the whole function called by the thread.
17:00:15
pjb
It's not because handling a request failed, that the request handling should stop, is it?
17:03:06
pjb
Now one problem is that in more complex functions, there are a lot of places where a given error may occur. So just printing the error message may be insufficient.
17:04:05
pjb
nij: eg. (block try (handler-bind ((error (lambda (c) (princ c) (terpri) (print-backtrace) (return-from try nil)))) (body)))
17:21:48
Colleen
nij: Unknown command. Possible matches: 8, set, say, mop, get, about self, logout, grant, block, award,
17:42:43
pjb
nij: (block done (handler-bind ((error (lambda (err) (uiop:print-backtrace :stream *error-output* :count 10 :condition err) (return-from done)))) (/ 0)))
18:45:47
CL-ASHOK
Is there a way to define a function which modifies the value of the parameter passed in?
18:47:20
CL-ASHOK
e.g. (defun modify-this (parameter) .....) where .... modifies parameter. Or do I need to do (setf parameter (modify-this parameter))
18:48:07
pjb
(defun modify-this (parameter) (setf parameter 42) (assert (= 42 parameter)) parameter) (modify-this 33) #| --> 42 |#
18:48:40
pjb
CL-ASHOK: the parameter a the variable local to the function that contains the value of the argument passed to the function.
18:49:11
pjb
CL-ASHOK: if what you want to mutate is a lexical variable outside of the scope of the function, then no, there's no direct way.
18:49:27
pjb
CL-ASHOK: but note that you can create closures that can mutate a lexical variable, INSIDE the scope of the variable.
18:50:16
pjb
CL-ASHOK: (defun modify-fun (writer) (funcall writer 42)) (let ((variable 33)) (modify-fun (lambda (new-value) (setf variable new-value))) variable) #| --> 42 |#
18:50:46
pjb
CL-ASHOK: you can wrap that in macros: http://informatimago.com/articles/usenet.html#C-like-pointers-in-Lisp
18:52:03
CL-ASHOK
pjb: I have a CLOS object that I want to modify. So currently I am re-creating it with the new values, but it would be easier if I could just edit the slot that I want to edit
18:53:04
CL-ASHOK
but the object is passed in a function, so if I modify it, only the local copy is modified
18:53:12
pjb
(defclass c () ((foo :initform 3 :accessor foo))) (defun modify-object (o) (setf (foo o) 42)) (let ((o (make-instance 'c))) (modify-object o) (foo o)) #| --> 42 |#
18:54:18
pjb
It's not the variable O that is passed, it's the VALUE of the variable O. The VALUE of the variable or is a reference to the instance.
18:55:14
CL-ASHOK
Oh, so if I have (defun modify-this (object-a) ... (setf (object-name object-a) "David"))
18:55:31
CL-ASHOK
object-a is actually modified - so I don't need to keep copying it to a new object?
18:56:03
pjb
CL-ASHOK: there are very few lisp object types that are not mutable: numbers and characters. Even symbols who have an immutable name, are mutable: you can change the symbol-package, the symbol-value, the symbol-function, the symbol-plist.
18:56:46
pjb
The symbol OBJET-A names a variable (the parameter of the function named by the symbol MODIFY-THIS).
18:57:16
pjb
the variable named OBJET-A is bound to a lisp object. This lisp object is the VALUE of the variable named OBJET-A.
18:58:38
pjb
When you evaluate (setf (object-name object-a) "David"), the value of the variable named OBJECT-A, ie. a reference to the objeect, is passed to the function named (SETF OBJECT-NAME).
18:59:04
saturn2
if you want to be able to mutate a single value, you can also wrap it in another object, like an array e.g. (defun modify-this (parameter) (setf (aref parameter) 42)) (let ((container (make-array nil))) (modify-this container) (aref container)))
18:59:23
pjb
CL-ASHOK: in short, lisp uses pass by value, but all the values are references to objects. So you can still mutate mutable objects.
19:01:33
pjb
CL-ASHOK: really, the model is very simple: places are litle boxes, references are little arrows stored in those boxes, pointing to the referenced lisp object.
19:01:58
CL-ASHOK
because in a "normal" parameter, bindings are created with lexical scope (not sure if that is the right terminology)
19:02:18
pjb
Some lisp objects such as number and characters don't contain places, they don't have any arrow going from them.
19:03:52
pjb
(defun f (p) …) (let ((a 42)) (f a)) when evaluating f (in the …) we have 2 references to the number 42: a:[*]--->42<---[*]:p
19:04:35
pjb
in the place A and the place P. What has been copied, it is the *--> that was in A, to P. Hence the 2 arrows.
19:04:50
CL-ASHOK
Ah so when we change a to 43, then we are repointing a to a new value, whereas when we change an object
19:06:32
pjb
eg. a vector with 3 slots: v:[*]-->{[1][2][3]} passed to a function (defun m (w) (setf (aref w 1) 42) …) v:[*]-->{[1][42][3]}<--[*]:w in the …
19:07:06
pjb
when we return from the function the parameter w is destroyed, but there remain the reference from v: v:[*]-->{[1][42][3]}
19:09:01
CL-ASHOK
So does the compiler or interpreter maintain a list of lisp objects, and if there are repeated references to them, then multiple variables point to the same object?
19:09:08
pjb
CL-ASHOK: now, to delete an element from a list (destructively), we can mutate the CDR of the previous cell. Even if we want to delete the first element, we can move the CAR and the CDR of the second cell to the first cell. But what we cannot do, is to transform the last cons cell into the symbol NIL. Since NIL represents the empty list when we delete the last, element, we need a way to mutate the place that contained the ref
19:09:26
pjb
CL-ASHOK: this is why with functions like DELETE we use (setf list (delete element list)).
19:10:00
pjb
It's to handle the case: (let ((list (list 1))) (values (delete 1 list) list)) #| --> nil ; (1) |#
19:16:48
CL-ASHOK
I found I'm getting into the habits of using a lot of lets, which is effectively an imperative style
19:18:25
pseudonymous
I have a function which, somehow, returns a namespaced (?) symbol..? All in all it looks like this `(package::foo ...)` and I expected `(foo ...)` - this result comes when calling the relevant function from another package.. Ideas ?
19:20:52
CL-ASHOK
pjb: I basically have let* and then define 10 variables, with the final one being the answer
19:22:15
pseudonymous
Bike: hey :) Not that I'm aware, but CL is not my strong suit. Had a break, but mainly coming from Clojure with a bit of Racket years back. Can I show you a paste ? If so, which paste site(s) are acceptable on this channel ?
19:28:51
pseudonymous
Bike: https://plaster.tymoon.eu/view/2431#2431 - the actual function is at the top, the function it's called through right below, the example output in the bottom :) Appreciate it!
19:29:47
CL-ASHOK
https://github.com/muditbac/Reading/blob/master/programming/(Prentice%20Hall%20series%20in%20artificial%20intelligence)%20Paul%20Graham-ANSI%20Common%20LISP-Prentice%20Hall%20(1996).pdf
19:29:50
Bike
okay, well, that looks usual. if *package* is some other package than xyz, when you print an internal symbol from xyz it will be qualified like this.
19:30:23
Bike
Since *package* was xyz when you defined rr/prop-access, the prop symbol it uses is in the xyz package.
19:33:31
Bike
basically what package you're in when you run these functions won't affect the results, it's just that the results are displayed differently.
19:37:01
pseudonymous
Ah, well, it does cause some issues in my tests. Strangely enough, the other functions I have which return syntax have managed to avoid this issue until now.
19:37:39
Bike
It could be for example that your test refers to its own 'prop, which will effectively be xyz/tests::prop, which is a distinct symbol from xyz::prop.
19:40:18
pseudonymous
Hehe.. I suspect it's because I'm returning (and comparing) forms like `(lambda ...) and `(let ...) and I'm guessing both packages agree on these symbols :D
19:43:52
Krystof
beach: my first bug report to SBCL was in 2001; my first commit to SBCL cvs was 2002
19:46:54
Krystof
beach: https://web.archive.org/web/20170630054304/http://www.advogato.org/person/crhodes/diary/24.html puts my (I think) first RMLL appearance in 2002
21:14:18
Nilby
srandon111: I like netbsd, but I have some troubles with sbcl on it. I've been working on trying to fix it. Maybe if I figure it out, I'll work on threads.