freenode/#lisp - IRC Chatlog
Search
8:00:09
splittist
I think the progress on SICL has been nothing short of amazing. Particularly when the offshoots - eclector etc. - are taken into account. And the talent it has attracted is impressive.
8:01:54
beach
Absolutely right. The independent modules have become impressive thanks to the qualified people who agreed to develop and maintain them.
8:19:33
splittist
hypercube: I don't think it ever left. Perhaps it hasn't grown at the same rate as other (newer) languages, but there are pockets of lisp we rarely hear about. (Perhaps because it's in law enforcement and intelligence.)
8:21:04
splittist
When LAMBDA for Excel drops later this year, and joins the fairly recent LET, we can claim lisp IS the language of industry (:
8:23:03
hypercube
im pretty new to common lisp and got into it mainly through taking a scheme course at school, but im surprised that programming isnt done that way more
8:23:39
Nilby
splittist: for printfcl (printf "%+0.ld % .0d %+0.0ld" 0 0 0) is not entierly valid, but seems to differ from the C version.
8:24:46
beach
hypercube: It shouldn't surprise you if you know how programmers are trained and chosen, and how little management knows about software development in general.
8:25:57
lukego
Hey what's the appropriate time to split code into a separate package? I only have a few KLOC of code and I'm feeling the urge to break this up into separate logical packages but I also have a feeling that's possibly just unproductive busy-work
8:27:13
beach
lukego: I break my code up into "modules", where each module resides in a directory, has an ASDF system definition, and a component (file) containing a package definition.
8:28:17
beach
lukego: I extract a module whenever I see a reasonable (usually CLOS-based) protocol emerging.
8:28:26
lukego
beach: thanks, I was looking for a reference example of that style, and see now SICL repo is such
8:28:50
no-defun-allowed
hypercube: It makes sense to me, given whoever runs the industry wants perhaps the opposite of people doing whatever they want (for the most part).
8:29:01
Nilby
splittist: I wrote a printf in a blub language and had some old test file around which I think I got from cygwin.
8:29:13
lukego
yeah I have the vague feeling that having everything in the same package is making it too easy to have murky interfaces that I am not thinking out
8:30:26
hypercube
do you have any recommendations if i want to get serious about common lisp programming? any good books or courses?
8:30:34
beach
lukego: Yes, that's the risk. Plus, now when we have package-local nicknames, having a package for each module is not a problem.
8:30:54
minion
hypercube: look at PCL: pcl-book: "Practical Common Lisp", an introduction to Common Lisp by Peter Seibel, available at http://www.gigamonkeys.com/book/ and in dead-tree form from Apress (as of 11 April 2005).
8:31:16
lukego
hypercube: I think that Common Lisp is used in industry, mostly quietly in small groups, and seems likely to continue that way. maybe it's healthy that the amount of CL used in industry is driven by the number of geeks learning CL and looking for opportunities to work with it. better than e.g. if Gartner told the S&P500 they all need to adopt Lisp and the mess that would create.
8:45:41
Shinmera
lukego: In my mind files are for the maintainer's organisational structure, and packages are for the user's organisational structure. If you don't have users, then it doesn't matter much, but as soon as you see a part that could stand on its own, it can be useful to extract it.
8:49:34
lukego
I'm mostly asking myself whether multiple package namespaces will be a plus or a minus e.g. using symbols like BGA-NAME verses BGA:NAME verses NAME. I'm a CLOS n00b here and it's already bothering me having the same symbol for unrelated slots of different classes e.g. NAME or ID.
8:49:42
splittist
With a sufficiently smart editing environment (tm) (and perhaps a sufficiently smart programmer...) files should be a backing detail, and the programmer should be looking at whichever 'view' of the code makes sense for the task at hand (e.g. methods grouped by function or by specialised argument)
8:50:46
Shinmera
lukego: But if you want to be stricter about it, as beach mentioned, design your protocols first, and separate them out into a package per protocol.
8:51:18
lukego
splittist: but now you're describing the environment that I switched /away/ from to work in Lisp :-) i.e. GToolkit in Pharo Smalltalk
8:53:38
lukego
splittist: but I'm not really in that school of thought -- I'm more into embracing the limitations of the file-based representation e.g. as a means of putting a narrative order onto code that is lost when you slice and dice it up
8:57:08
lukego
also as an old-school DEFSTRUCT kind of Lisp hacker it bugs me a bit with CLOS - and indeed with Smalltalk - that `M-.' doesn't hop you straight to the code you want but rather makes you scroll through to the relevant method even though that's usually painfully obvious to you as a programmer. but for better or worse I'm CLOS'ing this project
8:57:27
lukego
Maybe that copy of AMOP that I ordered a month ago will turn up one day and then I'll share everyone else's enthusiasm for this stuff :)
9:02:58
Shinmera
it would need to know the type of the arguments, which is usually not available because inference around CLOS is weak.
9:04:23
lukego
I'd like to have a DWIM version of `M-.' that jumps to some dynamic but predictable place e.g. the most recent method actually invoked from the callsite where I pressed `C-u M-.'
9:11:40
scymtym
the DREI common lisp syntax has some interesting ideas about semantics-aware editing regarding completion and "undefining": https://github.com/McCLIM/McCLIM/blob/master/Libraries/Drei/lisp-syntax-swine.lisp#L434 (too bad that the more abstract parts are mixed up with the editing functionality)
9:14:59
lukego
(actually it could be an interesting form of "JIT" if SBCL would compile two copies of a function, one with lots of instrumentation for debugging and editing and so on and one without, and then enable the fast one only when it's actually "running hot")
9:15:56
lukego
Or maybe I'm dreaming of the Bad Old SBCL that had an interpreter that it used sometimes
9:16:56
lukego
I think I've asked this before but it's way too early to do real development in a SICL-hosted-on-SBCL, right?
9:17:07
no-defun-allowed
A JIT would still instrument in order to know when to give up on an optimisation, and a good one would still preserve semantics of the slow code.
9:19:10
lukego
no-defun-allowed: I meant without the various downsides of a highly dynamic JIT i.e. you still compile the same statically optimized machine code ahead of time but you also have a slow/instrumented version that you can swap in whenever you like e.g. to say "the next time we run that function let's log how each method invocation is resolved and store that for reference by an M-. command"
9:19:35
lukego
beach: SICL is more about the long game of having a complete environment unto itself right?
9:22:27
lukego
(aside: it's remarkable how much instrumentation you can put into machine code on modern out-of-order CPUs without having much impact on performance e.g. conditional branches to hooks that are speculated away by the CPU)
9:24:03
lukego
beach: SICL sounds great but as a humble practitioner I'm not sure how to connect it with anything I'm doing
9:34:37
h4ck3r9696
I have a problem with usocket: sometimes, when I try to use wait-for-input, it throws an exception: "couldn't read from #<SB-SYS:FD-STREAM for "socket 192.168.0.46:4444, peer: 192.168.0.27:35932" {1007AA9A43}>: Connection reset by peer [Condition of type SB-INT:SIMPLE-STREAM-ERROR]". I don't think this is normal, but if it is, how can I fix this?
9:36:42
Shinmera
It means your connection was terminated. You "fix" it by either somehow having internet that never breaks, or handling the error and establishing a new connection.
9:44:46
beach
lukego: Right, it is not meant for you (at the moment). Once the environment is in working condition, I hope you will see some nice features.
10:15:32
splittist
ACTION realises he's had Harbison & Steele on his shelf all along; proceeds to schedule printfcl rewrite
10:25:16
hhdave
ikrabbe (or ikrabbe|2): I noticed over on #clim you were talking about using CL for devops. I'm doing that these days using https://github.com/Virtual-Insurance-Products/cl-sysop (which I wrote). I handled the executing commands on remote systems bit - it can bounce over several systems via SSH (also uses zlogin for executing things in SmartOS (solaris) zones). It handles all the shell quoting.
10:45:17
ikrabbe
hhdave: Thanks for the note. I first transfer the sequence of commands send to a system into a list. I scan this list with a recursive function. That is a bit more complex, but far more flexible, as I searched a general solution for a common problem. The quoting is done by the structure of the list.
10:59:05
hhdave
ikrabbe: oh right. In my system I have a method which makes a command for a certain host which consists of a comamnd name and a list of arguments. I'd be interested to see what you come up with. I think there are other implementations of similar things. I've built up a system for declarative devops using CLOS.
11:02:27
ask6155
I want to return a list with the items in the list x plus some more items at the end
11:05:45
no-defun-allowed
Huh? '(x y) and (x y) are not equivalent. The former evaluates to the latter though.
11:06:42
Nilby
ask6155: Just be aware that the last argument to append must be a list e.g. (append '(1 2) (list 3)) => (1 2 3)
11:14:04
ask6155
I'm using common-lisp and in append I had to make all arguments lists like this '(x) I cannot use 'x it gives an error 'x needs to be a list. I have 3 args and x is the first
11:16:44
no-defun-allowed
If you have a list bound to X, then the call should look like (append x (list other elements here))
11:19:51
no-defun-allowed
'x and x are not equivalent under evaluation, but I suppose reality is not being communicated well when someone who writes A LARGE POPULAR LISP APPLICATION is telling people that sort of nonsense.
11:21:33
no-defun-allowed
ikrabbe's suggestion to use quasiquotation would also work, e.g. `(,@x 1 2 3)
11:22:13
no-defun-allowed
Note that 1, 2 and 3 there are not evaluated - well, append would work fine for now.
11:23:38
Nilby
If someone can succeed despite my technically wrong advice, then they might have a chance with the harder stuff.
11:25:12
lukego
speaking of things having to be lists I have a function (defun listify (x) (if (listp x) x (list x))) and was surprised not to immediately see it already existing in CL / alexandria / serapeum unless I missed it?
11:26:15
lukego
no-defun-allowed: yes! fool that I am, I was looking for LISTS in the alexandria docs ToC and totally overlooked CONSES
11:26:49
no-defun-allowed
Nilby: The qualifier "technically" isn't necessary; that is absolutely confusing advice.
11:35:05
no-defun-allowed
And, from my point of view, progress was made in part because I had to correct you and jmercouris, and I would prefer to not have to do that.
12:02:55
lukego
are you chastising people for the quality of the free help that they are offering in good faith to strangers on the internet? that's harsh :)
12:24:47
ikrabbe
not when they lead people in the wrong direction, though the critic was a bit strong, for a little quote :)
12:28:43
ikrabbe
ask6155: it took myself a good amount of time, to realize that append can be replace, especially in situations, where the result is not known: (apply #'append '(a-list) (return a few lists, to be appended)) is far more complex, than `(,@a-list ,@(return a few lists, to be appended))
12:28:57
rodriga
has anybody here ever worked in a Lisp startup? or have any connections to a Lisp startup or "internships"?
12:38:26
mfiano
Whenever I see #'append in my code, I consider it a red flag and I stop and think very carefully whether it can be expressed in a more efficient manner.
12:48:59
ikrabbe
As you first learn about quasiquote as "the somehow used macro definition leader", it is replaced by append when you begin your list juggling.
13:15:33
ikrabbe
I think quasiquote is a quote good word, to express the function of the backquote character (at least far better than "the somehow used macro definition leader")
13:16:26
lukego
rodriga: I've worked in a Lisp startup and have a new embryo-phase Lisp startup now. what are you wondering?
13:22:57
ikrabbe
mfiano: I just wikipedia'ed the word and found that quasiquote is actually a semantic concept of quotation, that matches our usage very well.
13:25:47
ikrabbe
https://plato.stanford.edu/entries/quotation/#CornQuasQuot :D There are more modes to quotation, we might be able to adapt ;)
13:25:58
lukego
I guess that if one is looking for a lisp job/internship that list of Lisp companies is a good place to look. I only saw this for the first time this week. https://github.com/azzamsa/awesome-lisp-companies
13:28:13
mfiano
ikrabbe: It is the same concept. My point was that it is not a defined term in the Common Lisp standard. It was borrowed from Scheme to mean the same thing as an existing term in our standard.
13:40:30
jcowan
It's also used in Bourne shell terminology: '...' is quotation, "..." is quasiquotation
13:42:12
jmercouris
no-defun-allowed: pretty sure if one form evaluates to another they are equivalent...
13:42:19
Xach
if you are uncomfortable with all the mysterious unquoting rules, it's queasyquotation
13:50:06
beach
jmercouris: There is nothing wrong with the relation "evaluates to". It is reasonably well defined in Common Lisp.
13:53:24
seabass[m]
I was under the impression that it was macros that ran at compile time, rather than functions
13:56:13
beach
No. Most modern Common Lisp systems compile on the fly, so there is no interpreter present.
13:57:37
Xach
beach: doug k had a very interesting example of how adding an interpreter to SBCL made parallel compilation faster
13:58:55
seabass[m]
did you know that your blurb is at the top of http://www.gigamonkeys.com/book/ ?
13:59:14
aeth
I don't doubt that you could do everything as a function but... this really does seem like a place where macros are more straightforward. Read/parse file at macroexpansion time, generate DEFCONSTANTs. The only issue is that macros can be evaluated more than once (and SBCL often evaluates them twice), so side-effects (including reading a file, I guess? it would happen twice) are discouraged.
13:59:23
Xach
beach: basically, if you have serial dependencies A, B, C, interpreting A and B with an interpreter only to provide the required compile-time side-effects of the code allowed C to be compiled before A or B is compiled.
13:59:50
Xach
beach: of course, this requires a complex and fast interpreter optimized for that purpose...not a "traditional" interpreter that helps with debugging or macroexpansion etc
14:01:10
beach
aeth: Entirely possible. Since I don't understand the problem statement, I was merely asking a question.
14:01:28
aeth
seabass[m]: even simpler than that, you can just check to see if the constants already exist, maybe?
14:01:56
seabass[m]
aeth, sorry what do you mean? This is a particular set of data specific to my program
14:03:02
seabass[m]
By using constants I can avoid this huge JSON file being parsed every invocation, and also make the binary 'portable' by not needing a /usr/share dir
14:03:16
lukego
ACTION gets some popcorn, has never really grokked the intersection between compile time evaluation and macro definition
14:03:54
Xach
lukego: when the interpreter was being developed (a long time ago), i thought it would really help for interactive debugging, but it's really just to avoid the overhead of the smart compiler generating nice code.
14:05:15
aeth
seabass[m]: If you're using DEFCONSTANT it will be an error to redefine it on recompile. Two issues. First, it can run multiple times (wasting the later efforts assuming that the two definitions match). Second, if the file changes it will just error on recompile.
14:05:51
aeth
seabass[m]: The easiest workaround would just be to use a global, which at that point can just be done at the first run (assuming that it's a program or a framework, and not a library with many entry points)
14:05:57
lukego
aside: edebug for emacs has wonderful user experience for interactive stepper-style debugging, based on a metacircular interpreter afaik
14:06:25
Xach
lukego: allegro and lispworks are really fast too. it's interesting to see the kind of mindset that develops around many (most?) users of free CLs thinking SBCL is the only way to go and the best at everything
14:06:31
seabass[m]
Maybe I should give you an overview of what I'm trying to achieve more generally
14:06:57
seabass[m]
Essentially, I've got this big JSON file. The JSON file is updated every few months
14:07:36
seabass[m]
the end user would need to download my source code, and then download any version of the JSON file into the source directory
14:07:54
seabass[m]
Then compile, and boom all the constants are there and the program never needs to read a JSON file again
14:08:32
seabass[m]
If I manually wrote the constants in the Lisp source, I'd need to change them manually at every release of the JSON data
14:16:30
lukego
seabass[m]: I guess it's two related problems. One, how to load the data at compile time, perhaps with EVAL-WHEN; two, what to do with that data after it's loaded, e.g. keep it in a list that you lookup from, or translate it into Lisp-level compiler constants via macros.
14:20:28
lukego
I really don't have this stuff swapped in but I am also curious about what is the idiomatic solution :). Maybe it depends on the way in which you're compiling your application e.g. into compiled modules (fasls) verses as a snapshot (image)?
14:22:56
lukego
I hope that I'm not side-tracking you here but one relevant feature that Lisp has is being able to snapshot the whole Lisp process into a file -- basically a coredump -- and then run that again later. it's like a suspend-to-disk and all of the data you have loaded is included. I'm not sure if/how this applies to your situation though
14:23:50
seabass[m]
hmm that sounds cools but probably a bit advanced for me as well as my target userbase
14:25:10
lukego
I don't quite follow what the interface for your end-users will be. are they getting a stand-alone binary from you? or are they really getting source + json? and you plan to ship those on different schedules e.g. new lisp daily but new json monthly?
14:25:51
seabass[m]
The releases that I make will always use the latest combination of JSON + Lisp code
14:26:14
seabass[m]
But if my users want to use a different version of the JSON, they can download them seperately and create that binary themselves
14:27:17
lukego
Maybe consider building on Xach's buildapp? https://www.xach.com/lisp/buildapp/ iiuc that's a simple way to create stand-alone executables that can easily load both code and data during build.
14:27:48
Xach
i like and use buildapp but investing time in learning how asdf's binary building works is probably better
14:28:02
beach
seabass[m]: Maybe if you remove JSON from the discussion, and just let us know what the parser for the JSON file would return.
14:28:35
beach
seabass[m]: And then, tell us what you want that result to turn into, in terms of Common Lisp forms.
14:29:33
seabass[m]
beach, it would return a list, containing a list of two keywords and their values each
14:29:40
Xach
i couldn't figure out cl-launch, so i made buildapp, which is simpler. then asdf was updated to be a little simpler than buildapp (i think)
14:31:52
beach
And what would you like your Common Lisp code to look like as a result of that example?
14:34:25
beach
Sure. But I don't see anything in your example that would suggest a Common Lisp name that could be used in a DEFCONSTANT form.
14:35:13
beach
seabass[m]: It would be even better if you explain what you want without reference to programming languages that some people here might not master.
14:35:37
seabass[m]
beach, fair enough, but I'll have to think longer to get it into 'lispy' formats :)
14:36:39
beach
seabass[m]: So neither the keywords not the string literals can be used as the name of a Common Lisp constant. Therefore, you need to tell us what name you would like for your example.
14:37:26
beach
seabass[m]: Then, you need to explain what you had in mind when you thought it was possible to use keywords as names of constants, but then your example has duplicates, which would mean defining a constant in two different ways.
14:37:56
seabass[m]
I guess I'd like to have one constant that is a list, where each item has keyworded values
14:39:26
beach
Still, the duplication will be a problem. It doesn't make sense to have a plist with duplicate keys.
14:39:42
lukego
I have interpreted seabass[m]'s questions totally differently and made an example which may or may not be confusing and irrelevant :) https://gist.github.com/lukego/44ee65e9d2ed9587c91338d237f27fe4
14:39:49
seabass[m]
So, is there a way of populating such a plist in a loop (which can ignore duplicate keys), and then 'set that it stone' for the binary?
14:40:49
beach
seabass[m]: That's trivial. If you have the list in your example, then just turn it into (defconstant +mumble+ '((:a "string" :b ...) (:a ...)))
14:41:36
lukego
This example runs standalone.lisp that creates the executable ./standalone. This executable includes the contents of the file /etc/protocols at the time that the executable was created. Running ./standalone will print the contents of /etc/protocols -- not by opening that file but by "remembering" the value that was compiled in.
14:41:40
seabass[m]
great! So I populate a variable, and then defconstant it into a constant, all within a 'at compile time' section?
14:42:17
seabass[m]
That's pretty much what I wanted do to; can that be compiled into a binary and still work?
14:42:36
beach
seabass[m]: Or perhaps (defconstant +mumble+ '((:a "string") (:b "...") (:a ...) (:b ...))) or even (defconstant +mumble+ '(:a "string" :b "..." :a .... :b ...))
14:42:44
lukego
well in my interpretation the defconstant business is just a distraction. all you need is to have the data passed from compile time to runtime. the details of how you parse it, how you store it in variables, etc, are up to you and straightforward once you grok the bit above
14:43:05
lukego
seabass[m]: Yes. The --load will have the side-effect of creating ./standalone which is an executable.
14:44:21
lukego
The way it does this is basically to "core dump" into that file -- i.e. suspend the Lisp process to disk such that it can be resumed in a new process -- but that's not really a scary thing in Lisp, and it's handy because all your state is preserved e.g. values you have loaded from disk or libraries you have loaded etc (but not open files/sockets/etc of course that die with the process and don't persist)
14:45:41
lukego
Maybe if you take this approach you could just parse the JSON data at runtime if that makes it easier to think about. You can still have the JSON data loaded at runtime and stored in the executable -- but it's probably not necessary to translate it into Lisp code since if you have it in a Lisp string you can just parse it into a Lisp data structure at any time.
14:46:34
seabass[m]
There's a portion of the JSON that'll never be needed for my program, so I think it probably makes sense just to save the data I need
14:49:03
lukego
So what you have here is really a general suspend/resume facility. You can decide what data you want to have in the process at the time you do the suspend. In this example you have the raw contents of the file stored in a variable, but you could instead e.g. pass that to a function that extracts only the part you need, or compresses it, or parses it and stores the parse tree, or translates it into lisp code, etc.
14:50:13
lukego
Since the suspended Lisp process includes the whole Lisp compiler you should also be able "at runtime" to load in new data and generate a new executable containing that instead.
14:52:18
lukego
So basically it's very wasteful by the standards of the 1990s. By today's standards I'd call it borderline restrained.
14:53:06
lukego
anyway, it's a starting point if you want to get up and running, quite possibly you'll find a better solution later if you want to reduce your file size etc.
14:53:57
lukego
(maybe other people have better suggestions for you, I'm only taking the time now because it looked to me like you were getting side-tracked with thinking about how to represent JSON data as Lisp code, when it really seemed like your main problem was just embedding some data in your program)
14:58:08
seabass[m]
shka_, M-x find-function RET indent-line-to RET, just in case you're interested anyway :)
15:00:02
lukego
shka_: one example, https://www.researchgate.net/publication/242313131_Using_the_new_common_Lisp_pretty_printer
15:01:16
beach
seabass[m]: No, it is not fine. It doesn't have a good idea of what the code in the buffer represents, so it often gets indentation wrong, and it confuses non-forms and forms.
15:01:40
lukego
decades of Emacs use and no foot pedals, then I took up soldering and suddenly I have five under my desk right now :)
15:01:57
seabass[m]
beach, that's funny, I've never had any issues with that. But then again, I'm not too advanced at Lisp right now, as you can see :)
15:03:41
shka_
beach: i think that emacs has a few extra benefits for people who program in multiple languages
15:04:14
beach
shka_: Yes, but I was answering: <seabass[m]> It surely must be the best Lisp editor in existence
15:04:15
mason
seabass[m]: I think it's probably worthwhile since Emacs, despite protestations, is in fact modal. "I've got the control key down" is a mode.
15:06:20
beach
lukego: I would like a keyboard with a much more narrow space bar, and I would like the extra space to be used for control and meta, one for each thumb. I take it Japanese keyboards are like that, but for different reasons.
15:07:31
lukego
beach: yeah. I always shop for the keyboard with the narrowest spacebar that I can. ironically it means wanting a Windows key. the best I can usually do it having Space flush with the left of C e.g. on my Thinkpad and Mac keyboards. Sometimes it comes out below X and then I get hand cramps reaching for Meta.
15:08:20
lukego
though I only use my left hand for modifiers I think. pinky for control (capslock) and thumb for meta.
15:08:27
pjb
lukego: https://groupbuys.mechboards.co.uk/shop/hyper-7-keyboard-r3/ has a small space.
15:08:52
lukego
once upon a time I had my spacebar mapped to a Hyper key but I was in a bad place then and stopped escalating my keyboard hacks as the hand cramps started :)
15:08:57
seabass[m]
lukego, me too unless my left hand hurts, then I use my right hand for modifiers for a few hours
15:10:47
lukego
I have been gradually expanding my notion of what is a reasonable price for a keyboard as I keep on buying more and more cheap and crappy ones and wishing I'd been less stingy :)
15:11:08
lukego
but just using the thinkpad now, and Barrier to share the laptop keyboard/mouse with the desktop.
15:12:23
lukego
seabass[m]: cool :) it's a great piece of software! though one day I must work out how to get it to auto-start on startup. each time I reboot one of my machines I end up fishing out a backup keyboard/mouse to manually start barrier with :). maybe I could just start it from the command-line, have to check that..
15:13:08
lukego
I suppose actually that barrier makes total sense as a text-based command line application, I wonder if it has such a mode, it's awkward to start in GUI mode since in principle I don't have a keyboard/mouse on the client machine
15:15:23
lukego
thanks but I'm on NixOS so that'll be another whole kettle of fish to integrate the script into and I don't have the motivation just now :)
15:16:16
lukego
I can't remember what sin I am atoning for by using NixOS but it's probably a whopper
15:29:22
lukego
Here's my latest abuse of unicode, this time because (required-argument) takes too much horizontal space:
15:42:03
lukego
yeah. I never give that name though because I'm always bothered about the verbosity.
15:42:35
lukego
(and because often the reason I'm using defstruct in the first place is because I couldn't stand the redundancy of defclass :))
15:44:04
lukego
but it's nice to let my hair down and allow myself to indulge some symbol/reader macros and funny syntax sometimes too.
15:45:03
_death
it's easy-defclass to those who know and love it.. for others it's "oh man, now I gotta learn another stupid defclass shortcut library to understand this form"
15:47:40
lukego
yeah. I guess I've been struggling and failing to get the taste for CLOS for like twenty years now so a crutch might be helpful. but I do have AMOP on order.
15:52:59
lukego
I have made one apparent step forward by factoring slots out into mixins like (defclass indexed () ((index ...))) when I often use the same slots in various classes
15:53:28
lukego
(defclass foo (indexed banked sided) ()) saves a lot of text compared with entering the slots manually every time.
15:55:30
beach
lukego: There is redundancy in DEFCLASS only if you don't care about modularity and consistent protocols.
15:56:34
lukego
beach: so the Erik Naggums of the world keep telling me, but I don't believe it's as black and white as that.
15:57:32
beach
lukego: In practice, not every slot should have an :INITFORM, not every slot should have an :INITARG, not every slot should have a :READER, and not every slot should have a :WRITER.
15:57:57
lukego
to me it sounds like saying that Java class definitions are only verbose if you don't care about scope, mutability, and allocation policy. but that doesn't excuse typing "public static final ..." ten thousand times
15:59:17
jmercouris
lukego: here is an example of us using it: https://github.com/atlas-engineer/nyxt/blob/master/source/blocker-mode.lisp
15:59:51
lukego
jmercouris: thanks! I'll try joining you at the philistines table and see how I fit in :) but I am guessing that reading AMOP will change my idea of what is appropriate, for better or worse, and I don't know in what direction
16:00:36
beach
jmercouris: Yes, it is no doubt quite convenient... if you don't care about modularity and consistent protocols, like I said.
16:00:46
lukego
beach: I'm often just creating internal data structures and not public interfaces. the way in other languages one might use a throw-away dictionary or tuple.
16:02:55
beach
lukego: Even for those, it pays off to think about what kind of options you want to give to MAKE-INSTANCE, what slots you want to be writable, etc.
16:03:47
jmercouris
If Encapsulation is important, you’ll end up writing getters and setters anyways
16:04:39
jmercouris
Talking about using class instances as a way to pass state around , instead of thinking about them as objects
16:09:46
beach
In particular, you may not want to use :ACCESSOR if you want client code to read the slot, but not write it.
16:10:49
mfiano
I even go as far as to define a %-prefixed accessor in addition to a reader that is exported, rather than use slot-value for internal code, since it is often wanted to extend that protocol
16:12:57
mfiano
If I don't want users to write, I'll export a symbol used for :reader, and give myself a non-exported symbol for :accessor/:writer
16:13:22
jackdaniel
howerver given that you bother to write down how to use your system and you do not mention the writer (setf foo), then if someone uses it then it is violating the library protocol
16:14:16
lukego
This may shock you guys but I sometimes even pass around data as *lists of atoms* :)
16:14:18
beach
jackdaniel: Sure. But it is good to give warnings or errors in case of incorrect use.
16:16:00
mfiano
It surprises me at how many codebases use the same symbol name for the slot as the accessor (in the general sense, not :accessor)
16:16:13
jackdaniel
beach: I tentatively agree but one could consider adding (setf %extra) accessors clobbering from the code perspective (and one more sub-protocol to keep in mind when working on the system)
16:17:52
pve
lukego: you might use emacs to generate an initial defclass form for you, and then edit as necessary
16:17:52
lukego
The whole "ravioli code" concept with layers of empty calories between every tiny morsel of meat :)
16:19:21
pve
you end up with a defclass form that everyone understands, without having to type it all out
16:19:50
lukego
This is the big challenge with CLOS for me. I don't /want/ to agree with what you guys are saying :) I like the kind of Lisp code that Peter Norvig writes and he's more likely to use DEFCLASS with :TYPE LIST than any of this business
16:22:03
lukego
but maybe it is more of an applications verses libraries thing. I'm writing code that I expect to churn quickly and not be seen by anyone else's eyes before being rewritten a couple of times. so it doesn't seem rational to spend time worrying about how a hypothetical unknown third party might interact with this code. different situation if you're pushing libraries to github/quicklisp.
16:24:04
jmercouris
All of the advice so far has been given within the context of third party consumers and some robust foundation
16:25:42
lukego
I can also understand that if you spend time teaching people to program in Lisp, you will want to be focusing on the best practices for doing this properly, since people can always use their judgement to take shortcuts later.
16:26:28
lukego
I'm reading some ACL2 code that has page-long definitions on which each line is of the form (defun foo-quux (foo) (caddddddddddr foo))
16:26:51
Xach
there's also a big difference between "there's no reason for [the way defclass works]" and "i don't like how it works" or "the problems that it solves aren't that important to me" etc
16:26:58
beach
jmercouris: I am saying that DEFSTRUCT is already a way to make your code more modular and with defined protocols. If you don't think you need such things, there might be no point in using DEFSTRUCT either. Lists could be more flexible.
16:27:09
lukego
so even for throw-away code I appreciate easy ways to get accessors, places to hang print functions, etc.
16:28:17
lukego
beach: that's a good point. in other languages I would do exactly that e.g. if they have pattern matching to make it convenient. could well be that in serapeum there are such facilities and some of my structs could be lists because I don't need dedicated accessor functions.
16:28:41
Bike
i wish structure objects were defined with defclass, and defstruct was a library macro to define accessors with convenient names
16:28:48
lukego
ACTION makes mental note to read some idiomatic serapeum code e.g. implementation of serapeum itself
16:30:05
jackdaniel
Bike: in the vast undefined behavior (defclass foo () () (:metaclass structure-class)) works on some implementations
16:31:19
splittist
mixins and generic functions are a great way to allow for unforeseen behaviour modification. And every time I worry about performance I tell myself the world now runs on javascript over the network.
16:31:27
lukego
Gnuxie[m]: I do a lot of rewriting. I'll probably rewrite all this particular code at least a couple of times before I share it with anyone else. I've already rewritten much of it once.
16:31:29
Bike
you'd probably have to do something funky to ensure the class is defined at enough at compile time to allow subclassing
16:32:09
jackdaniel
ah, that's it, I've tried redefining foo, when I define a "fresh" class, then I can put slots in there
16:33:19
Bike
defstruct has to do funky stuff of that kind. defstruct is kind of entirely funky stuff
16:35:18
pve
lukego: I once worked on an old application that stored everything (or a lot, anyway) in symbol plists. A curious design choice, but it did work..
16:36:06
lukego
pve: thank you for normalizing the use of whatever quirky representation one prefers in the privacy of one's own codebase :)
16:36:32
Xach
If your program does something very useful, people will often adapt to it, rather than demand vice versa
16:37:03
mfiano
THat's a major problem with Lisp. People often care more about the code than the artifact
16:38:14
Xach
It's a problem with many forms of endeavor - obsession with the tools and their proper use rather than the product of the tools. But there's no denying that a nice tool, used properly, is a delight.
16:38:36
lukego
I'll admit that I allow myself to spend much more creative energy on editing Lisp code than most other languages. I enjoy that though. keeps me amused while I'm programming
16:38:45
Xach
ACTION thinks of people who post pictures of their workbench and planes rather than the useful objects produced with them
16:39:04
Shinmera
I hate my level editor a whole lot, but simply don't have the time to make it nice.
16:40:15
pve
lukego: but to be fair, it was written mostly by computational linguists who only wanted to get the job done
16:41:12
Shinmera
Well the most pressing deadline is me running out of money, so I have to be very smart with that.
16:41:36
Shinmera
Other than that we also have a release schedule we're aiming for, which is roughly 2 years from now.
17:13:42
_death
jackdaniel: I'm surprised ;).. I expected some resistance, at least for the draw-arrow stuff, if not the keybindings (which I supposed must have had some good reason not to be there in the last 20 years)
17:17:40
_death
jackdaniel: cool :).. I also had to patch the coordinates stuff, which currently has exact comparisons incl. on floats that causes trouble with ellipses, but I noticed the commented version and some old mcclim-devel discussions and some issues on github so I thought another approach may be on the queue
17:18:38
jackdaniel
I want to change the ellipse representation from parralelogram to something more stable (transformation-wise)
17:19:20
_death
yeah, that's one of things I gathered.. the exact comparisons may caused issues elsewhere too
17:19:58
jackdaniel
comparisons are one issue, but the current code can error because of a non-reversible transformation (due to rounding errors)
17:21:09
_death
right.. there are two issues.. the inversion is easy to reproduce with the Fig example, and the comparison is easy with https://www.artm-friends.at/rm/kytron/kytron-clim.html (after small tweaks to make it work)
17:30:21
_death
I also have some changes to scigraph, but it may be that it doesn't work right only for me.. I guess the most annoying issue right now is the repeated mapping and unmapping (with lots of match error 42) that happens if I switch windows in stumpwm, usually once per application frame.. also, (setf clim:*default-server-path* :clx) looks cool and retro :)
17:33:47
_death
(to make clear, this issue is not limited to scigraph.. it often happens with any arbitrary application frame)
18:36:18
albusp
Trying to get sly working with emacs, currently I don't have slynk running (no lisp process active), and indenting code in *.lisp files gives the error "Symbol’s function definition is void: sly-common-lisp-indent-function". I'm checking sly.el and others, and found a line in slynk.lisp mentioning the function: https://github.com/joaotavora/sly/blob/e927cdae984b2c3383e1e2358e37f1a4115b142e/slynk/slynk.lisp#L3996.
18:37:55
albusp
slynk is not yet running because it doesn't compile on abcl (yet - i'm trying to fix it)
19:06:26
contrapunctus
"Who needs DEFSTRUCT anyway. You can just use CAR/CDR." lol I had to do a double take here, until I read the previous message 😄