CrashTestDummy2 has quit [Ping timeout: 272 seconds]
waleee has quit [Ping timeout: 255 seconds]
char has joined #commonlisp
d4ryus1 has joined #commonlisp
d4ryus has quit [Ping timeout: 252 seconds]
notzmv has joined #commonlisp
makomo has quit [Ping timeout: 255 seconds]
<loke[m]>
red-black trees are quite efficient for that.
akoana has quit [Quit: leaving]
hendursaga has quit [Ping timeout: 244 seconds]
hendursaga has joined #commonlisp
lisp123 has joined #commonlisp
flip214 has quit [Ping timeout: 255 seconds]
lisp123 has quit [Ping timeout: 255 seconds]
derelict has quit [Ping timeout: 256 seconds]
tyson2 has quit [Remote host closed the connection]
flip214 has joined #commonlisp
char has quit [Ping timeout: 255 seconds]
char has joined #commonlisp
<contrapunctus>
pjb, loke[m]: thanks, I'll look into those.
<char>
jasom: remember how you said that PBKDF2 was minimum for password hashing and should be used as defaul. in 10 years maybe it will be too weak but changing the default could break someone's application. What do you think of having no default and having an error if the library user doesn't set their own algorithm?
<beach>
Good morning everyone!
<White_Flame>
char: yeah, I missed the rest of the conversation, but that should be the way things are done. Everything needs at the very least a version number
<White_Flame>
instead of implicit assumptions about formats
<White_Flame>
and the same falls to APIs if they're to be long term
<char>
White_Flame: Do version numbers really help? I think most people are using quicklisp, and I thought, you could not specify version numbers for packages loaded by quicklisp?
lisp123 has joined #commonlisp
JoshYoshi has joined #commonlisp
Josh_2 has quit [Ping timeout: 272 seconds]
JoshYoshi has quit [Remote host closed the connection]
<beach>
I would appreciate help with other implementations as before. And I certainly wouldn't mind if someone were to write issues for other situations, like the DIGIT-CHAR-P I mentioned around 12 hours ago.
frgo has quit [Ping timeout: 272 seconds]
Bike has quit [Quit: sleep]
Inline has quit [Quit: Leaving]
lisp123 has quit [Ping timeout: 256 seconds]
cjb has quit [Quit: rcirc on GNU Emacs 28.0.50]
jeosol has joined #commonlisp
pjb has joined #commonlisp
char has quit [Ping timeout: 255 seconds]
contrapunctus has left #commonlisp [#commonlisp]
treflip has joined #commonlisp
contrapunctus has joined #commonlisp
CrashTestDummy2 has joined #commonlisp
CrashTestDummy3 has quit [Ping timeout: 256 seconds]
lisp123 has joined #commonlisp
shka has joined #commonlisp
lisp123 has quit [Ping timeout: 255 seconds]
rgherdt_ has joined #commonlisp
<gin>
any tips on when to use '(("name" . "alice") ("city" . "london")) vs. (list (cons "name" "alice") (cons "city" "london"))?
<gin>
I have heard that if we are going to mutate the list then we should (list (cons ... but if we are not going to mutate the list then we may use '((...
<gin>
But we almost never mutate the list. Even functions like PUSH do not mutate the list. they add a new element and update the place. so is it safe to okay to use '(( ... mostly?
<beach>
Sure, but with a few "but"s.
<beach>
First, PUSH is not a function. It is a macro.
<beach>
Second, if you do (PUSH ... (CDR LIST)) then you mutate the list, so you can't say in general that PUSH does not mutate anything.
<beach>
Third, are you really sure you never want to delete an element from the list, or update some value in any element?
trufas has quit [Ping timeout: 255 seconds]
<beach>
... like (SETF (CDR (ASSOC "city" LIST ...)) "birmingham") of the person moves.
djuber has quit [Remote host closed the connection]
djuber` has joined #commonlisp
<gin>
beach: In my code I am following the practice of never mutating the list (I guess that is a good practice?), so looks like it is okay for me to use '(( ... style?
<beach>
So what do you do if the person moves to a different city?
<gin>
beach: Apart from my specific circumstance, is there a best practice or recommendation between '(("name" . "alice") ("city" . "london")) vs. (list (cons "name" "alice") (cons "city" "london")) style?
<shka>
i have my personal guideline of that
<pjb>
gin: also, you may prefer to use keywords or symbols for the keys in a-list instead of lists, since by default, assoc uses EQL to compare the keys.
<beach>
If you are sure that the list will never be mutated, then a literal object is fine.
<beach>
gin: ^
<pjb>
gin: if you use strings, you will have to use (assoc "name" person-alist :test (function equal))
<gin>
beach: I update the .lisp file with the alist by hand and re-run some functions that make use of the new data. that is my current way of solving my problem.
<shka>
if the list never leaves place (a function usually) where it was created, it is fine
<beach>
gin: Wow, strange. But, sure, go ahead then.
<moon-child>
gin: I would not say it is 'good practice'. Avoiding mutations avoids certain types of bugs ('spooky action at a distance') and can sometimes lead to more elegant algorithms. But sometimes you have to bend over backwards to implement something without mutation, or compromise significantly on performance
<moon-child>
s/sometimes/frequently/
<pjb>
gin: you need to reload your source, if you mutate the literal objects because that means you've changed the source.
trufas has joined #commonlisp
<shka>
having said that, you may just have policy to not use lists for mutations
<shka>
or at least, not naked lists
<pjb>
gin: it's actually very dangerous, because the compiler can coalesce similar literal objects.
<gin>
shka: what is your personal guideline?
<shka>
if the list never leaves place (a function usually) where it was created, it is fine to mutate it
<gin>
shka: ok
<shka>
and never mutate lists that you did not create recently
<shka>
like: in the function scope
<moon-child>
shka: so you would not be willing to create a list, mutate it, and then return it? I think that that's reasonable
<gin>
another question. why use alist for key-value pairs instead of plist? I see that plist can also do everything that alist does, or am I wrong?
<shka>
so far it is fine
<moon-child>
I would say, rather, that one should generally follow the uniqueness rule (codified in clean's type system): only mutate objects which have only one referent
<shka>
this is... much more complicated rule to follow
<gin>
any views on my alist vs. plist question?
<jdz>
shka: Not sure your code mutates literal data, even if the scope is limited to one function.
* beach
keeps quiet. Too many people giving advice already.
nature has quit [Quit: leaving]
pillton has quit [Quit: ERC (IRC client for Emacs 27.2)]
<beach>
gin: What you are doing seems to be what is known as a "dictionary" in terms of abstract data types. You would typically design a protocol (= interface) for such a dictionary, and always use it. Then you can change your implementation when you like without changing client code.
<beach>
gin: You usually don't want your implementation details to propagate all over the place to client code.
<gin>
beach: ok
<beach>
gin: But I am sure you already knew that if you have programmed before in some other language.
<gin>
beach: but then I wonder in Emacs for example (I understand CL is not Elisp) but I am comparing approaches here, in Emacs, alist and plist are exposed to the user for defining properties. they seem to expose the implementation to the user. any views on this?
<gin>
I like that alist and plists are easy to type for the user that wants to specify configuration or some input data.
<gin>
so I made this decision of using alist as the implementation details as well as the user interface. is this uncommon in the CL world? seems to be very common in elisp world.
<gin>
the only unresolved question I have in my mind is "Why alists? Why not plists?"
<beach>
Then, I have no more advice to give.
<jackdaniel>
more elegant representation, like you have (operator . args) in alist you have (attribute . values)
<jackdaniel>
(arguably of course)
<moon-child>
does anyone if any implementations put literal objects in read-only memory, to more easily diagnose mutation of them?
<moon-child>
it seems like a simple, elegant solution (though it does come with a small, constant space overhead), but sbcl and ccl at least don't seem to do it
<moon-child>
actually, no, there needn't be any space overhead, using mirrored memory space; though tlb will bloat somewhat
<gin>
beach: your advice is well taken. don't mean to ignore what you said. it is valuable advice for an inexperienced programmer like me. still in the process of comparing various approaches and understand the pros and cons of each.
karlosz has joined #commonlisp
<gin>
I am guessing https://irclog.tymoon.eu/libera/%23commonlisp preserves chat logs in perpetuity, so I can go back and refer to these conversations anytime in future? or is there no guarantee and I must save these chat messages myself?
<contrapunctus>
gin: there's no guarantee of even your personal logs surviving, but yes, the channel logs will probably survive 😏
<gin>
contrapunctus: ;)
<gin>
contrapunctus: how does your emoticon appear as emoji but mine does not? do you copy the emoji from somewhere and paste it? or does your client support emoji?
frgo has joined #commonlisp
<contrapunctus>
gin: I'm using Conversations, and all too many IRC clients don't support emoji. That's all I know. ¯\_(ツ)_/¯
pve has joined #commonlisp
<shka>
moon-child: CL lacks concept of immutability
<shka>
everything is mutable
<moon-child>
(setf (car '(1 . 2)) 3)
<moon-child>
the behaviour of the above is undefined
<shka>
gin: honestly, plists are useful only as arguments in macros and the likes, where they look like good old keyword arguments
<moon-child>
I would prefer if an implementation signalled a condition for such code
hendursa1 has joined #commonlisp
<shka>
alist is most useful to have dict that behaves like stack (newly consed value shadows the inner value)
<shka>
but otherwise... nah
<shka>
unsuitable for storing large data sets because of linear lookup
<jackdaniel>
i.e if you have only a reader, tgen the slot is immutable
<jackdaniel>
also immutable data structures are a quality of the algorithm, not the language
<jackdaniel>
the latter may help to enforce that qualities
<pranavats>
jackdaniel: Can we not setf the slot-value still?
<jackdaniel>
can't you attach gdb to clojure process and mutate memory cell?
<beach>
pranavats: It is all a matter of conventions. If you can't trust your programmers to follow conventions, you need to find some different ones.
<pranavats>
Haha.
<beach>
pranavats: You don't export the name of the slot. Then, the programmer would have to use double package markers, which is a no-no.
<jackdaniel>
it is as with oop - it is a programming technique that may be used in assembly with some conventions (self-imposed ones)
varjag has joined #commonlisp
<beach>
pranavats: In fact, using SLOT-VALUE and (SETF SLOT-VALUE) is already a bad sign in client code.
<jackdaniel>
you may write a single block program in java too
<pranavats>
beach: Its a bad sign because its conventional to use accessor functions for that?
makomo has joined #commonlisp
<beach>
pranavats: It is a bad sign because slots are implementation details and implementation details should not be exploited by the clients of a module.
<jackdaniel>
programming languages are vehicles to put in flesh programming techniques - some vehicles put limitations on what you can do (i.e no faster than 50km/h), but you may drive 50km/h even in a vehicle capable of going 80km/h
Lord_of_Life_ has joined #commonlisp
<pranavats>
I see.
<beach>
pranavats: Whether some protocol function is a slot accessor or something else, should be transparent to client code, and it may change as the module evolves.
<beach>
pranavats: For example, you may have a protocol function AGE, but whether the age is stored in a slot or computed from the date of birth is unimportant.
<beach>
pranavats: And the maintainer of the module should be able to change this decision without affecting client code.
Lord_of_Life has quit [Ping timeout: 272 seconds]
Lord_of_Life_ is now known as Lord_of_Life
<beach>
pranavats: But this is not specific to Common Lisp of course. If you have done any programming in any other language, then you know that the rules are the same.
<gin>
i was about to ask that. these are general programming concepts, right? not specific to CL? I mean these nuggets of wisdom would serve well in other languages too, right?
<beach>
Yes, modularity is not reserved for Common Lisp in any way.
<beach>
It is elementary software engineering.
<gin>
I have mostly done scripting in shell and python, so I approach programming like scripting. what I am doing with CL right now is effectively write personal scripts to automate some routine tasks.
<moon-child>
to varying degrees. You must know the conventions of your language, and the extent to which encapsulation is expected and appropriate to a given task
<gin>
this conversation has me worried that I might be picking up bad programming practices while doing this. any book recommendations where I can learn good programming wisdom?
karlosz has quit [Ping timeout: 276 seconds]
<beach>
gin: Robert C Martin has some books I think.
<gin>
okay. will search for them. thank you.
<beach>
gin: The concept of modularity goes back many decades, so I am sure there are dozens of books written on the subject, starting in the 1970s or so.
<gin>
one more question about good coding style in CL community. I am checking UIOP source code as inspiration. Take https://github.com/fare/asdf/blob/master/uiop/package.lisp for example. it has many large functions. Within a function, all lines stick to each other. No blank lines at all between lines within a function. in Python this would be unusual, I see people often inserting lots of blank lines to make
<gin>
code equivalent of "paragraphs" and often each paragraph is preceded by comments "# Validate syntax.", "# Check if key exists in DB.", etc.
<gin>
so is it common in CL to write functions without any blank lines in between?
<beach>
If you feel the desire to insert a blank line in the middle of a function, it is likely that you really should make it two functions.
<beach>
gin: You usually insert one blank line between top-level forms. But no blank lines inside a top-level form.
<beach>
gin: Actually, most functions in that link are not so large. But it is special because DEFUN forms are often not top-level in that file.
<beach>
gin: So that file is probably not a good example of typical style.
<gin>
beach: ok. any file you can recommend from any source code where I can learn good style from? any file of yours is also okay. I want to keep one file as a reference.
<beach>
gin: Your request is unusual. The best way of learning these things is to look at lots of code by several other people, and then try to derive some guidelines from that.
<gin>
beach: thank you. I will read more code in future. just want a starting point to adopt some style. this link is good. looks very neat.
<beach>
Thanks.
Alfr has joined #commonlisp
<pjb>
gin: don't confuse large toplevel forms with large functions too. It's true that there are a few large functions in that file, but there are also toplevel forms (eval-when), that contain several functions. These forms can be large, but each function inside is small.
<pjb>
gin: since sexps can be combined like this, the "size" of an item can be non-obvious. It's like if you had a big python class with a lot of small def.
<pjb>
gin: now, for large functions, it may be also a side effect of formatting. Inserting too many newlines to fit artificial and ancestral 80 columns…
<pjb>
gin: otherwise, in general, more than the textual size of a function, it's the conceptual size that matters. when you have a function with a lot of check-type forms, for example, there's no conceptual complexity so you can discount those lines.
<pjb>
gin: what matters is that a function does a single thing, not to mix I/O with computation for example. etc. Then indeed, you should split functions into.
dsk has joined #commonlisp
<pjb>
gin: also, long functions can denote a procedural style: do this, then do that, then do that… and soon you've got multiple pages. Instead, if you think more in a functional style or in terms of combination of higher level operations, you will have a natural decomposition into subfunctions.
easye has joined #commonlisp
lisp123 has joined #commonlisp
amb007 has joined #commonlisp
lisp123 has quit [Ping timeout: 256 seconds]
amb007 has quit [Ping timeout: 276 seconds]
amb007 has joined #commonlisp
selwyn has joined #commonlisp
selwyn_ has joined #commonlisp
selwyn has quit [Ping timeout: 255 seconds]
pjb has quit [Ping timeout: 276 seconds]
kakuhen has quit [Quit: Leaving...]
dsk has quit [Ping timeout: 255 seconds]
frgo has quit [Remote host closed the connection]
frgo has joined #commonlisp
amb007 has quit [Ping timeout: 276 seconds]
amb007 has joined #commonlisp
CrashTestDummy3 has joined #commonlisp
CrashTestDummy2 has quit [Ping timeout: 276 seconds]
rgherdt_ has quit [Read error: Connection reset by peer]
Bike has joined #commonlisp
Krystof has quit [Ping timeout: 272 seconds]
recordgroovy has quit [Quit: leaving]
lisp123 has joined #commonlisp
char has joined #commonlisp
dsk has joined #commonlisp
lisp123 has quit [Ping timeout: 276 seconds]
char has quit [Ping timeout: 256 seconds]
PinealGlandOptic has joined #commonlisp
IAmRasputin has joined #commonlisp
Inline has joined #commonlisp
selwyn_ has quit [Read error: Connection reset by peer]
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
hendursa1 has quit [Quit: hendursa1]
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
hendursaga has joined #commonlisp
luis` has quit [*.net *.split]
Mrtn[m] has quit [*.net *.split]
susam has quit [*.net *.split]
^[ has quit [*.net *.split]
froggey has quit [*.net *.split]
hineios has quit [*.net *.split]
White_Flame has quit [*.net *.split]
etiago has quit [*.net *.split]
jcowan has quit [*.net *.split]
casual_friday has quit [*.net *.split]
xlei has quit [*.net *.split]
susam has joined #commonlisp
jcowan_ has joined #commonlisp
etiago has joined #commonlisp
etiago has quit [Changing host]
etiago has joined #commonlisp
White_Flame has joined #commonlisp
froggey has joined #commonlisp
casual_friday has joined #commonlisp
hineios has joined #commonlisp
xlei has joined #commonlisp
jcowan_ is now known as jcowan
dsk has quit [Ping timeout: 255 seconds]
kpoeck has joined #commonlisp
CrashTestDummy2 has joined #commonlisp
derelict has joined #commonlisp
CrashTestDummy3 has quit [Ping timeout: 255 seconds]
attila_lendvai has joined #commonlisp
^[ has joined #commonlisp
CrashTestDummy3 has joined #commonlisp
CrashTestDummy2 has quit [Ping timeout: 265 seconds]
Devon has quit [Ping timeout: 252 seconds]
ec has joined #commonlisp
sp41 has joined #commonlisp
vats has joined #commonlisp
nature has joined #commonlisp
selwyn has joined #commonlisp
lisp123 has joined #commonlisp
<pranavats>
There's a video linked on the chapter on GUIs in CL Cookbook of McClim applications running in a browser using Broadway protocol. Does anybody know how that was made to work? Is there any source code or instructions on how to do that?
<jackdaniel>
pranavats: I'd look in scymtym's repository for a branch with a name branch - he's the author of that backend
<jackdaniel>
s/name branch/name broadway/
lisp123 has quit [Ping timeout: 272 seconds]
thonkpod has quit [Ping timeout: 255 seconds]
<jackdaniel>
as of how this is possible - the api of the "browser side" in gtk is available to read, so this backend targets this api (as far as I'm aware there are two flavours - vector based and raster based, and broadway backend implements both)
<pranavats>
Thank you
<jackdaniel>
sure
<jackdaniel>
n.b. I've published a long overdue progress report on mcclim blog
<pranavats>
Reading it now. Thanks.
Inline has quit [Quit: Leaving]
Inline has joined #commonlisp
pranavats has left #commonlisp [Disconnected: Replaced by new connection]
vats has quit [Ping timeout: 272 seconds]
vats has joined #commonlisp
pranavats has joined #commonlisp
paulapatience has joined #commonlisp
thonkpod has joined #commonlisp
derelict has quit [Ping timeout: 245 seconds]
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
kpoeck has quit [Quit: kpoeck]
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
tfb has quit [Remote host closed the connection]
tfb has joined #commonlisp
<nature>
That's actually pretty crazy, never seen anything like that before!
tfb has quit [Remote host closed the connection]
<Inline>
what ?
<nature>
this mclim running in the browser
tfb has joined #commonlisp
<nature>
s,mclim,McClim,
<Inline>
ah
<Inline>
yah, are you using jupyter notebook ?
<Inline>
where did you get it ?
derelict has joined #commonlisp
<nature>
Also had an unrelated question, is there a go-to way to validate/parse safely user input? I saw this cl-data-format-validation package, is it relatevely safe to validate form data?
<Inline>
oh oh
<nature>
Inline: no I am not using jupyter notebook
<Inline>
afaik that's one of the hard parts in commonlisp
<nature>
Inline: where did I get what?
<Inline>
user input can be code executing
CrashTestDummy has joined #commonlisp
<Inline>
nevermind nature, i don't know the web interface of mcclim
tfb has quit [Ping timeout: 245 seconds]
<nature>
in the cl-cookbook there was a link to a video of prototype, someone mentioned it before you connected
amb007 has quit [Ping timeout: 272 seconds]
<Inline>
afaik one solution is to use another language or language framework for parsing inputs, i.e. an executable maybe written in C or so
<Inline>
which you use as an intermediary
amb007 has joined #commonlisp
CrashTestDummy3 has quit [Ping timeout: 256 seconds]
<nature>
arf, that would complicate my setup a lot, I am making a simple web app which does the basic CRUD operation through mito and I simply wanted to make sure that some data received via a POST request are number, dates, phone number etc...
<Inline>
well ok that might be doable in cl alone i think
<_death>
why wouldn't it?
<nature>
I am pretty sure I could manage with regexes but I wanted to know if there is a more "lisp way" of doing it
<nature>
I still am a beginner, I come up with weird questions like this sometimes ^^'
<scymtym>
the McCLIM Broadway backend prototype allows displaying and interacting with McCLIM applications in the browser. it uses a modified version of the javascript code which was originally developed for the Broadway GTK backend which does a similar thing for GTK applications. the McCLIM version differs from the GTK version in terms of events send by the browser and instructions send to the browser. the McCLIM version also generates
<scymtym>
javascript code for message (de)serialization at runtime
<nature>
That's impressive!
pjb has joined #commonlisp
<gin>
is there a function to compare the equality of two pathnames?
<pjb>
equal
<pjb>
(equal #P"~/" (user-homedir-pathname)) #| --> t |#
<gin>
So equal. I thought there would be a more specific function like there is stirng= for strings.
<gin>
If it is equal for pathnames I will use equal. thanks pjb
<Inline>
you can convert to string with namestring etc
<Inline>
if you want todo that
<Inline>
but that will behave string like so you loose the pathname specific stuff
<Inline>
like that ~/ is defined as user-homedir-pathame, or aliased or so