freenode/#lisp - IRC Chatlog
Search
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.
22:54:55
phoe
so I guess buy it now, mostly because I don't know if asking you to wait for a new edition is asking you to wait forever
0:03:35
nij
For instance, I want the :nickname slot of 'person to be a string that only contains lowercase letters a-z. And whenever an instance of 'person to be constructed, the check is performed; and an error will be signaled if test fails.
0:08:09
lotuseater
or use DEFTYPE to construct such a special string type and use that for the :type field for the slot (that's only checked at initialization if safety is high)
0:09:30
pjb
but types may be ignored by an implementation. Better write the :before method, it's their purpose.
0:10:55
pjb
But using check-type in a :before method would be useless, you could only signal an error.
0:12:14
pjb
So it's better to use the main method: (defmethod initialize-instance ((p person) &key nickname … &allow-other-keys) (assert (and (stringp nickname) (< 3 (length nickname))) (nickname) "Nickname must be a string of more than 3 characters, not ~S" nickname) … (call-next-method) p)
0:12:42
pjb
Well: (defmethod initialize-instance ((p person) &key nickname … &allow-other-keys) (assert (and (stringp nickname) (< 3 (length nickname))) (nickname) "Nickname must be a string of more than 3 characters, not ~S" nickname) … (when (next-method-p) (call-next-method)) p)
0:12:50
nij
pjb: even with initialize-instance, sometimes if the user is not careful, they can still use make-instance to surpass my test?
0:13:32
pjb
nij: but you may prefer to use shared-initialize instead, in case there's a change-class involved.
0:13:39
Bike
technically they could bypass initialize-instance by using allocate-instance and setting slots manually, but if they do that they are beyond the protection of god or man
0:14:28
pjb
The generic function shared-initialize is used to fill the slots of an instance using initargs and :initform forms. It is called when an instance is created, when an instance is re-initialized, when an instance is updated to conform to a redefined class, and when an instance is updated to conform to a different class. The generic function shared-initialize is called by the system-supplied primary method for initialize-instance,
0:14:28
pjb
reinitialize-instance, update-instance-for-redefined-class, and update-instance-for-different-class.
0:15:17
pjb
(defclass animal () …) (change-instance 'person (make-instance 'animal :race 'werewolf) :nickname "Woof")
0:16:17
pjb
But yes, shared-initialize should be used in general, instead of initialize-instance. We can cope with initialize-instance just because we don't re-initialize, redefine a class or change of class often.
0:17:21
pjb
nij: go to #sbcl or some other implementation specific channel to discuss why they don't allow you to lock any slot. For example (lock (aref v 42))
0:18:15
nij
Some object really needs to be checked in order for it to fit into the expected abstraction framework.
0:18:59
pjb
nij: you are asking the questions wrong. You should notl say "I find it weird we cannot do X in lisp", you should say "How do I do X in lisp?"!!!
0:19:12
pjb
nij: the part where you are asserting things that are wrong, instead of asking how to do it!
0:20:43
pjb
nij: that said, I agree that there could be some macrology, to specify invariants, pre and post conditions in a more declarative way, and have the functions and method definiting macros use those declarations.
0:20:46
nij
Or instead I should have said: "I find it wierd to not being able to automatically assumption-check in the thing provided already by CLOS." Is that better?
0:21:26
pjb
nij: you can (shadow '(defclass defun lambda defgeneric defmethod defmacro)) and implement them to process such declarations.
0:21:40
no-defun-allowed
pjb: Stop complaining, start googling https://github.com/sellout/quid-pro-quo
0:22:18
pjb
(defgeneric foo (x) (declare (precondition (< 0 (bar x))) (postcondition (= (bar x) (- (old (bar x)) 1)))))
0:23:23
pjb
nij: some declaration would be needed to specify the allowed conditions. (like throws declarations in C++).
0:25:50
nij
I.. I need time to comprehend quid-pro-quo.. but first I'll do pjb's advice. If someone would, could you please tell me how quid-pro-quo would fit into my need? I will get back to that soon after digesting pjb's word.
0:26:59
nij
===> (defmethod foo ((x c)) …) would automatically insert the test ;; !!!!! I didn't know this.
0:27:44
pjb
Once a symbol from CL is shadowed, we're not talking about CL anymore, but about your own operators!
0:29:34
nij
I'm melt. Sounds exactly what I want: "The client must guarantee certain conditions before calling a method specialized on the class (the preconditions), the class guarantees certain properties after the call (the postconditions)."
0:31:52
pjb
nij: also, note that just using ASSERT in your code, let you insert explicit pre-conditions post-conditions and invariants.
0:32:12
perdent
Hey is anyone interested in a crypto/hardware challenge i made involving DPA/CPA on AES-128? So I captured the embedded device that was used to encrypt the ciphers you are trying to break. are you able to recover its Encryption Key? here is the socket_interface: https://pastebin.com/cLuqmZyY and here is the remote lab layout: https://ibb.co/q9j59Mq PS, his might b helpful, message me if you need any hints, and if you manage to solve it
0:32:13
perdent
Can communicate to the remote device with netcat or or with the socket interface script to receive traces etc.
0:32:13
perdent
Here is the host you can netcat to and communicate via the socket script: 206.189.121.131:32384
0:38:09
nij
quid-pro-quo seems to be a stronger version of dbc, according to someone on the internet
0:41:41
nij
What if I just use deftype.. and make a new type? Then use :type? What are some ways for the users to workaround this scheme?
0:45:56
lotuseater
and then eg (deftype special-string () '(and string (satisfies special-string-p)))
0:48:53
pjb
nij: :type in defclass is a DECLARATION, not a check! "The :type slot option specifies that the contents of the slot will always be of the specified data type. It effectively declares the result type of the reader generic function when applied to an object of this class. "
0:49:15
pjb
nij: it is YOU who are telling the compiler that it does not need to perform any check, that the slot will always contain the type you specify.
0:49:49
pjb
What you want is to check the parameters for the right type. Ie. use CHECK-TYPE in the shared-initialize method.
0:51:32
pjb
(defclass c () ((x :initarg :x :initform 42 :type fixnum :reader x))) (make-instance 'c :x "foo") is undefined, but worse, it makes (declaim (safety 3)) (+ 3 (make-instance 'c :x "foo")) undefined as well AFAIUI.
0:52:27
pjb
Because :type fixnum in the slot works as a declaration, (+ 3 (x (make-instance 'c :x "foo"))) should behave as (+ 3 (the fixnum (x (make-instance 'c :x "foo")))) and therefore cannot signal a type-error.
0:55:53
pjb
well, we're still in undefined waters for (+ 3 (x (make-instance 'c :x "foo"))), so I guess a type-error would be acceptable. But anything else too.
0:56:19
pjb
THE specifies that the values returned by form are of the types specified by value-type. The consequences are undefined if any result is not of the declared type.
0:57:44
nij
https://github.com/sellout/quid-pro-quo/blob/master/README.md ;; see the last code block.
0:58:11
nij
The tests are put in that slot! How did it do it?! Did it redefine the macro defclass as pjb said?
1:00:00
nij
It also says "in order to have invariants on a class, the metaclass must be specified as contracted-class." - metaclasses are still beyond my knowledge.
1:01:50
pjb
nij: nope, there's no shadow in https://github.com/sellout/quid-pro-quo/blob/master/src/package.lisp but dbc shadows defclass and make-instance.
1:02:35
Nilby
My opinion is that until you have a lot of CL experience, it's probably better not to mutate the language too much, until you understand the trade-offs.
1:02:54
pjb
nij: Perhaps the presence of a source file named metaclass is a hint? https://github.com/sellout/quid-pro-quo/blob/master/src/metaclass.lisp
1:03:15
nij
Nilby: Yeah I think so. So I'm trying to find out if it mutates the lang, or actually it's playing in the circle.
1:04:28
Nilby
With Lisp, it's hard to see a circle. In some way every function and macro mutates the language.
1:05:36
lotuseater
hehe, yeah nij, there you could learn also more about where parser-combinators come from
1:06:14
nij
lotuseater: I got irritated when there's no checking performed for a, say monad, when you claim your data is a monad..
1:06:33
lotuseater
and for what Nilby says, it's also not bad for knowing how the MOP works and how (or maybe why) it differs
1:06:34
nij
I think dbc is very important.. I cannot imagine a lang without that. At least, I need to know how to dbc.
1:07:07
nij
lotuseater: Are you hinting that maybe the magic here is played by MOP? I have no idea what that is yet.
1:08:05
lotuseater
when you talk about type signatures in haskell, that's checked at compile time by the GHC type inferencer
1:09:46
nij
Perhaps - in readme it says "Corman – NO[T supported], it’s not supported by Closer-MOP"
1:15:50
saturn2
nij: all the pieces of CLOS - classes, generic functions, and so on - are themselves objects which you can subclass and define your own behavior for. that's what MOP is
1:20:00
zacts
can a lisp program with included quicklisp libraries be compiled into a single binary?
1:21:03
saturn2
yes, as long as those libraries don't depend on reading any files after being compiled
1:22:39
no-defun-allowed
Same as how you'd make a binary without dependencies. Load your code, then dump an image.
1:23:18
zacts
no-defun-allowed: I'm a complete beginner, I don't even know how to do that yet. Can I lookup how to do this in the SBCL doc?
1:24:19
White_Flame
saves a snapshot of the current state of the running lisp image, and give it a function to run when it starts up again
1:24:33
no-defun-allowed
zacts: Yes, but in summary, assuming you have another system with your code, you are looking at (ql:quickload :your-system-name) (sb-ext:save-lisp-and-die "binary-name" :executable t :toplevel #'your-system-name:start)
1:25:39
zacts
would this binary be portable enough that I could post it as a Linux release for a project on GitHub?
1:27:40
zacts
Like, would I be able to publish a single x86 Linux static binary image that others could run on an x86 Linux without them needing to install SBCL?
1:29:43
White_Flame
however, if some of the QL dependencies rely on native .so's being present, those aren't going to be statically linked
1:30:32
White_Flame
so the target machine might hopefully just need some apt installs or whatever to get them
1:34:54
lotuseat`
hm i wasn't aware you can compile static binaries. but that would loose the ability being redefinable at runtime, wouldn't it?
1:39:31
Nilby
zacts: There can be problems, but here's a couple recent successful stories of binary packaging: https://www.timmons.dev/ and https://nyxt.atlas.engineer/article/continuous-testing-and-packaging.org
1:41:17
White_Flame
well, at the OS & C lingo, a static library means it's fully included into your executable when you compile it. A dynamically linked library means it looks for the shared installed separate library file when the executable runs, meaning the executable is smaller and the OS could have a different version and still work
1:42:10
White_Flame
SBCL, for instance, uses a zlib dynamic library to support compressed cores, so it's not fully static
1:46:29
White_Flame
so really, I'm not sure how many "static binaries" there are in existence anymore, but rather you have static libraries vs dynamic libraries
1:49:25
etimmons
definitely no libc.so and libpthread.so. Not sure if there's any special magic for linux-vdso.so on static binaries
1:50:29
etimmons
And possible to do with ECL (definitely easier than SBCL, and actually supported by upstream)
1:52:16
etimmons
libc.so madness was one of the reasons I pursued static binaries with SBCL. I was tired of always needing to remember to compile with an old glibc for the broadest support
1:53:21
Nilby
zacts: There's also this https://github.com/Shinmera/deploy from the first persone, that we know of, to heroicly make CL Steam games.
1:55:46
etimmons
zacts: definitely recommend starting with deploy or linux-packaging. Making static binaries definitely has some quirks that it's best to avoid unless you *really* know that's what you want
2:06:26
etimmons
Yes. and linux-packaging is https://gitlab.com/ralt/linux-packaging/ (also referred to in the Nyxt link)
2:07:31
etimmons
In that case, just use asdf:program-op and compile on the oldest version of your linux distribution that you're willing to support