libera/#commonlisp - IRC Chatlog
Search
3:13:22
loke[m]
@cpli:libera.chat: you just add it to the dependencies in the asd file, or am I miunderstanding the question?
4:00:05
jmercouris
are you trying to actually literally call something from the trivial features system in your asd?
4:12:35
bitblit1
<jmercouris> "are you trying to actually..." <- I think that is what he was trying to do.
4:13:29
jmercouris
then you have a couple of options, basically you can require it, embed it in the top of your asd and use it
6:28:34
bitblit1
So, I asked about compiling your program while it's running to see "live reload". I understand now that anything in the loop with it's own compilation unit will be able to reload while the application is running. However, how will I update things that should NOT be in the loop. Such as init functions. Let's say I am working on creating a game or whatever, I want to write the code to create a window and compile it while the program is running
6:28:34
bitblit1
and want to see it update live. However, putting the CREATE-WINDOW function in the main loop will create too many windows. I don't know how to get around this problem. Do I have to check if it is the first instance of the loop? If so, when I compile, will the loop rerun making it the first iteration of the loop?
6:35:02
bitblit1
Or the loop which runs and keeps checking for any events that might have to be processed
6:55:30
beach
If your application starts by executing some initialization code and then runs an application event loop or command loop, then if you want to alter the initialization code, it is very likely that you need to restart the application.
6:55:31
beach
You could execute additional initialization code at the REPL, like to create a window, but it would be complicated to make your application take it into account. You would have to think hard about how to structure your application in order for it to take such modifications into account.
6:57:14
beach
In other words, you can't have an application with some arbitrary structure and then expect it to respond to arbitrary code modifications at the REPL. You have to think about the modifications you might want and structure your application accordingly.
7:00:17
bitblit1
beach: Yes, so I understand most of the implementation and structure now. For example, I could create a render method which could look at a list of windows and keep on rendering/updating them. This is great as I could have an empty list and it would render nothing. Now all I have to do is change the window list, however, to do that, I would need to be able to access it easily, through a global variable. If i want to avoid global variables, I
7:00:17
bitblit1
would have to create a state class which would keep track of my state and update that. Is this correct? And if so, is it even a good idea?
7:02:16
beach
Sure. For instance in a CLIM application, the "application frame" is meant to hold "global" information about the application. At some point, though, you need at least one global variable, and in a CLIM application, this is CLIM:*APPLICATION-FRAME*.
7:03:45
bitblit1
Ooooh, this seems interesting. Thanks for all the info beach. Are there any pitfalls or caveats in this process?
7:07:12
bitblit1
What is this <CLASS> naming convention, don't see it much, is it good practice or smth?
7:24:19
loke[m]
<beach> "It is not a Common Lisp conventi..." <- I thought it was clever, until I had to deal with code that used that convention. Then I changed my mind.
7:26:16
loke[m]
I think it's Fukamachi that likes that style. He also uses one-package-per-file, which is also highly annoying.
7:27:34
loke[m]
I would of course like to clarify: That's my personal opinion. And the annoyance stemmed from me porting over code written in the package/file style to a single package and it was frustrating. I'm sure if you're used to the style and committed to it, it's not so annoying.
7:35:15
bitblit1
Yeah I used to use that convention but was like eh, package.lisp + using popular (non?)convention feels good
7:36:13
jackdaniel
bitblit1: if you have some "render" loop and you want to change the function that draws it, you may define a function update-window that is called from within that loop like (funcall 'update-window window), then if you redefine update-window then the new version will be used in said loop
7:36:35
jackdaniel
in contrary to (loop (draw-a) (draw-b)) where ou'd need to actually stop the loop to redefine its body
7:38:07
jackdaniel
in /some/ projects I have a macro define-class that defines a class, a function of the same name (being de-facto make-instance) and a variable with a value being the class itself
7:38:11
loke[m]
I also decided that it didn't really increase readability, so it felt similar to hungarian notation to me, which is something I don't like.
7:39:12
jackdaniel
bitblit1: you may find this interesting: http://turtleware.eu/posts/Tixel-Viewer.html
7:40:00
jackdaniel
of course the most important convention is to stick to the style in the codebase, otherwise it is a matter of taste (I like the convention <foo> personally)
7:41:00
loke[m]
That's a much worse take, because special and nonspecial variables have the same namespace.
7:41:04
jackdaniel
to deliberely hide the difference in the client code; I'm not sold on that though
7:42:08
jackdaniel
the program in this post also allows redefinitions: http://turtleware.eu/posts/Controlling-the-terminal.html
7:42:55
loke[m]
jackdaniel: I think anyone who's done any elisp programming knows how annoying it is when dynamic variables are not marked up.
7:43:28
jackdaniel
some languages other than common lisp even make up separate accessors for special variables (so they do not share the same namespace)
7:46:47
bitblit1
It's crazy how you guys do this for free and to help people out, inspires others to do the same, growing the community. Can't go without appreciation.
7:48:27
jackdaniel
don't worry, soon this boring detail will be abstracted away by chatbots - they'll consume the content someone created and answer any question you want
7:58:36
bitblit1
Why can I create an instance of tmp-class and have the state be set to 'single-float?
7:59:14
jackdaniel
the type is your propomise to the compiler, some implementations ignore it, some enforce it on adequate optimize values
7:59:58
bitblit1
Oh... so like what should I do if I want to make sure the types in my classes are right?
8:00:21
beach
bitblit1: I believe recent versions of SBCL will check this if you have a high value of some OPTIMIZE qualities.
8:00:28
jackdaniel
also thanks(?) to the fact that classes can be redefined (so the type declaration may actually change), the compiler can't make assumptions about slot types at compilation time - even if it knows what is the class of the argument
8:01:25
jackdaniel
but then keep in mind that NIL is not of the type cons, so if you want to allow default NIL value, then the type should be (or null (cons integer))
8:02:38
beach
bitblit1: I strongly recommend you change the default OPTIMIZE settings of SBCL, at least during development.
8:04:50
bitblit1
Oh, I understand so if we want to finally publish a high performance library we can just (declare (optimize 3))?
8:05:43
cpli
if i only require `open` and `close` (posix) i feel as though there should be some simple posix library; i.e. not osicat
8:05:45
beach
bitblit1: I find that the choice of algorithms and data structure is way more important for performance than the OPTIMIZE settings, so I don't bother with such declarations.
8:09:11
beach
bitblit1: From #clschool I have also observed that many newbies are concerned about low-level optimization, including things like (SPEED 3), but those are often the same newbies that have insufficient knowledge about the design of algorithms and data structures. So they have highly micro-optimized, yet slow, code.
8:12:22
bitblit1
IDK why I am dragging on this but one edge case I found was that the :type being (or null (cons integer)) is that only the first element (or cons cell) has to be an integer, and the rest can be anything they want. Is this intended?
8:14:33
beach
The thing you can't do is to specify a list of arbitrary length with a particular element type. Other than is you use SATISFIES of course.
8:15:52
bitblit1
Huh? Ooooooh lore expands. You mean using an array. Dunno I don't need that level of detail just a list of windows or integers
8:16:52
beach
In that case, if you really want to check the type, use SATISFIES. Speed for that kind of thing doesn't matter.
8:17:36
beach
Also, you would probably define abstractions like ADD-WINDOW so that you don't have to use the concrete data type all over your code.
8:26:44
bitblit1
There are already many functions like add-window create-window etc. Although I haven't :USE XLIB, Isn't it kinda wrong to do that
8:29:04
beach
It is usually not that good. And by not :USEing it, you can create your own ADD-WINDOW function with a name in your own package.
8:30:21
beach
bitblit1: I highly recommend you think of the objects you manipulate as part of a (usually CLOS) protocol so that you do not litter your code with concrete representations.
8:30:55
beach
Establish the types (usually classes) and operations (usually generic functions) used to manipulate your objects.
8:41:26
phoe
what would be an elegant to say "return true if all these elements are EQUAL to one another" in CL?
8:48:06
splittist
which is every 'equal, but making a choice about what to do with no or one element.
10:12:05
bitblit1
So with the canonical application class, close, render etc should be methods right? Also, since I won't extending application class, do I need to make explicit defgenerics?
10:15:19
beach
DEFGENERIC forms are (unfortunately) optional, and omitting them does not prevent extensions. But I always include those forms, if only to give an explicit name to the parameters so that they are visible in an IDE or in SLIME.
10:16:37
beach
I wrote "unfortunately", because it is one of those design mistakes that can make life harder for the programmer. A simple typo in a DEFMETHOD form will silently define another generic function. Fun debugging stuff like that.
10:17:57
beach
We have gotten rid of most such design mistakes over the years. Fortran contained lots of those (maybe still does?) and the same thing holds for C.
10:18:36
bitblit1
So, I should make close, render, and other important functions methods of my canonical class?
10:18:52
loke[m]
beach: That's why you have to put `implicit none` in the beginning of your fortran source ;-)
10:31:02
splittist
bitblit1: a literal CLOSE is going to conflict with CL:CLOSE if (as seems likely) you've USEd the cl package. But you probably meant CLOSE-WINDOW (:
10:34:32
bitblit1
Ohhh, yeah I was lliterally just trying to debug that problem, thanks a lot splittist
10:41:22
splittist
Has anyone been working on a baserow/smartsheet style thing (web-based, user-configurable db frontend) in lisp?
10:44:13
phantomics
splittist: I built a system that's basically a web-based visualizer for CL forms and systems that includes a spreadsheet module
10:45:50
splittist
phantomics: possibly even better. The forms/systems were persisted as source, in the image, with backups, all of the above, or I'm completely misunderstanding things (:
10:46:49
phantomics
The forms and systems were persisted as source, specifically ASDF systems were the top-level division
10:47:53
phantomics
It could have been used as a DB frontend, just wasn't limited to that. The project is dormant with plans to build a new version once some of my other dev goals are reached
10:48:43
phantomics
It's called Seed, you could say it was a very different kind of IDE with support for multiple visual programming frontends whose input composed to CL source code in an ASDF system
10:50:08
splittist
phantomics: cool. (I don't want to think about how many 'dev goals' I have on the stack...)
10:53:13
phantomics
Hi beach, I heard you had a project to build an assembler that's portable across CLs, is that correct?
11:01:31
bitblit1
The safety 3 and other optimizations made my life sooooo much easier... hahaha I was coding with a (little) pain for so long
11:01:48
beach
phantomics: I don't see that there is any implementation-specific code in an assembler, so I don't see why any care needs to be taken to make it portable.
11:04:21
phantomics
Very cool, so there's potential to expand it to other architectures as well? Could it be used to build functions and load them in a running CL instance the way you would any other function?
11:05:57
phantomics
About implementations and assemblers: I've been working with SBCL's vop system to do JIT assembly of optimized kernels, one caveat with the vops is that there are some registers you shouldn't use because SBCL uses them and you can clobber values that are needed by the compiler
11:06:02
beach
Yes, I want to add support for RISC-V, but most architectures are trivial compared to x86. Whether you could use it in an implementation would depend on how that implementation is designed, I would think.
11:07:15
phantomics
For instance, in 2.3.0 putting anything in R12 and R13 will cause memory faults, I was able to avoid this by putting them on the stack for the duration of the function and popping them at the end, but I was advised not to do this and also that the restricted registers may change from version to version of SBCL
11:07:17
beach
phantomics: I had no ambition to create an assembler for any existing implementation, so I didn't give any particular thought to that aspect.
11:07:45
hayley
Yes, don't do that. From memory, R12 is used for thread-local state, and R13 for the card map used by the garbage collector.
11:08:17
hayley
Are you performing your own register allocation? I think the register allocation done for VOPs would already avoid those registers.
11:08:34
phantomics
So in order to assemble loadable functions you need to know the gotchas for a given implementation, and those may change between versions.
11:09:39
phantomics
hayley: I was experimenting with manual allocation, now I only manually allocate the A and D registers because you need to handle them specifically due to their role with MUL, DIV and some other stuff
11:09:50
beach
phantomics: Sure, an assembler just takes representations of instructions (in this case as instances of standard classes) and produces a sequence of bytes. It is up to the user to put in the right instructions and the right arguments to those instructions, including the registers.
11:12:12
phantomics
Perhaps CL implementers could include a parameter listing the registers that shouldn't be changed and any other gotchas that an assembler needs to avoid on a given impl
11:14:55
hayley
It would also be necessary to have a way to install a function from a byte vector, which might be awkward for ECL, and more awkward for ABCL.
11:15:56
phantomics
The performance of the JIT-built vops has been amazing, April's performance for the specific operations I've optimized may be the fastest of all CPU-based APLs, unfortunately it's limited to SBCL for now
11:16:58
beach
phantomics: It is not that simple. Some registers could be used for other things in some parts of the code, but not in other parts of the code.
11:17:20
hayley
(See <https://www.softwarepreservation.org/projects/apl/Papers/DYNAMICINCREMENTAL> for reference)
11:19:08
phantomics
Short answer: yes. April has been rebuilt implementing lazy evaluation in the last year. The code generated by the compiler produces a tree of CLOS objects whose methods generate an optimized function for transforming an array
11:19:30
hayley
(Or, in a Common Lisp context, I might as well ask if it's more like Petalisp (which does all the data flow analysis, and compiles larger "kernels") or numcl (with functions individually hand-tuned).)
11:20:45
phantomics
One of the most dramatic things it lets you do is for example (april-f "5 5↑¯20 ¯20↓80 80↓3/20⌽2000000 2000000⍴⍳10*10")
11:21:30
phantomics
This is creating a 2 million square matrix, rotating, stretching and cropping the entire thing, then taking the upper-left 5x5 of it
11:22:51
phantomics
Because it starts from the end and works backwards only the 25 output elements are actually computed
11:24:33
phantomics
The array restructuring functions work by processing array indices as encoded integers. For instance, if you have a 3D array whose dimensions are all under 256, its coordinates can be encoded in a 32-bit int. Coordinates (1, 2, 3) can be encoded as #x00010203 for example
11:25:52
phantomics
So for instance if you're doing a take of the array which crops off 10 elements on all sides, all you need to do is add #x000A0A0A to each coordinate value
11:26:31
phantomics
You can chain these operations together to do multiple array transforms in a single loop without writing the intermediate arrays into memory
11:28:50
phantomics
Using CLOS initialize-instance and metaclass allocator overrides, it's also possible to obviate some classes when they're created
11:29:29
phantomics
For example, 3⌽3⌽X becomes 6⌽X and ⍉⍉A becomes just A because two successive permutes cancel each other
11:59:59
bitblit1
phantomics: Not really, just random stuff. I am making a window manager called blitter-wm and other small projects like a calculator for CLOSOS.
12:05:10
bitblit1
Not really, just for myself. I was tired of StumpWM being wierd and unmaintined. Wanted a simple X window manager entirely in CL which would be super customizable. However, this was my secret preperation for making a WM for CLOSOS
12:14:01
phantomics
If you could get some workflow display logic in there would be cool, like being able to spawn collections of windows and desktops for a specific task
12:14:49
bitblit1
phantomics: Could you elaborate a little more? I would love suggestions! Also, you can be sure to add them as TODOs (issues in git repo)
12:16:55
phantomics
Say I want to define a task like video editing, which will involve the video editor, Inkscape for designing caption graphics and Audacity for creating the audio track. It will start those programs and display them in a specific defined layout with constraints based on the monitor form factor
12:18:07
phantomics
And also give a set of key shortcuts for moving between them. Another simpler workflow could be "image editing with April" where I have an Emacs window for interacting with April and an image viewer window for viewing the image I'm generating. This can be done entirely in Emacs but it could also be a workflow based on multiple desktop apps
12:20:54
phantomics
I could put a TODO but it's not very concrete as a goal, something more specific that you could improve over Gnome/KDE/xfce is configuring keyboard shortcuts for doing different things, a Lisp-based config would be great for stuff like that with unlimited options
12:30:02
phantomics
You may want to look into the Cassowary constraint solver for layout logic: https://github.com/slightlyoff/cassowary.js, https://constraints.cs.washington.edu/cassowary/
12:47:18
phantomics
Here's a discussion of Cassowary and some other algos: https://news.ycombinator.com/item?id=13124584
13:01:57
bitblit1
How do I create a macro wrapper around a function which is sensitive to keyword arguments passed to it effeciently? For example:
13:02:25
bitblit1
I have a function whose argument list looks like this: `(&key (host "") (display 0 display-p) (screen 0 screen-p))`
13:03:00
bitblit1
I want to create a macro/function which would run it in a separate thread and take the exact arguments
13:09:34
flip214
bitblit1: you can use &rest to capture all arguments and relay them on; but be aware that a macro gets _unevaluated_ arguments whereas the function gets _evaluated_ args
13:13:42
flip214
bitblit1: see the last example on http://www.lispworks.com/documentation/HyperSpec/Body/03_daf.htm