libera/#commonlisp - IRC Chatlog
Search
4:00:41
beach
Also, look at the channel logs. This question comes up several times a year. You won't add anything to the existing information.
4:05:39
lisp-newbie
List question: I have a list where every car is itself a cons which is a key value pair, I want to get the value for a certain key, but it's not a plist because each car is not a key, it's another cons which is a key/value cons. Does anyone know how can I do this?
4:09:16
lotuseater
lisp-newbie: and if you "know" all keys will be of type string you can provide ":test #'string=" to ASSOC
4:10:59
lisp-newbie
Oh haha beach you are saying that is the default way of doing such a thing? the framework I'm using just turns it into an assoc list and that's how to do it.
4:12:20
lotuseater
lisp-newbie: assoc-lists are useful when dealing with small amounts of key-value pairs. anything beyond that is better to handle with hash tables
4:13:42
lisp-newbie
(assoc (lack.request:request-body-parameters *request*) "id" :test #'string=) this gave me an error: Constant "id" conflicts with its asserted type LIST.
4:16:40
lotuseater
this is one of the good things when using SLIME or friends, typing a known symbol as operator and it shows you good named arguments and possible keywords etc in the bottom bar
4:18:00
beach
lotuseater: I use that feature all the time, which is why I don't have to remember this information myself.
4:19:33
lisp-newbie
How about embedded keys?? Do I have to do the same assoc twice? Or is there a direct way to do it? Say:
4:19:54
lotuseater
yes it's a lifesaver feature. I remember a time where I didn't use it and thought "oh noez what did this had as keywords?"
5:30:58
kakuhen
Is there a neat way to "cast" the type of a bignum to, say, (unsigned-byte 64)? Right now I am simply taking the integer modulo 2^64 to achieve this.
5:33:19
beach
So you just want to ignore upper bits, even if that means returning a different value than that of the original number?
5:34:25
kakuhen
As of now, my expression is (mod (logior (ash value count) (ash value (- 64 count))) #.(expt 2 64))
5:42:19
moon-child
I think that will not behave correctly if your input is greater than 64 bits; you should mask before shifting
5:43:57
moon-child
(let ((mask #.(1- (expt 2 64)))) (logand mask (logior (ash value count) (ash (logand value mask) (- 64 count)))))
5:47:35
hayley
If you use SBCL then you could use SB-ROTATE-BYTE to generate the right machine instruction for a circular shift, and then use a portable implementation for other Lisp implementations.
6:20:11
kakuhen
I see. I'm using CCL so I decided to just write the usual C version "directly," without considering the fact it's non-portable across architectures :x
6:36:21
hayley
I don't see why it would be non-portable, assuming you wrote it in Common Lisp. Then it would merely go slower if the implementation requires bignums to work.
7:19:56
kakuhen
Is there something like #'float but for double-float? My implementation only seems to offer double-float as a class and type
8:54:27
beach
We now have 35 WSCL issues defined: https://github.com/s-expressionists/wscl/tree/main/wscl-issues/proposed and, as before, help would be appreciated where these issues need to be checked on more implementations.
9:46:06
contrapunctus
nirnam: why not use Emacs? With Evil you have a complete implementation of Vim editing. You can use TRAMP to access remote machines. The Lisp tooling, I hear, is unparalleled in Emacs. So...why not? 🤔 (also, EWW is a great browser for documentation - mostly textual, but can also display images.)
9:59:42
nij-
Emacs takes times to learn. It'd be a slightly painful learning process who has settled in their systems that fulfill most of their needs.. or at least it was how it felt for me before I switched to emacs ;)
10:01:21
nij-
But really.. I think the fundamental difference between emacs and vim is that emacs is lisp, but vim is not. That lisp is better could be obvious to lispers, but I find it hard to explain to those who aren't.
10:16:01
pjb
beach: I've posted my comments in a PR https://github.com/s-expressionists/wscl/pull/1 Feel free to integrate them as you wish and reject the PR, it's not to be taken literally.
10:31:43
lotuseater
Has anyone advise or sources to fully understand continuations? I think I don't up till now. I know and worked through the chapter in "On Lisp" by Paul Graham some times, knowing how to define the needed macros is indispensable.
10:35:00
MichaelRaskin
For continuations I would recommend _Scheme_ explanations of things like amb macro
10:35:04
hayley
A continuation is "merely" the rest of the computation. If you reify a continuation as a function, then calling the function will run the rest of the computation.
10:36:54
lotuseater
thx you two :) I got it like it's some sort of runtime goto and then "all you need is call/cc"
10:37:47
nirnam
contrapunctus: tho I understand why emacs is a superior lisp IDE, vim is much more fitting in my environment
10:40:04
nirnam
it system adminstrator setting, I only doing lisp for curiocity, most of the time I have to ssh to a machine, get in, get out, go home
10:44:22
akater[m]
I have to say, there is at least one use case for the Info version of ANSI standard: full-text search is faster than in CLHS.
11:10:09
susam
Hello! Is hunchentoot a good choice for web server? I need something simple that can accept an HTTP request, parse its GET or POST parameters, send back a response, etc.
11:17:43
susam
lotuseater: Thanks. I have the documentation. It does seem to have what I need. My reason for asking here was to check if Hunchentoot is still a good recommendation or if the community recomends something else.
11:52:23
phoe
due to Liskov substitution principle, if you have FOO that is a superclass of BAR, then every BAR is a FOO
11:53:16
phoe
so (slot-value bar 'some-slot) should function if (slot-value foo 'some-slot) is a part of your documented interface
11:53:30
phoe
so, in other words, you can't do that and if you could then you shouldn't so that because you break LSP
11:53:59
hayley
.oO( Maybe lotuseater wants to do Self-esque protocols where methods can override slots, but this is Common Lisp, so we are doing generic function oriented programming... )
11:56:33
hayley
That kind of overriding is also done in Brachaware like Newspeak and Dart and I think it's almost doable in Lisp, if you think of the interface being generic functions and initargs for MAKE-INSTANCE.
11:57:19
lotuseater
I just have a class VERTEX (for graphs) with a slot DIRECTED of type boolean, so when T at inizialization it will be changed to class DIRECTED-VERTEX which should inherit from VERTEX but doesn't need the DIRECTED slot anymore necessarily.
12:00:20
hayley
Then the slot is unnecessary, and you could have a method like (defmethod initialize-instance :after ((v vertex) &key directed) (when directed (change-class v 'directed-vertex))) if I recall correctly.
12:03:01
phoe
which is, whether (make-instance 'verteX ...) is required to return something whose CLASS-OF is VERTEX and not a subclass
12:04:09
hayley
"The generic function make-instance creates and returns a new instance of the given class."
12:11:56
phoe
can be composition over inheritance, at which point a DIRECTEDP slot can work just fine
12:12:38
phoe
but I'd actually make a DIRECTED-MIXIN and UNDIRECTED-MIXIN and define DIRECTED-SLOT to have superclasses (DIRECTED-MIXIN VECTOR) because why not
12:16:16
phoe
that works too, but note that a lot of OO systems out there either do not have multiple inheritance or do but shun it
12:16:40
phoe
so in their context composition is storing stuff in slots, rather than mixing in flavors
12:19:05
hayley
Seems it would be Bracha-ware again as http://www.bracha.org/oopsla90.pdf talks about "inheritance mechanisms [being] subsumed in a new inheritance model based on composition of mixins".
12:31:22
akater[m]
lotuseater: “inherit all but one slot” sounds like you simply need to invert one link in the inheritance lattice. If you want a to inherit all but one slot of b, it should rather b inherit from a and add the slot in question.
12:37:31
pjb
Or you may neutralize a slot by overriding its accessor, as long as you do it preserving the Liskov Substitution Principle.
12:39:41
pjb
(defclass colored-square () ((color :initform 'red :accessor color) (side :initarg :side :accessor side))) (defclass square () ((color :initform 'nil))) (defmethod (setf color) (new-color (square square)) (error "a square cannot be colored"))
12:40:42
pjb
To do it cleanly, ie. as akater[m] said, you can also use mixins thanks to multiple-inheritance.
12:41:18
pjb
(defclass colored-square (square colored-object) ()) (defclass uncolored-square (square) ())
12:43:13
pjb
Most often, classes are defined without expliciting their invariants, and the pre- and post-conditions of their methods. Therefore the LSP is trivially ensured by assuming the trivial conditions and invariants (NIL and T).
12:43:47
pjb
ie. you use the object only to store data, and you can call the methods in any order whatever the state of the object.
13:12:45
nij-
Hello, if I understand correctly, when I run (ql:quickload :slynk), this line will be evaluated: https://github.com/joaotavora/sly/blob/master/slynk/slynk.asd#L112
13:13:31
nij-
This will in turn evaluate the file slynk-retro, which defines a package "slynk-retro" and some functions under that package.
13:13:55
nij-
However, I the package isn't defined and the functions aren't defined either. Something must be wrong..
13:15:14
pjb
nij-: quickload does several things. including asdf-load'ing the asd file, which evaluates that form, and this will only record the data structure for the system and its dependencies and components.
13:15:18
nij-
Now, in my $QUICKLISP/dists/quicklisp/installed/systems/slynk.txt , it does tell quicklisp to look at "dists/quicklisp/software/sly-20210630-git/slynk/slynk.asd"
13:16:08
pjb
nij-: it's when quickload then tries to compile and load the system that the data structure created by that form will be used by asdf to compile and load the files of its dependencies and its components.
13:19:23
pjb
Note that the system "slynk/retro" :depends-on (:slynk) so the system "slynk" will be loaded first.
13:19:45
nij-
It's weird cuz another system :slynk/mrepl is loaded automatically - https://github.com/joaotavora/sly/blob/master/slynk/slynk.asd#L92
13:20:24
nij-
And you can see, both systems are defined similarly. Why did :slynk/mrepl get loaded automatically, while :slynk/retro didn't?
13:21:42
pjb
not until you ask to load it either thru quicklisp or with (asdf:operate 'asdf:load-op :slynk/mrepl)
13:23:39
nij-
Opening a fresh-new repl => (ql:quickload :slynk) => (in-package :slynk-mrepl) #|succeed|# => (in-package :slynk-retro) #|error|#.
13:25:04
nij-
I've searched over the repl, there does not seem to be a form that load slynk-retro for me either.
13:25:39
pjb
nij-: note that systems are named with lowercase strings "slynk". Packages are named by strings, usually upper-case "SLYNK-MREPL".
13:26:31
nij-
In the repo the package SLYNK-MREPL is given in slynk-mrepl.lisp, which is only pointed by the system :slynk/mrepl.
13:28:05
pjb
anything can happen, it could as well define a package named "SANTA-CLAUS" or define no package at all.
13:30:34
nij-
AH turns out that without quickload-ing slynk gives me the package slynk-mrepl already.
13:31:02
pjb
I don't observe your behavior, and there's nothing in my slynk sources refering the slynk-mrepl pacakge.
13:31:38
nij-
I see. It must be that when I loaded sly from emacs, it loaded the mrepl config for me automatically.
13:35:32
tfeb
Yes, I set up sly and slime to do that but I forget how (but it's not in any lisp-side inits I have in git, and I can't see my emacs-side inits from here)
13:36:45
nij-
And I'm being extremely lazy on my emacs config.. currently using doom, which automatically does many magics tooo..
14:11:34
beach
It could have been created using MAKE-SYMBOL, or from UNINTERN of a previously interned symbol.
14:11:55
lisp123_
Perhaps I should then store gensyms into a global list upon creation and then check against that?
14:13:44
lisp123_
In 'On Lisp', PG suggests one could use genysm as a value for failing a test, if I were to go down that route, I would need to be able to check that the return value was a gensym created during the process and hence a failure
14:15:39
lisp123_
Yeah it seemed strange to me as well. A condition may work, I will have to play around with it
14:19:31
pjb
lisp123_: (let ((eof (gensym))) (eql eof (with-input-from-string (input "") (read input nil eof)))) #| --> t |#
14:20:31
pjb
lisp123_: (let ((eof (gensym))) (with-input-from-string (input "#:foo") (let ((foo (read input nil eof))) (list (eql foo eof) (symbol-package foo))))) #| --> (nil nil) |#
14:21:06
pjb
lisp123_: (let ((eof 42)) (with-input-from-string (input "42") (eql eof (read input nil eof)))) #| --> t |# WRONG!
14:21:45
pjb
the point of the guard value is to make sure it cannot have been used in the data structure for anything else.
14:23:00
pjb
We could as well use (let ((eof (cons nil nil))) …) or any other unique object identity.
14:24:33
pjb
(let ((eof (gensym))) (let ((data (with-output-to-string (out) (prin1 eof out)))) (print data) (let ((obj (with-input-from-string (inp data) (read inp nil eof)))) (list obj (eql eof obj))))) #| "#:g12402" --> (#:g12402 nil) |#
14:25:30
pjb
ldb: you wouldn't write an eof guard, you would just truncate the file. But you could write another guard object in some data structure, as long as you keep a reference to it, and ensure its identity is not lost by the serialisation/deserialisation.
14:27:04
pjb
(let ((empty (gensym))) (let ((data (list 'foo empty 'bar empty))) (let ((*print-circle* t)) (prin1-to-string (cons empty data))))) #| --> "(#1=#:g12410 foo #1# bar #1#)" |#
14:28:54
pjb
this is only the initial one, to know which ## is empty. There could be other shared references.
14:42:40
jcowan
When I need a unique object, I usually use (copy-seq "End of file object"), which is self-documenting but guaranteed unique, even if the compiler merges identical string literals.
14:51:26
jcowan
This actually isn'tt realistic in Scheme, because Scheme has a distinguished eof-object which you can gett a hold of by calling (eof-object) and can be tested for with (eof-object? obj).
14:52:43
jcowan
It has the advantage of being of a distinguished type. So you could in CL declare a struct and call itts constructor once.