freenode/#lisp - IRC Chatlog
Search
6:20:05
buffergn0me
Another thing to consider is breaking up packages along domain specific language boundaries.
6:38:51
aeth
jackdaniel: I :USE internally even though USE in general is discouraged, so that gets around the major inconvenience of separate packages.
6:43:03
aeth
I have some macros that greatly cut down on exports. It's mostly just the one macro for defining with-foo-accessors. (with-foo-accessors ((foo foo) (bar bar)) ...) behaves like with-accessors, except it will intern and prefix the accessor, so it's really (with-accessors ((foo foobar::my-foo-foo) (bar foobar::my-foo-bar)) ...)
7:07:15
_death
also, I find that with-accessors is a bad idea on several counts.. it's meant to lessen verbosity, but is itself verbose.. it's an under-the-carpet macro since the verbosity is a symptom of bad interface
7:09:07
aeth
_death: having foo::bar internally in a macro is perfectly okay as long as it doesn't fit in any of the cases that makes (gensym) necessary
7:09:54
_death
aeth: yes, but it means the user doesn't distinguish between external and internal symbols.. so no point in packages
7:11:53
_death
it loses the idea of symbol identity, since the second symbol in the "binding" is used only for its name in another context.. this makes it difficult to distinguish internal and external, and to extend as well
7:17:05
aeth
_death: Extensibility is a valid criticism of this sort of approach, but these aren't really meant for outside use. This gets around exporting issues when using many *internal* packages.
7:17:47
aeth
Extending these internal structure-objects and standard-objects will almost certainly break something.
7:19:03
aeth
_death: make a package for every file and you soon find yourself writing packages with literally dozens of exported symbols
7:22:19
aeth
Consider window settings. There's title, width, height, fullscreen, vsync (if graphically accelerated), etc.
7:22:31
aeth
e.g. https://gitlab.com/zombie-raptor/zombie-raptor/blob/63e9a3906476b1e54040597e45636fd2da6c3417/core/settings.lisp
7:23:03
aeth
I mean, I could probably split that into (for example) three objects, but that just means I either pass in 3 objects instead of 1 or I have one object-of-objects and now have 3 more accessors!
7:23:51
aeth
I think most Lispers just would use a dozen global special variables, which is even more problematic
7:25:12
aeth
Notice that each element in the struct has a :type argument. This is checked reliably in some implementations. The plist approach would require a CHECK-TYPE at moment of access from the plist, in a different part of the program.
7:25:30
aeth
There's just a ton of complexity in a game engine, no matter how you choose to arrange it.
7:26:22
_death
if you want to deemphasize symbol identity, you can use keywords which is very easy to see the pros and cons of.. a macro like with-foo-accessors lets you "feel with but go without" (not sure about the english idiom for this..)
7:29:45
aeth
If I used keywords to abstract over struct and standard-object accessors, I would have to write a considerably more complicated macro than with-foo-accessors, and without the benefit of the reader basically seeing what I mean just by the name of it.
7:30:36
_death
but the point is that you don't access your settings by having an accessor for each one
7:32:43
_death
you don't need to do type checking at each access.. you can do it when you create or modify the object
7:33:08
aeth
Do you want zombie-raptor/core/settings:settings-title, an explicit import-from for the 5 settings you happen to access in that package, the package to :USE that package, etc? Pretty much every way to access is messy.
7:33:43
aeth
And I use zero special variables (besides redefinitions of *standard-output*/etc.) because they don't play nice with threads.
7:37:30
aeth
I had weird things happen with special variables and threads. Now I just take the extra few minutes to pass objects around and get better performance and a clearer idea with what's going on.
7:38:31
aeth
It actually isn't that big of a deal to pass a variable 6 levels down a call-stack as special variable proponents claim.
7:39:26
aeth
standard-output is essentially irrelvant 95% of the time, so it would just pollute the API
7:41:21
aeth
That means that I would have to write my application with the assumption that the settings could change at any moment to anything.
7:42:58
_death
you are right that this is something to think about.. you can tell the user not to do that (this isn't java after all :).. or you could actually handle it correctly.. think Cells :)
7:44:19
_death
or are you saying that you just won't pass a settings object there.. which then make it troublesome to inspect settings
7:45:30
aeth
_death: the easiest way to inspect this is to recompile a function to insert a (break) in the middle of it ime
7:45:56
aeth
otherwise there would be dozens of objects (not just settings) that would need to be saved into debug globals
7:48:57
_death
in short you choose not to use the mechanism of special variables for something they are quite useful for (context).. many programmers do that, usually because they lack that mechanism.. and then there are programmers that make a conscious choice.. I think we can put Schemers in that category
7:50:00
aeth
_death: Special variables means that the whole program and all outsiders access settings. A settings object means only the functions that are passed the object (and, obviously, the programmer if debugging or whatever from the REPL) access it.
7:53:37
_death
this is a familiar argument (protect the programmer from himself) and we can agree to disagree about it.. there is a small technical point that the special variable has a name like *settings* which may be imported or not and so there's a way to indicate use or not use
7:55:49
aeth
_death: The programmer can do whatever they want in the CL environment, including access private things. This makes tests a lot easier to write, for instance. It also helps with REPL-based debugging, even though it might be annoying to write out a full package followed by ::
7:57:15
_death
aeth: right.. and a special variable is transparent.. things that don't use it don't need to pass it around.. unlike a settings object where you need some non-users to pass it around to users
7:58:38
_death
aeth: and internally, there's also the need to pass it around.. like I said, this hurts interactive development
7:58:41
aeth
_death: in my architecture, everything's passed into the init. The programmer owns the data. I don't even support reading in textures. I might eventually but in all of my tests that needed it, I just load in a PNG myself.
7:59:13
aeth
_death: Since the programmer passes everything in, the programmer can save it into a special variable first
8:01:07
aeth
_death: That's also why I prefer structs with typed-slots or standard-objects with a metaclass that ensures that preconditions are held. I want errors to happen before passing the data in.
8:01:34
_death
vsync: does the number #x3DA says anything to you.. (maybe a more indicative notation, &H3DA)
8:06:41
vsync
wonder if you could get ultimate frame rate by inserting a tiny flicker at some frequency
8:08:55
p_l
ACTION notes that all of the data channels in visual path are continuous wave with various levels latency involved in processing them
8:10:13
_death
vsync: it was the port of the VGA status word register.. to wait for vertical retrace you'd wait for the 3rd bit to be set there
8:34:35
shrdlu68
Running `sh make.sh` in the latest SBCL tarball from github says it can't run `git describe`.
8:41:02
shrdlu68
I have some code that runs in 14s in SBCL, and way too long in other implementations. It heavily (ab)uses a hashtable, I'm fairly certain that's the biggest factor in the difference. Now I'm curious what exactly makes SBCL's hash table faster.
8:42:40
Shinmera
and hash-tables with test equal or equalp are probably not tables at all, but trees.
8:43:31
shrdlu68
I defined a custom hash table test and used sxhash with virtually indistinguishible results from :test #'equal
8:49:23
shrdlu68
I wonder where this massive difference stems from, then. In ECL, it runs for over 2m, I had to interrupt it. Similarly dismal on CCL.
8:50:50
jackdaniel
ecl is espcially bad with generic function dispatch, I would be suprised if hashtable were that much subpar
8:51:10
_death
CL hash tables are complicated creatures.. several times I saw advice to implement your own hash tables and see resulting performance
9:03:27
jackdaniel
shrdlu68: would be suprised, hash tables are optimized on ecl to a reasonable degree
10:17:52
trittweiler
The signaling not per se, but the handling will most likely involve a transfer of control - so yeah.
10:28:20
shrdlu68
I profiled the code: https://gist.github.com/shrdlu68/081a78c6196b676395ca518a268d9119
11:03:44
vsync
i throw from my primary method to my around-method and it doesn't skip the after-method :(
11:47:21
makomo
i figured i can arrange the evaluation of the condition by injecting it into the temps/exprs values returned by the setf expander
11:49:03
makomo
one thing i'm not sure about was a warning from SBCL i got which i can't reproduce now
11:49:38
makomo
it was warning about how "NIL is not a CONS" because it analyzed that WHEN and UNLESS might return NIL
11:50:18
makomo
Bike: yeah :/. i was thinking of somehow merging the temps/exprs as well, but i'm not sure if it's fixable
12:04:34
makomo
Bike: as an expander, yes, but in this case it's used as a macro that expands into code that gets the value of the place
12:05:17
makomo
and i think this conditional place is finally a proper example of a place which you can't treat as a form and ev
12:06:48
makomo
i was thinking of how you can get the value of the place "(car a)" just by evaluating the form "(car a)"
12:07:09
shrdlu68
shka_: I think this is more accurate: https://gist.github.com/shrdlu68/081a78c6196b676395ca518a268d9119
12:07:24
Bike
i figured (iff a b c) would expand into (let* ((#:1 a) (#:2 (when #:1 b)) (#:3 (unless #:1 c))) (if #:1 #:2 #:3)) which is obviously just a more complicated (if a b c)
12:10:59
makomo
Bike: hm, i think i don't even need to rely on READF and the expander of IFF for the IFF macro
12:11:38
Bike
i'm not sure what readf is for, except i guess writing a complicated setf expander with complicated get, and wanting to not duplicate it
12:42:21
makomo
the places are implemented via macrolets that expand into a %READF form, which is either a call to the macro %READF or a %READF place
12:48:07
makomo
both of those just set a flag to trigger a different expansion of the macrolet, and the expansion is initiated by GET-SETF-EXPANSION
12:48:24
makomo
i think that's the trickiest part, the hidden macroexpansion within GET-SETF-EXPANSION
12:55:56
shrdlu68
shka_: I'm not sure how this works, does it show the time taken in a function, taking into account the functions called by that function?
12:56:50
shrdlu68
If function A calls B, do we get the time spent in A outside the function call to B?
13:37:29
flip214
The iterate darcs' tree has been renamed some time ago... see https://www.common-lisp.net/project/iterate/darcs/
13:57:02
phoe
pjb: this is going to be a funny mail - asking https://tlo.mit.edu/ for FOSSing a piece of software written 23 years ago. (:
14:05:52
phoe
I've been refurbishing it since yesterday and got satisfying results; now I'm trying to get an official license on it
14:57:22
beach
I am hoping my favorite coauthor will have time to set up the infrastructure for testing the algorithms this year. Last year, she was on an all-research year, so she was buy doing that.
14:58:10
_death
shka_: https://groups.google.com/forum/message/raw?msg=comp.lang.lisp/EoKU5n0lbJs/DGdyZ-lCuTEJ
15:00:37
_death
further confirmation from 1993 https://groups.google.com/forum/#!search/sxhash/comp.lang.lisp/oBHfPf0mnog/RC9uTGiMz_8J
15:11:43
beach
I did that as part of compiling the text of the book, but I don't think that is the good way of doing it.
15:13:22
beach
The algorithms are written in Common Lisp and translated to my own algorithmic notation.
15:40:44
makomo
Bike: regarding the SETF-EXPANDERLET thing, wouldn't this have to be wrapped with an EVAL-WHEN to be portable? https://github.com/Hexstream/place-utils/blob/master/main.lisp#L9
16:06:24
beach
So let's say that METHOD-COMBINATION is a class. Then presumably STANDARD, AND, PROGN, etc., would be instances of that class, right? But then, method combinations take options, so it would appear that a method combination metaobject is an instance of an instance of a class.
16:08:14
beach
Let's call the last thing a "variant". FIND-METHOD-COMBINATION would check whether the name and the options describe and already existing variant and return it. DEFINE-METHOD-COMBINATION, on the other hand, would define an instance of METHOD-COMBINATION. Does this seem reasonable?
16:10:15
beach
But he does not allow lambda lists in long method combinations, so no "use time" options.
16:10:20
Bike
i think he mentioned it, but find-method-combination makes more sense if it's called compute-method-combination
16:11:22
Bike
is there any reason to have the "same" method combination use in two different generics be the actual same object, besides maybe saving some memory?
16:12:11
beach
There might be. Currently that is how it is done in SBCL according to Didier's paper.
16:14:28
beach
The main question is what kind of animal is the result of DEFINE-METHOD-COMBINATION and what kind of animal is returned by FIND-METHOD-COMBINATION.
16:15:04
beach
And I think DEFINE-METHOD-COMBINATION might make an instance of the class METHOD-COMBINATION.
16:15:44
beach
And, like I said, FIND-METHOD-COMBINATION might create a "variant" which is some kind of instance of the instance that was created by DEFINE-METHOD-COMBINATION.
16:16:12
Bike
The way I think of it is that define-method-combination defines a kind of method combination, but the actual method combination objects have to be computed and have all the argument information. so they are "variants" so to speak.
16:16:46
beach
The other possibility is for DEFINE-METHOD-COMBINATION to create a subclass of METHOD-COMBINATION rather than an instance.
16:17:00
Bike
in ECL and Clasp's implementation, the things like "standard" and "progn" don't really exist as objects, there's mostly just a hash table that stores the expansion function and stuff, and then the actual method combination object is equipped with that when it's created.
16:18:03
beach
Either way, there has to be some kind of dictionary to look things up given the name.
16:19:47
Bike
I think the "general" things are different from the specific "variants"- classes is one way I guess
16:23:18
dim
beach: you're contemplating making every function (operator?) a generic function the same way that any data type is usable as an object?
16:25:17
beach
I am not considering making every Common Lisp function generic, no. I am not sure what it means for any data type to be usable as an object. I can't see how (integer 2 3) would be an object, other than in the trivial sense that it is a list of 3 elements.
16:26:23
dim
my vocabulary on those concepts is lacking, maybe I should consider reading the mop someday…
16:28:17
dim
in math the zero-argument result of the + function would be named the neutral element in the group, right?
16:28:43
Bike
but it's not clear what the group is. fixnums and floats are different groups (i don't think floats actually form a group, but w/e)
16:29:14
dim
so maybe that's the missing piece that would allow for a generic +, where your specification would allow for a “neutral element” to be defined for any data type (integer, defclass instance, etc)?
16:29:17
beach
I am still interested in getting good performance, and I don't know how to do that without inlining and I don't know how to inline generic functions.
16:31:01
beach
dim: I will make things like SYMBOL-NAME and SYMBOL-PACKAGE generic though, simply because it is easier to do that than to make them non-generic in SICL. Plus, the generic function would not do any more work than an ordinary function would do.
16:33:13
makomo
beach: what do you think about Fare's LIL? is it a feasible approach? i think i remember watching part of his 2-3 hour stream about LIL
16:33:48
beach
(defclass symbol () ((%name ... :reader symbol-name) (%package ... :reader symbol-package)) (:metaclass built-in-class))
16:35:26
pjb
The 0-ary CL:+ doesn't prevent to define a generic function SI:+ taking 1 or more arguments, with (defun cl:+ (&rest args) (if (zerop (length args)) 0 (apply (function si:+) args))) and to document it. If enough implementation do that, we could even standardize it!
16:35:38
makomo
beach: not to be rude, but i thought i heard your voice on the stream :-) https://www.youtube.com/watch?v=kV63Mf5Qb2Q
16:36:53
makomo
beach: yeah, i don't think fare's LIL is directly related to what you're talking about currently
16:37:18
stylewarning
dim: nitpick: for associative functions that allow “zero arguments”, you only need monoidal structure, not group structure
16:37:19
makomo
but i wonder whether it's a feasible design given the potential overhead of GFs, etc.
16:38:32
dim
stylewarning: I know nothing of monoids, only was taught groups and some other basic stuff 20+ years ago
16:39:54
shka_
and LIL is worth studying because it is a very sound way to develop certain class of protocols
16:42:41
makomo
btw, it appears the talk lasts about 1h 30m, i don't know why i thought it was longer
16:45:40
makomo
beach: ah, this is the 2h 30m one, but it's about ASDF https://www.youtube.com/watch?v=Qqqbc31ZZ-U
16:45:57
makomo
beach: but i'm not sure anymore whether i heard your voice or not, maybe i confused you for someone else :-)
16:47:10
beach
makomo: If it turns out to be true, I will go seek professional help for my bad memory.
16:47:14
stylewarning
makomo: beach sounds like a professor and someone who thinks about compilers sometimes
16:49:56
makomo
stylewarning: oh, since you mentioned abstract algebra, i want to ask: what do you think is the relation (or is there any) between Lisp and abstract lagebra/category theory/etc., compared to the same thing but with Haskell for example?
16:50:26
makomo
the question is probably vague but maybe you can understand/guess what i'm getting at
16:51:19
stylewarning
makomo: I think there’s no intrinsic relationship, except that Lisp being dynamically typed allows you to get away with implementing broader protocols for algebraic structures
16:52:37
stylewarning
makomo: Haskell type classes are limiting because they force you to choose one implementation that you want to be polymorphic over (in other words, you can only create one Group over Integer as a type class, even though integers have many such group operations)
16:52:38
makomo
stylewarning: do you say that because nobody ever formalized Lisp in those terms or? and would you say that Haskell does have such a relationship?
16:53:25
stylewarning
makomo: I say it because Lisp lets you implement things that arent adhering to a strict static type system
16:54:44
stylewarning
Standard ML lets you get a bit further than Haskell on this front by having “parameterizable signatures” called “functors”
17:01:21
dim
you might have fun reading about Mythril if you're interested into SML family, https://mythryl.org/my-Executive_summary_.html
17:26:06
flip214
when interrupting QL during download of packages, and later on retrying (ql:update-all-dists), it just says "already updated" - and not-yet-downloaded packages are kept in the old version.