December 19, 2022
On Monday, 19 December 2022 at 16:03:36 UTC, bachmeier wrote:
> What you're proposing barely qualifies as breakage.

Yeah, and the dub users wouldn't even notice it since I'll just add another 50 lines to dub.json for them. (Though they will be the ones to see the version number update. I tell people to use >= instead of ~> like dub suggests since what I consider a breaking change is almost certainly not going to affect them, but since ~> is the default they might be trapped on an old version for some time. oh well)

> The entire thing is this 25-line file:

Oh yes, I remember this. It is a cute little program.

> From time to time I'll add a web interface on localhost to a D utility I've written. That sort of thing.

Little web interfaces are actually not half bad for a lot of things. You might enjoy experimenting with that cgi dispatcher some day, with its `serveApi` function it can auto-generate html forms form D functions. I haven't written much documentation of this stuff yet though.

But check it out:

---
import arsd.cgi;

class TheClass : WebObject {
        @UrlName("") // indicate this is the root function
        string hello(string name) {
                return "Hello, " ~ name ~ "!";
        }

        static struct Info {
                string name;
                string title;
        }

        @AutomaticForm
        @(Cgi.RequestMethod.POST)
        Info[] withAutomaticForm(Info[] info) {
                return info;
        }
}

mixin DispatcherMain!(
        "/".serveApi!TheClass
);
---

For this one, you will want to compile with `dmd -i` with the arsd repo cloned locally, since it requires cgi.d, dom.d, and jsvar.d. Of course, you can just download them and build with the explicit list too.

Relatively slow build for an arsd module, about 1.6s for this example on my computer, but I've still kept it kinda under control despite the code gen magic it is doing behind the scenes.

But anyway, run it! Here, I put a binary up so you can try yourself:

http://arsdnet.net/cgi-bin/ncgi3/?name=D+fan

http://arsdnet.net/cgi-bin/ncgi3/with-automatic-form

You can see how it builds the form and some data output all from the D struct and function definitions. Not ideal for user-facing stuff (that's where you get into all the other code like custom presenter classes or the arsd.webtemplate module etc), but if you want a quick ui to call some things i quite like what it does automatically.

And of course it can do the json output too:

http://arsdnet.net/cgi-bin/ncgi3/?name=D+fan&format=json
December 19, 2022
On Mon, Dec 19, 2022 at 08:57:26PM +0000, Adam D Ruppe via Digitalmars-d wrote:
> On Monday, 19 December 2022 at 20:18:54 UTC, H. S. Teoh wrote:
> > On that note, though, it would be nice if D had some kind of feature where only actual dependencies end up in the executable, i.e., end-to-end pay-as-you-go.
> 
> It does, and it has for over five years now! This is the only reason why this change is even on the table at all.
> 
> This is what `dmd -i` does. Only things actually imported are compiled at all. Then you keep your imports local in templates which means they now happen on function-level granularity.

Well I know what `dmd -i` does. :-P  What I had in mind was something more radical: importing a module would *not* trigger inclusion of the entire module's code; only the parts that are actually referenced.  Say module M contains functions A, B, C, each of which references symbols X, Y, Z, respectively, in modules J, K, L.  As it currently stands, if you import X, then `dmd -i` will also import J, K, L for you.  However, if you only call X.A, then in theory the symbols from K and L will never actually get used.  In my ideal vision, K and L would *not* be imported in this case.

Now, today this can already be done to some extent by moving the imports of J, K, L into the respective function bodies as local imports, and making them template functions.  This however only works for templates, and isn't scalable to the case where module M contains multiple functions that import the same module; in that case it's probably better to move the import to module level instead of repeating the import inside every function that might need it.  And if you can't use template functions for whatever reason, you're also stuck.

An even more extreme (and probably impractical) extension of this the elimination of code paths that can be determined at compile-time never to execute. E.g., most programs would not need all of the format handlers inside writefln(). If you never need to format a float, then the float-formatting part of writefln()'s implementation is just dead weight and ought to be eliminated.  I don't think the current implementation of format() is capable of doing this (the implementation inside is a hairball of interdependent pieces that are almost impossible to extricate independently).


[...]
> The linker can also further strip unreferenced things from the executable afterward, and if you're careful about your import web, this can be very effective (and it sometimes can be too even if you aren't careful, but any module constructors being present have a habit of defeating the linker's stripping since it can't know if it is actually necessary or not).
[...]

In an ideal world, there would be a list of symbols touched by the module ctor, and if the reference graph containing these symbols is disjoint from main(), then the corresponding code can also be elided.


T

-- 
MS Windows: 64-bit rehash of 32-bit extensions and a graphical shell for a 16-bit patch to an 8-bit operating system originally coded for a 4-bit microprocessor, written by a 2-bit company that can't stand 1-bit of competition.
December 19, 2022
On Monday, 19 December 2022 at 19:57:24 UTC, Guillaume Piolat wrote:
> Besides, it can be non-breaking when using dub subpackages, using sourceFiles.

Yeah, the dub users probably won't notice it at all, since I'll add the dependency to the subpackage in my config.

But sourceFiles btw isn't great for this since you can end up with multiple definitions of things if people use multiple subpackages together. I've found the best way to do it is to make each module that can be used alone into its own subpackage and then list that as a dependency.

It is a huge hassle to essentially reinvent what the compiler does natively... but it also seems to avoid the most problems when people do start mix and matching. And that's something I still will continue to support - while I provide a little of everything, I try not to force you to buy into my worldview just to use a little bit. If you like my png.d but not my simpledisplay.d, that's ok, they work well together but they also work just fine independently. Or if you like my simpledisplay but prefer your own image formats lib, it shouldn't be too hard to make adapters for the interfaces since I still try to keep things decoupled.

Just at the same time, having a common core to import that defines a few of these interfaces helps with that interop too, which is why I'm looking at this.
December 19, 2022
On Mon, Dec 19, 2022 at 09:56:37PM +0000, Adam D Ruppe via Digitalmars-d wrote: [...]
> And that's something I still will continue to support - while I provide a little of everything, I try not to force you to buy into my worldview just to use a little bit. If you like my png.d but not my simpledisplay.d, that's ok, they work well together but they also work just fine independently. Or if you like my simpledisplay but prefer your own image formats lib, it shouldn't be too hard to make adapters for the interfaces since I still try to keep things decoupled.

In one of my projects, I actually used a subset of arsd.terminal.Terminal's API as the basis for introspecting terminal-like objects in the code. There are a bunch of generic functions that use DbI to implement terminal-like functionality on things like virtual screens, sub-screens, buffering screens, etc., and of course Terminal itself.  One in particular is a function call capture proxy that records calls to (a subset of) Terminal functions and saves them to a file, that can later be played back by a separate program. The playback can be to an instance of Terminal, or to another terminal-like virtual screen that renders the playback into pixels using some user-configured font and outputs an animated gif. :-D  All of these can be more-or-less transparently swapped (and to a lesser extent Terminal itself, because I was too lazy to implement DbI for all of its methods, I just arbitrarily chose the subset I use the most), giving rise to all sorts of cool tricks.

Your modules being more-or-less independent of each other was an important factor in making this possible. If Terminal had, for example, used some type defined by another module into its API, it would have made these DbI adapters more klunky to write, because another terminal-like wouldn't be able to define its own equivalent of that type without running into potential conflicts.


> Just at the same time, having a common core to import that defines a few of these interfaces helps with that interop too, which is why I'm looking at this.

Makes sense, as long as core.d doesn't grow without bound. ;-)


T

-- 
Stop staring at me like that! It's offens... no, you'll hurt your eyes!
December 19, 2022
On Monday, 19 December 2022 at 21:41:47 UTC, Adam D Ruppe wrote:

>> From time to time I'll add a web interface on localhost to a D utility I've written. That sort of thing.
>
> Little web interfaces are actually not half bad for a lot of things. You might enjoy experimenting with that cgi dispatcher some day, with its `serveApi` function it can auto-generate html forms form D functions. I haven't written much documentation of this stuff yet though.

I wasn't aware of it, but I'll give it a try. This is kind of how we used to use Tcl to make GUIs for scripts, but without the 1980s appearance on Linux.
December 23, 2022
I use some of your stuff so I'll chime in. I don't automatically pull in files and so the updates to modules is done by hand in my case, so you adding a few dependencies is not a problem.

But I do not pull in the full arsd repo & I'd hate to see that to become a requirement. In general I love the "its just a few files you can add" to dependency management, but I don't mind it becoming a couple of files.

As for event loop stuff, there is a golden rule in my eyes, as long as there is a way to own the loop, just call a poll/dispatch function and I can still use the thread, there should be no issue with it.

The moment that is not the case that's when that type of stuff turns painful :^)
December 23, 2022
On Friday, 23 December 2022 at 07:55:31 UTC, Greggor wrote:
> But I do not pull in the full arsd repo & I'd hate to see that to become a requirement. In general I love the "its just a few files you can add" to dependency management, but I don't mind it becoming a couple of files.

Yeah, there's some temptation to break out a few more interfaces... well, ok i admit it is more than just some temptation, there's actually four or five files I'd probably add if there was zero concern (I'd do the eventloop+error handling+validation helper core, then a circular buffer container, the text layouter, and then possibly a couple more)...

but I think I'll resist that and just put a set of things in the one additional core.d file, that compromise I think will do what I need it to do. The others in the list aren't as important.

And of course, it is possible to keep doing things how I do it now, with some duck-typed interfaces that happen to be compatible if you pass the right arguments, then I copy/paste what needs to be pasted. But that's getting a bit limiting since i don't copy *everything*.

> As for event loop stuff, there is a golden rule in my eyes, as long as there is a way to own the loop, just call a poll/dispatch function and I can still use the thread, there should be no issue with it.


eeeeeh, you shouldn't have to! but yeah, if you look at my http2.d current thing that's the model I've been coming to like. There's an `advance` function, a `addToSimpledisplayEventLoop` function which offers a file descriptor to integrate with an external thing, then the individual tasks can `waitForCompletion` and such.

then, of course, you do have a static `runEventLoop` kind of thing to just drop and run.

So you get some control but it might be a lot of extra work depending on what you're doing around it. Whereas if you make use of the event model you ought not need to do other stuff in the middle; you might even run the events in a separate thread and just queue messages back to this one.

I haven't worked out the exact details yet but I'm fairly happy with how that http2.d thing has worked out api-wise, and the simpledisplay core is pretty solid allowing for integrations, so I'll probably just generalize those.

Either way, yes, I do try to keep things decomposable so you can mix and match what you want. It might be a lil extra work for both of us but p sure I can keep it working for all these cases.

(and I plan to keep my existing apis forwarding to the new thing, to avoid code breakage, and this also forces me to do it in a flexible way since my own existing things will require some of it)
December 24, 2022
I don't mind the changes, go for it!


1 2
Next ›   Last »