freenode/#lisp - IRC Chatlog
Search
1:45:28
aeth
Hmm, so macros can have &optional and &key within things apparently. Time to build some really complicated macros.
1:56:40
whoman
minion memo jmercouris papyrus is lighter and cleaner, but org is structured and allows other code as well. i think i will stay with org for literate docs
2:06:01
waynecolvin
print documentation strings https://pastebin.com/V94fjqxJ works in clisp, not sbcl
2:17:55
aeth
I think I have three possibilities. I can have a family of related macros that largely share the same code. This is sort of like do-foo. I can build a complicated syntax that basically requires Emacs+SLIME to know what's going on through the names. Or I can sort of build almost a loop-like thing (really just keyword arguments) that could ideally be at least readable without an API reference.
2:25:50
aeth
whoman: You can do that manually. e.g. foo, foo/bar, foo/bar/baz. uiop:define-package's :use-reexport is useful for this
2:26:35
aeth
i.e. foo uses :cl (so you can in-package) and use-reexports foo/bar and foo/quux and foo/bar use-reexports foo/bar/baz, etc.
2:28:47
aeth
You have hierarchies of packages all building up exports, but with only the bottom level (or top level? depends on how you look at it) actually naming what it exports
2:30:11
Zhivago
The reason that it is flat is separate compilation -- and that the package is part of the symbol name.
2:30:22
whoman
well. i figure if i were to conflict with my own names, either my names are not good enough or i'm making up too many things that need names.
2:30:52
aeth
Zhivago: What I've been doing with the more complicated macros is relying on helper macros, so each layer of abstraction can technically be avoided. e.g. with-foobar might use a with-bar, which can be used on its own, too.
2:31:27
Zhivago
aeth: Perhaps, but I'd recommend that with-bar expand to a call to a bar-foo function.
2:31:45
whoman
aeth scared me yesterday about name conflicts and i had haskell and js nightmares so i got edumacated
2:32:22
Zhivago
aeth: Then your macro can look like (defmacro with-bar (zoo &body body) `(bar-foo ,zoo (lambda () ,@body)).
2:32:22
aeth
whoman: but I should emphasize again that my package layout in zombie-raptor is the nuclear carpetbombing solution to name conflicts and there are probably simpler ways.
2:32:58
aeth
Zhivago: The problem is that these macros are run very frequently in loops within loops (possibly within loops)
2:33:50
whoman
hmm what is the opposite word for Scale. macros shouldn't shrink stuff, but expand them. no? i mean they arent called micros. and code Scales well sure, but what is the opposite ? well now i just dont know any more.
2:35:20
whoman
it kind of feels that aeth is going in a certain direction with the macros. but i am a newbie, never wrote more than 1 level of macaroni
2:36:33
Zhivago
Aeth's plan seems to be to invent a new language which consists of a flat list of values and keywords in order that slime not be confused by its structure.
2:36:38
aeth
whoman: Macros could shrink things, even usefully. Consider a macro that removes trivial arithmetic operations like multiplication by 0. Iirc, sbcl's compiler's optimizer won't remove them for floating point numbers because that technically can change the outcome of the floating point operations.
2:37:42
aeth
(Sorry, I mean multiplying something by zero and then adding... clearly that could be replaced with nothing.)
2:38:09
Zhivago
aeth: Although for those cases you probably want compiler-macros which are a little different.
2:45:15
aeth
Zhivago: What I have (and it certainly wastes memory, but that's okay for me) is a bunch of data stored in specialized 2D and 1D arrays of the same length. What I'm doing is hiding that. I actually use symbol-macrolet to make something very similar to with-accessors, which mostly takes care of hiding that.
2:45:48
aeth
(For 2D arrays, they're obviously not of the same length as the 1D arrays or even necessarily each other, but they're of the same outer length)
2:48:22
aeth
I either provide a specific ID or I provide nothing. If I provide nothing, I iterate over everything. Either way, code is only executed if the thing implements *all* of the things that I'm accessing with the accessors (checked very efficiently through boolean sets implemented as fixnum bits).
2:50:23
aeth
(I think I could actually greatly save memory if I implement a hash function and turn the arrays into a custom hash table, with the ID as a hash key instead of an actual index number to the arrays. But I'm not sure that would work because that wouldn't avoid the worst case of everything implementing everything. It would at least make things more cache-friendly in cases that aren't as bad.)
2:52:27
aeth
I'm essentially building something that's almost an ECS and almost an in-memory NoSQL database, and where the language-in-macros part comes in play is that I could greatly expand the possible ways to query the data other than ID match or everything.
2:53:56
fouric
"aeth | Hmm, so macros can have &optional and &key within things apparently" <- have time to elaborate?
2:54:18
fouric
ACTION has written simple macros before (little opengl binding things) but doesn't know enough to know what this is
2:54:36
aeth
"code is only executed if the thing implements all of the things" => "code is only executed if the entity contains valid data for all of the tables with accessors in the query"
2:54:59
aeth
"macros can have &optional and &key within things apparently" => "macros can have &optional and &key within lists within the top level lambda list apparently"
2:55:49
aeth
A specific example: (ecs (index-name &optional index-number) tables-and-accessors &body body)
2:57:43
aeth
And it's slime-friendly, so you can actually figure out what's valid, unlike with tables-and-accessors, which is complicated and arbitrary length, so I have to deal with that myself
3:03:32
aeth
Oh, I'm writing very clever, terse code. And it's becoming more like that every time I add more functionality. Soon, I'm going to allow a special definition for helper functions so I don't constantly requery the ECS. i.e. implicitly pass just the arrays that are being used, and use with-entity-accessors only, without any direct access to the ECS.
3:05:40
aeth
Of course, it leads to people questioning things like why I set a variable to multiple values, e.g. (setf velocity (values x y z))
3:09:59
aeth
(setf velocity (values x y z)) is really, roughly: (setf (array-row-of-3 %velocity id) (values x y z)) where array-row-of-3 sets the first three values of a row in a 2D array when given three values... so ultimately (psetf (aref %velocity id 0) x (aref %velocity id 1) y (aref %velocity id 2) z) and quite a few things are being hidden
3:13:41
aeth
oh, and that's essentially (psetf (aref (velocity-velocity (velocity ecs)) id 0) x (aref (velocity-velocity (velocity ecs)) id 1) y (aref (velocity-velocity (velocity ecs)) id 2) z)
3:22:53
aeth
on the other hand, it reduces the maintenance to a handful of unreadable macros instead of the entire source code
3:22:55
Zhivago
If the code is as clever as you can make it, it's probably too clever for you to debug.
3:26:18
whoman
ouu interesting. i like that idea. puppet strings for a whole project, the One macro...
3:26:19
aeth
(with-selection ecs (id entity-id)\n ((velocity (velocity velocity :row-of 3)))\n (setf velocity (values x y z)))
3:26:55
aeth
A bit confusing because the name velocity is used a lot but :row-of 3 basically says it's magical like that, and even says how many values it takes
3:27:23
Zhivago
Ok, that's probably a little less horrible but, even so it seems like it would be simpler to have an obvious accessor.
3:27:47
aeth
Basically: with the selection from the ecs where id=entity-id from the table velocity bind velocity to the row-of 3 called velocity
3:27:50
fouric
Zhivago: some dude named Chad Fowler thinks that you should never modify functions, only rewrite them: https://dave.cheney.net/2017/11/30/never-edit-a-method-always-rewrite-it
3:28:18
fouric
if your unreadable, terse code needs to be modified, all aeth has to do is just rewrite it with equally unreadable, terse code that has the new functionality
3:30:00
Zhivago
fouric: But if he doesn't understand what the original does, how will he understand what the new version should do? :)
3:30:17
whoman
C/java/objc/js//make/etc i can type fast and a lot with some nice music going, its quite chill and mindless. i like how lisp and haskell and ocaml 'force' me to reflect and think, as itchy as my hands are to type.
3:30:22
aeth
Zhivago: The accessor is (velocity velocity :row-of 3) and that's the same syntax as directly using with-entity-accessors, it's just combined into the database query
3:30:57
whoman
comments or not, the compiler is still the one "doing" it. code is generally quite specific
3:30:57
aeth
Doing things this way saves a lot of repetition (and potential typo bugs) since it's both fetching velocity and accessing velocity in the same place
3:31:27
Zhivago
I'm not going to stop you from doing this -- but I will point out that as developers mature they move from fancy to boring code. There's a reason for this.
3:32:51
aeth
Zhivago: The array doesn't exist, though. The structs don't exist, either. Those are just implementation details that I want to completely hide from the user.
3:33:28
aeth
Otherwise I have to rewrite about a third of my game engine every time I change how the data is structured.
12:59:04
jackdaniel
the end of paste.lisp.org, it's not pastebin. there is plenty of other paste services
13:05:41
phoe
Make sure that the symbol you use in the SLOT-VALUE and the symbol used as the slot name are EQ.
13:06:38
phoe
francogrex: https://stackoverflow.com/questions/40742048/is-there-a-way-to-get-the-slots-of-a-class
13:13:16
random-nick
is there a pastebin service which does rainbow parentheses or parentheses highlighting?