libera/#commonlisp - IRC Chatlog
Search
12:33:44
rotateq
I had a CLOS question in mind recently, but then I realized it was again easier than I thought. :) Just how to use FIND-METHOD correctly if a parameter in the lambda list is specialised with eql.
13:58:40
mfiano
I am working with a function that calls externals OS processes and returns a string as the result. This string consists of substrings delimited by tab characters and terminated by newline characters. What would be a decent way to produce a list of lists from this string, where each inner list represents the string cells of each column for a row, and the outer list contains these lists of rows?
14:04:59
mfiano
I never thought to use a csv parser, in part because I didn't know they supported other delimiters.
14:05:50
_death
this specimen seems like it's of a family of formats are usually known as tsv (tab-separated values), analogous to csv
14:07:23
mfiano
(The command I am calling has a switch that removes the first line of column names and transforms arbitrary numbers of whitespace to single tabs)
14:07:55
mfiano
It's meant for easier machine readability, though I do have the option of not using that switch if it makes it easier for Lisp
14:12:45
mfiano
I'm reviving a few thousand line shell script I wrote about 6 months ago, but it outgrew my least favorite host language and is very hard to maintain.
14:13:32
Guest74
there are some data table libraries out there, but afair they parse to their own format.
14:14:10
mfiano
My plan is to parse this data (and other output) into standard-objects, because it can benefit greatly be inheritance and generic dispatch.
14:15:39
mfiano
I'm using a nice wrapper over uiop:run-program that has nice conditions to handle in the event of a failure, instead of all the garbage-in/garbage-out bugs in my original shell script.
14:15:57
Guest74
after seeing what was inside of the csv libraries, I just basically use read-line and split-sequence.
14:21:48
Guest74
I can't remember the name of his library. I reading some other library that uses it, and can't remember that one either. I really hate this covid.
14:36:54
mfiano
Yeah I asked him about it. It also doesn't handle pipelining, which the current library I'm using does.
14:39:46
mfiano
Anyway, to answer my original question, I'm just using read-line and uiop:split-string
14:42:53
Nilby
sorry i know it doesn't help, but this is how i do it: (view-table (read-table (!! "program") :style +tsv+ :guess-types t))
15:09:12
Nilby
they are a massive tangled profusion of packges of bespoke and ramshackle nature, unfortunately entrenched in their own enclave
15:31:37
Nilby
it's mostly not abstractions. unfortunately one can find such weird lisp software hives like this through history. mostly they don't get the critical mass or quality, to be widely used
16:23:24
mfiano
Has anyone any reference apart from AMOP on how to add additional slot options to a class via a metaclass? I would like to add a :encoder and :decoder slot option, that decides on how slot values are serialized and deserialized when parsing/unparsing.
17:00:51
mfiano
In reading the MOP a bit, I found the way to do this is to create specialized instances of direct-slot-definition-class and effective-slot-definition-class, and define methods for them that return those classes. However, I am a bit confused in that these generic functions have a single argument to specialize, the class to add these new slot definitions to. I therefor am unsure how to add _two_
17:03:51
Bike
i am not sure what you mean. neither of those generic functions add slots to any classes. they just indicate what the classes of slot definitions should be.
17:04:08
mfiano
I would like a class to have two new additional slot options, such as the slot specification (foo :reader foo :initarg :foo :encoder #'some-encoder :decoder #'some-decoder)
17:05:18
mfiano
Ok, do I have to subclass both standard-direct-slot-definition and standard-effective-slot-definition classes with the same body?
17:05:57
Bike
you can have (defclass my-slot-definition (standard-slot-definition) ((%encoder ...) (%decoder ...))) and then have your my-direct-slot-definition and my-effective-slot-definition be subclasses of that
17:07:26
mfiano
I am unsure where to put the supers standard-direct-slot-definition and standard-effective-slot-definition
17:10:27
Bike
unless you're doing something much more exotic than you are, you should probably have your direct slot def class inherit from standard-dsd, and your effective from standard-esd, and you can have them both inherit from the class with the %encoder and %decoder slots to save some typing
17:10:42
mfiano
I will admit, I never used the MOP before to extend slot definitions, just trivial metaclasses. This is new and fun to learn.
17:24:10
mfiano
Bike: Is this what you were talking about? https://gist.github.com/mfiano/b824a68c58d72501afd5fca6005e66e8
17:26:17
Bike
did you compile-file this? it might have tried to define the class before the method was loaded.
17:31:14
Bike
You need to specify the metaclass, yes. since the metaclass can influence how inheritances work, it's necessarily prior
17:34:16
Bike
(class-of (find-class 'foo)) will be zfs-property-class, which is not a zfs-property-class
17:34:31
Bike
try (class-slots (find-class 'foo)), you should see zfs-property-effective-slot-definitions
17:34:51
Bike
however they will not have the information you want until you define a compute-effective-slot-definition method
17:36:40
mfiano
Oh I see. Yes that is the correct class, but the meta slots are unbound. I have more to learn it seems with regard to compute-*-slot-definition
17:37:16
mfiano
Wow lots of boilerplate here for a simple task. I have to learn how to do this so I can abstract it away for similar things to do for other classes.
17:38:25
Bike
what that function does is take all the direct slot definitions from the class precedence list, and combine them together into an effective slot definition
17:39:04
Bike
This is necessary because there's no obvious way to combine inherited slot information; even the standard slot options inherit in all kinds of different ways http://www.lispworks.com/documentation/lw70/CLHS/Body/07_ec.htm
17:39:45
Bike
it's been a while, but iirc your method should do call-next-method and then set the metadata slots in the result appropriately
17:39:47
mfiano
I see. So once I do all of this, what is the correct way to query the encoder/decoder functions of one of my leaf class instances?
17:40:36
Bike
You get at the slot definition (e.g. through class-slots) and then use your ENCODER and DECODER accessors
17:41:35
Bike
https://github.com/yitzchak/common-lisp-jupyter/blob/master/src/widgets/traits.lisp#L33-L73 here's some code in cl jupyter that defines a new slot class
17:43:41
Bike
in this case, the inheritance rules are simple: the most recent wins. your encoder and decoder might work the same way
17:44:15
Bike
also, iirc, you might have problems specifying them in the way you do. i don't think the slot definition initargs are evaluated, so the direct slots will just have the list (FUNCTION IDENTITY) instead of an actual function
17:48:22
Bike
i think i ran into this in my initial version of this cl jupyter code (it has since been totally rewritten by yitzi) which had observer functions, and i just had it take symbols instead. so you'd write :observer foo instead of :observer #'foo
17:48:56
Bike
well, basically, imagine you have a class foo that defines (%a :encoder #'x), and then a class bar that defines (%a :encoder #'y), and then say bar inherits from foo
17:50:05
mfiano
Well in my case there won't ever be subclasses of a zfs-property class, but I would expect the deepest subclass to win in almost all cases.
17:50:28
Bike
the GF receives the direct slots in class precedence order, so using SOME like this is kosher
17:54:20
mfiano
So if I wanted it to behave like any other initarg value, how would I accomplish that?
17:56:14
Bike
well, the others have funny behavior as well. like if you have an :initarg, it's not evaluated right off, it's saved and then evaluated each time you instantiate an instance
17:56:29
Bike
I don't think you can change the behavior of the defclass macro to make it be evaluated like you want, unfortunately
17:56:34
Arthur
I ended up hacking together some c2mop:compute-effective-slot-definition stuff when encountering the #'fn non-evaluated slot inits over in https://github.com/arthev/spiclum/blob/master/src/prevalence-class.lisp, maybe there are better ways
17:57:28
Bike
you can ofc define your own defclass macro, but that can be sort of a pain in its own way
17:57:59
mfiano
Can I use the mop to get a single class slot, or do I have to use #'find or whatnot?
17:58:31
Bike
if you mean you want to get a particular slot definition from a class, you do need to use find or something yeah
17:59:15
mfiano
instead of #'c2mop:class-slots <class> -> list, something like #'foo:class-slot <class> <slot-name> -> #<esd>
18:04:17
mfiano
THe MOP always impresses me at its flexibility at the cost of boilerplate. It's to CLOS as macros are to code. Not much you can't do with CL with those two powers combined :)
18:56:41
trev
does anyone know a plugin for emacs where you can basically hover over keywords or functions and see docs for them?
19:06:12
mfiano
Anyone know if alexandria or some utility library has a shorthand for (setf (slot-value instance slot-name) (call-some-func (slot-value instance slot-name))) ?
19:09:52
mfiano
They can, but in this case it won't work anyway as slot-name is not known at compile time.
19:10:51
mfiano
THey can also be a source of serious performance issues if you are evaluating an expensive accessor effective method each read of the symbol.
19:26:57
Bike
now that i'm thinking about it, maybe it would be nice if alexandria or something had a macro like atomic-update but without the atomicity
19:36:51
_death
that's kinda like PG's _f macro in On Lisp.. I don't think it's so nice.. instead I prefer to name the operation, like INCF
19:48:01
Alfr
Bike, not in the library, but here: (defun %update (thing fun &rest args) (apply fun thing args)) (define-modify-macro update (fun &rest args) %update)
20:05:46
mfiano
Not that I think I'd need to do type-checking considering the stringified source data is coming from the correct application I am parsing into lisp objects, but it makes me wonder if I should anyway.
20:07:50
mfiano
Like one slot is fed any of "none"i, "available", "unavailable", and encoded as any of :none, :available, :unavailable. But if my program logic is wrong and tries creating an instance with bad data, I have no way to type check.
20:10:11
mfiano
Though not sure if it makes sense to type check decoding if it is symmetric with the input.
20:14:08
mfiano
I'm also not sure if it even makes sense to specify an :encoder _and_ :decoder slot. The decoder just puts it into the original form it was encoded from. That logic can be derived with a closure or object representing the transcoding method.
20:19:25
mfiano
My plan was to build a CST, producing an AST afterwards to do type-checking/generation phases on. I think I need to sketch out the pipeline better...it might be overly complex like all my compiler theory implementations are :/
21:43:03
Guest74
ugh, I hate when you can't interrupt a slime repl. This is why I shouldn't have my editor in the same process, let alone my window manager.