My DConf talk on the language is now up too! https://www.youtube.com/watch?v=nDqlYnS-K2c
My DConf talk on the language is now up too! https://www.youtube.com/watch?v=nDqlYnS-K2c
- proper macros
- proper sumtypes with implicit conversion
- more normal lambdas (seriously, D's lambdas are wild)
- faster compiler with more caching and (maybe) eventually live reload?
- proper packages instead of include path.
And a bunch of small fry like format strings and named parameters.
And yeah, um, GC can be good but the D GC kind of isn't. We use D at work, and we run into GC issues frequently. Neat's RC is a much thinner wrapper around C memory allocation, which is just better imo, much as GC and RC are logically equivalent in some ways.
int factor = 2;
assert([2, 3].map!(a => a * factor).array == [4, 6]);
Then the `!` indicates that you're actually passing the lambda as a compiletime parameter to `map`. But the lambda can access the surrounding context! How does it pass a runtime value at compile time?So what you're passing is actually purely a function symbol. The way that it gets the stack reference to the surrounding function is that it's actually a nested function. And the way that `map` gets the stack reference to pass to the lambda is that, effectively, that instance of `map` is also a nested function of the calling function.
That's also why you cannot pass a lambda as a template parameter to a class method in D: it already has a context parameter, ie. the class reference.
In Neat, the value of the lambda is the stackframe reference, and it's just passed as a regular parameter:
int factor = 2;
assert([2, 3].map(a => a * factor).array == [4, 6]);
Which avoids this whole issue at the cost of requiring some cleverness with refcounting.It also encourages people not to think about what the structure of their templates, so you can end up with truly massive amounts of duplication.
Please elaborate on this. It's something I'm trying to get right in my own language since day one. I see in your language's manual that you have chosen to implement modules as files and packages as directories. I came up with something very similar but special cased the main module file so that the entire module could be contained in its directory.
my-module/
my-module.ln
(import (my-module)); reads my-module/my-module.ln
How do you represent modules in your implementation? How do you handle module loading? What paths do you search? Do you support Linux distribution packaging? This last feature is something I'm interested in supporting, I added system directories to my search path for this reason but I wonder if there's anything else that I need to do.So Neat's actual hierarchy is "file [> folder]* > package", where `package` itself is optional in the import declaration: you can write `import package(gtk).gtk`, but you don't have to. This is occasionally useful during bootstrap builds when you want to clarify which version of the compiler an import is coming from: the current running compiler is always `package(compiler)`.
This is all because I've been writing it with something like a package manager in mind from essentially day one.
edit: I'm not looking at distribution packaging right now, because I'm not looking at non-source libs at all. That's something that can come later if it's needed at all.
It would be indeed quite neat (pun intended) to see D adopt them as well, specially sumtypes, Rust went ahead and made enums better, it's quite an expected feature for a language at this point
So much good has come of it...
Are the changes to the language going to make it much better? Break existing code? How long until they finish that, is it nearing completion or just beginning now?? So many questions as someone new to D.
The problem the OP was talking about is that in D, you cannot implicitly use an `int`, say, where `SumType!(int, string)` is expected.
You need something like this:
alias StrOrInt = SumType!(int, string)
void takeStrOrInt(StrOrInt s)
{
writeln(s);
}
StrOrInt value;
value = 10; // ok
value = "foo"; // ok
takeStrOrInt(value); // ok
//takeStrOrInt(10); // not ok
//takeStrOrInt("foo"); // not ok
takeStrOrInt(StrOrInt(10)); // ok
takeStrOrInt(StrOrInt("foo")); // ok
Even though this is not perfect, it works quite well (I believe it's zero cost to do `StrOrInt(10)` for example, but I'm a D newbie).
It's a bit crazy for me to see people creating new languages instead of help improving existing ones because of minor stuff like this. The effort to create a language and a stdlib and a package manager etc. is ridiculously high compared to improving existing languages. publish(TrackingEvent(UpdateTrackerEvent(trackerId, position)));
that just adds visual noise. And the fact that you cannot return out of sumtype apply expressions just makes so many neat idioms impossible. Something like Object obj = nullableObj.case(null: return false);
is just fundamentally impossible in D.So it's not one thing, it's a lot of things coming together. :) Mostly I just realized one day that D was never going to be the perfect language for me, because it wasn't even interested in being that language.
> The effort to create a language and a stdlib and a package manager etc. is ridiculously high compared to improving existing languages.
Have you seen the DMD source code? Genuinely, writing my own compiler was easier than improving DMD.
But the mere fact that the primary ascribed goal is "fun" suggests it is not be taken seriously for actual work projects.
(Though I will be proper chuffed if you do. I just can not recommend it.)
To be honest, my goal is to have maybe 10 to 50 users right now. That'd be quite enough for this christmas.
As a funny side note, I read the part on your website where you talk about why you chose reference counting over garbage collection, and despite your light-hearted resentment of the fact that garbage collection is such a turn off for people, the fact that your language doesn't use garbage collection is one of the major factors in why she might end up using it lol. We decided not to do C# (my first suggestion actually) because since she doesn't want to use an engine, it wouldn't be used just as a scripting language, but for the entire object model and update loop and so on, so GC would be a dealbreaker. Sorry-
(tiny rant mode as a hobbyist gamedev myself) there is actually a good reason for this -- it is much easier to do multithreading when you don't have a separate thread going over all shared memory, and it's much easier to do a soft real time thing like game development if your memory allocation and deallocation stays relatively consistent and predictable, even if it is slower overall. Also, yes malloc may cause variable slowdowns too, but definitely to a smaller degree/varience than the average garbage collector and more predictably since you can control when allocations happen; otherwise there wouldn't be a noticeable difference between using garbage collected and non garbage collected languages for writing large-scale games. Plus, in any case, that's the reason why game developers tend to try to limit dynamic allocation at runtime in the first place.
Not yet, but I'm sure she'll be overjoyed to! She's so excited about this language, it'll finally make low level small scale gamedev accessible to her! :D
> Anyway, please also tell her to hit up the Discord (or IRC) for any questions!
I will! I'm sure she'll be excited there's an IRC
He doesn't have much time for the agents of corporations who through their foundations and charities aim to influence and seize control of such groups with their demands for CoCs, DEI in return for some funding and their choice of board appointees.
Nim has been getting along fine without them and will continue to.
I didn't notice any mention of tail calls. Does it support proper tail calls?