www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A D vs. Rust example

reply Don Allen <donaldcallen gmail.com> writes:
I've mentioned in past messages that I had ported a suite of 
personal financial management tools successfully from C to D 
after first attempting the work with Rust. I thought I'd give you 
an example of one of the many headaches I encountered with Rust, 
because it's illustrative of my contention that Rust's memory- 
and thread-safety without a GC makes the programmer a much more 
active participant in the memory-management system than do 
languages equipped with a GC. It's a primary reason why Rust is 
so much more difficult to learn than languages with GC support.

I'm a Scheme enthusiast and have written a lot of it over my many 
years. A common pattern that is so easy to address in Scheme is a 
situation where a number of variables get set, usually at the 
head of a loop, and those variables (sometimes mutable, if they 
are, for example, Sqlite prepared statements) are needed by a 
number of functions that are part of the processing. Being able 
to define closures inside the loop that see those variables as 
part of their environment makes the code simpler, cleaner, and 
easier to write, as opposed to passing the needed variables as 
arguments to the functions at every calling site, C-style.

Rust has closures. Great. So here's an example of an attempt to 
do something along the lines described above with a single 
mutable variable:

````
fn main() {
     let mut foo = 5;
     let mut bar = || {
         foo = 17;
     };
     let mut baz = || {
         foo = 42;
     };
     bar();
     println!("{}", &mut foo);
     baz();
     println!("{}", &mut foo);

}
````
I have a single mutable variable, foo, and two closures, bar and 
baz, that each mutate the variable. This solution isn't so bad, 
yes? Except it doesn't compile:
````
    Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `foo` as mutable more than once at a 
time
   --> src/main.rs:7:19
    |
4  |     let mut bar = || {
    |                   -- first mutable borrow occurs here
5  |         foo = 17;
    |         --- first borrow occurs due to use of `foo` in 
closure
6  |     };
7  |     let mut baz = || {
    |                   ^^ second mutable borrow occurs here
8  |         foo = 42;
    |         --- second borrow occurs due to use of `foo` in 
closure
9  |     };
10 |     bar();
    |     --- first borrow later used here

error[E0499]: cannot borrow `foo` as mutable more than once at a 
time
   --> src/main.rs:11:20
    |
7  |     let mut baz = || {
    |                   -- first mutable borrow occurs here
8  |         foo = 42;
    |         --- first borrow occurs due to use of `foo` in 
closure
...
11 |     println!("{}", &mut foo);
    |                    ^^^^^^^^ second mutable borrow occurs here
12 |     baz();
    |     --- first borrow later used here

For more information about this error, try `rustc --explain 
E0499`.
error: could not compile `playground` due to 2 previous errors
````
The problem is that the mutable borrows of foo in each of the 
closures occur, in effect, when the closure is defined, not when 
it is called. The compiler views this just as it would two 
assignments to foo -- two mutable borrows in the same scope -- 
and refuses to compile the program.

The solution is to use "interior mutability", which I view as a 
bit of a hack to get around the limitations of compile-time 
borrow-checking. Interior mutability lets you mutate variables 
that look immutable to the compiler and the safety of what you do 
is checked at runtime (so much for "zero cost"). Here's what the 
code looks like to fix the above using this approach:
````
use std::cell::RefCell;

fn main() {
     let foo = RefCell::new(5);
     let bar = || {
         *foo.borrow_mut() = 17;
     };
     let baz = || {
         *foo.borrow_mut() = 42;
     };
     bar();
     println!("{}", foo.borrow());
     baz();
     println!("{}", foo.borrow());
     }
````
This works, but at the cost of readability and some runtime 
efficiency.

The D equivalent:
````
import std.stdio;

void main()
{
     int foo;
     void bar() {
         foo = 17;
     }
     void baz() {
         foo = 42;
     }
     bar();
     writeln(foo);
     baz();
     writeln(foo);
}
````

This is just one of multiple examples I personally encountered 
where Rust's approach to memory- and thread-safety makes life 
difficult for its users. On simple cost-benefit grounds, I can 
see using Rust for writing OS drivers (or even an entire OS) or 
for use in embedded systems, especially if there's a real-time 
constraint; in other words, where a GC would be unsuitable. But 
for ordinary applications on today's hardware? Use of Rust 
instead of D, Go, Nim, etc. makes no sense to me.
Oct 20 2022
next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 [snip]
 The D equivalent:
 ````
 import std.stdio;

 void main()
 {
     int foo;
     void bar() {
         foo = 17;
     }
     void baz() {
         foo = 42;
     }
     bar();
     writeln(foo);
     baz();
     writeln(foo);
 }
 ````
[snip]
TIL that this works...I thought it would only work for global/static variables.
Oct 20 2022
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/20/22 07:09, jmh530 wrote:

 TIL that this works...I thought it would only work for global/static
 variables.
Similar nested function examples appear at the following point during one of my presentations: https://www.youtube.com/watch?v=dRORNQIB2wA&t=2419s Ali
Oct 20 2022
parent jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 20 October 2022 at 15:54:45 UTC, Ali Çehreli wrote:
 On 10/20/22 07:09, jmh530 wrote:

 TIL that this works...I thought it would only work for
global/static
 variables.
Similar nested function examples appear at the following point during one of my presentations: https://www.youtube.com/watch?v=dRORNQIB2wA&t=2419s Ali
I suppose I just don't make much use of nested functions. Might consider making more useof them, when needed.
Oct 20 2022
prev sibling next sibling parent user1234 <user1234 12.de> writes:
On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 [...]
 This is just one of multiple examples I personally encountered 
 where Rust's approach to memory- and thread-safety makes life 
 difficult for its users. On simple cost-benefit grounds, I can 
 see using Rust for writing OS drivers (or even an entire OS) or 
 for use in embedded systems, especially if there's a real-time 
 constraint; in other words, where a GC would be unsuitable. But 
 for ordinary applications on today's hardware? Use of Rust 
 instead of D, Go, Nim, etc. makes no sense to me.
Thanks, that's very interesting. I've remarked that the problem in the first example is that Rust does not seem to detect that the two closures are not escaped, i.e it seems it has no notion of a difference between nested functions and lambdas.
Oct 20 2022
prev sibling next sibling parent reply IGotD- <nise nise.com> writes:
On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 This is just one of multiple examples I personally encountered 
 where Rust's approach to memory- and thread-safety makes life 
 difficult for its users. On simple cost-benefit grounds, I can 
 see using Rust for writing OS drivers (or even an entire OS) or 
 for use in embedded systems, especially if there's a real-time 
 constraint; in other words, where a GC would be unsuitable. But 
 for ordinary applications on today's hardware? Use of Rust 
 instead of D, Go, Nim, etc. makes no sense to me.
Actually, Rust is even worse for embedded, OS, near hardware programming. The memory model just gets in the way of doing those things. Example of things in OS programming are often intrusive containers, pointers/references pointing in all directions and sometimes even to itself, multiple use of containers for the same object, chicken and egg problems. This is where the memory model of just Rust breaks down. Of course you have to use unsafe everywhere but as soon as you do that, things get ugly very quickly. For these tasks C++ is still the obvious choice. However, this is not normal programming and you have to do tricks that you never usually do in application programming. In short Rust is a useless language for embedded and it would take forever to become productive. Also information how to do this in Rust is difficult to find as most of Rust programs are just normal applications and that is also what Rust was originally designed for. I've tried several languages in order to evaluate how it can deal with embedded programs (more advanced than just blinking a LED, real resource handling). I've evaluated Rust, D, Nim, Swift among others and Rust got the place at very bottom by a great margin. There were simply things I couldn't do in Rust and even if it possible it would have taken ages do figure out how to do it. The other languages were more easy, not perfect and you had do deal with some quirks but you understood why and how you could work around them. Just like you I found out how the memory model isn't even zero cost with that you quickly have to resort to reference counting and with that RefCell (which is a runtime check) must be used as you suddenly have several possible paths of mutuable borrows. For financial software I would run from Rust faster than a rabbit. It's just too complicated and other languages offer faster developing times with more convenient libraries. I'm puzzled with the high popularity of Rust, like some kind of mass exorcism.
Oct 20 2022
next sibling parent reply Don Allen <donaldcallen gmail.com> writes:
On Thursday, 20 October 2022 at 14:26:07 UTC, IGotD- wrote:
 On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 This is just one of multiple examples I personally encountered 
 where Rust's approach to memory- and thread-safety makes life 
 difficult for its users. On simple cost-benefit grounds, I can 
 see using Rust for writing OS drivers (or even an entire OS) 
 or for use in embedded systems, especially if there's a 
 real-time constraint; in other words, where a GC would be 
 unsuitable. But for ordinary applications on today's hardware? 
 Use of Rust instead of D, Go, Nim, etc. makes no sense to me.
Actually, Rust is even worse for embedded, OS, near hardware programming. The memory model just gets in the way of doing those things. Example of things in OS programming are often intrusive containers, pointers/references pointing in all directions and sometimes even to itself, multiple use of containers for the same object, chicken and egg problems. This is where the memory model of just Rust breaks down. Of course you have to use unsafe everywhere but as soon as you do that, things get ugly very quickly. For these tasks C++ is still the obvious choice. However, this is not normal programming and you have to do tricks that you never usually do in application programming. In short Rust is a useless language for embedded and it would take forever to become productive. Also information how to do this in Rust is difficult to find as most of Rust programs are just normal applications and that is also what Rust was originally designed for. I've tried several languages in order to evaluate how it can deal with embedded programs (more advanced than just blinking a LED, real resource handling). I've evaluated Rust, D, Nim, Swift among others and Rust got the place at very bottom by a great margin. There were simply things I couldn't do in Rust and even if it possible it would have taken ages do figure out how to do it. The other languages were more easy, not perfect and you had do deal with some quirks but you understood why and how you could work around them.
Thank you for your evaluation of Rust for embedded work based on actual experience, which I don't have. I think the lesson of both yours and my experience is that you have to actually try it, get your hands dirty, to understand whether Rust is suitable for both your problem domain and your programming style. You will learn nothing from reading the hype (Exhibit A: the "affectionately named" Book; was this written by a 12-year-old?). I mention the programming style because, for example, someone who had spent their programming life writing C would likely not have encountered the closure issue I did. If all the functions are at top level and everything they need is passed to them as arguments, no problem.
 Just like you I found out how the memory model isn't even zero 
 cost with that you quickly have to resort to reference counting 
 and with that RefCell (which is a runtime check) must be used 
 as you suddenly have several possible paths of mutuable borrows.

 For financial software I would run from Rust faster than a 
 rabbit. It's just too complicated and other languages offer 
 faster developing times with more convenient libraries.

 I'm puzzled with the high popularity of Rust, like some kind of 
 mass exorcism.
People (alarmingly frequently) mindlessly jump on band-wagons. We're seeing it in today's politics, but I'll stop right there before destroying this forum :-)
Oct 20 2022
parent reply Don Allen <donaldcallen gmail.com> writes:
Where I do think D would do well by emulating Rust is in the area 
of helpful compiler warnings: noting unused variables, constants 
and imported symbols, pointing out unnecessary parentheses, etc.

I do realize that Walter has emphasized compilation speed in dmd 
and that is a worthy goal. In pursuit of that, some of what I'm 
suggesting may not be possible with dmd's current level of 
analysis of the source code. But to the extent that tradeoff 
exists, I'd suggest re-thinking it. The Rust compiler is much 
slower than dmd, but I personally did not find its speed (or lack 
thereof) to be a big issue for me while I was doing Rust 
development (on contemporary hardware with ~4ghz processors, 32 
GB of memory and an NVME SSD). Perhaps there's a cake-and-eat-it 
solution that would make the additional analysis and resulting 
warnings optional, so those running on old hardware or care more 
about compilation speed than the warnings could have it their way 
too.
Oct 20 2022
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 21/10/2022 4:25 AM, Don Allen wrote:
 Where I do think D would do well by emulating Rust is in the area of 
 helpful compiler warnings: noting unused variables, constants and 
 imported symbols, pointing out unnecessary parentheses, etc.
IDE's such as IntelliJ IDEA (D's plugin) call Dscanner all the time to verify code and get warnings. So in practice this shouldn't be an issue.
Oct 20 2022
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/20/22 08:33, rikki cattermole wrote:
 On 21/10/2022 4:25 AM, Don Allen wrote:
 Where I do think D would do well by emulating Rust is in the area of
 helpful compiler warnings: noting unused variables, constants and
 imported symbols, pointing out unnecessary parentheses, etc.
IDE's such as IntelliJ IDEA (D's plugin) call Dscanner all the time to verify code and get warnings. So in practice this shouldn't be an issue.
And there is 'dub lint' that uses dscanner under the hood. Ali
Oct 20 2022
prev sibling parent reply Don Allen <donaldcallen gmail.com> writes:
On Thursday, 20 October 2022 at 15:33:06 UTC, rikki cattermole 
wrote:
 On 21/10/2022 4:25 AM, Don Allen wrote:
 Where I do think D would do well by emulating Rust is in the 
 area of helpful compiler warnings: noting unused variables, 
 constants and imported symbols, pointing out unnecessary 
 parentheses, etc.
IDE's such as IntelliJ IDEA (D's plugin) call Dscanner all the time to verify code and get warnings. So in practice this shouldn't be an issue.
In my experience, it is an issue. dub lint does not warn about unused imports or unused constants, for example. I also don't use an IDE, unless you consider nvim an IDE. And I don't use dub to build my code (I'm open to it, but I've found the documentation thoroughly inadequate), so using its lint to check my code is more than a bit of a pain. So for me, the D existing tools to statically evaluate code in a manner similar to the Rust compiler are just not where I would like them to be.
Oct 21 2022
parent rikki cattermole <rikki cattermole.co.nz> writes:
On 22/10/2022 9:11 AM, Don Allen wrote:
 And I don't use dub to build my code (I'm open to it, but I've found the 
 documentation thoroughly inadequate), so using its lint to check my code 
 is more than a bit of a pain.
DScanner of course is separate from dub, so that isn't an issue if you do something different.
 So for me, the D existing tools to statically evaluate code in a 
manner similar to the Rust compiler are just not where I would like them to be. DScanner is currently being rewritten to use dmd-fe, so these semantically required checks will be implementable (as long as all files required to compile a module is provided).
Oct 21 2022
prev sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Thu, Oct 20, 2022 at 03:25:36PM +0000, Don Allen via Digitalmars-d wrote:
 Where I do think D would do well by emulating Rust is in the area of helpful
 compiler warnings: noting unused variables, constants and imported symbols,
 pointing out unnecessary parentheses, etc.
[...] It would be good to file these as enhancement requests to bugzilla, so that they don't get lost in the dusts of forum history. T -- If you want to solve a problem, you need to address its root cause, not just its symptoms. Otherwise it's like treating cancer with Tylenol...
Oct 20 2022
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10/20/22 18:49, H. S. Teoh wrote:
 On Thu, Oct 20, 2022 at 03:25:36PM +0000, Don Allen via Digitalmars-d wrote:
 Where I do think D would do well by emulating Rust is in the area of helpful
 compiler warnings: noting unused variables, constants and imported symbols,
 pointing out unnecessary parentheses, etc.
[...] It would be good to file these as enhancement requests to bugzilla, so that they don't get lost in the dusts of forum history. T
Such warnings don't carry over well to D though, because template expansion is untyped. Therefore, by default the compiler will check whether the _generated code_ has any of those issues, which is usually just an annoyance. Lots of false positives. I also don't think people should be encouraged to remove unnecessary parentheses, otherwise they will start to also omit necessary ones.
Oct 20 2022
prev sibling next sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Thursday, 20 October 2022 at 14:26:07 UTC, IGotD- wrote:
 On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 This is just one of multiple examples I personally encountered 
 where Rust's approach to memory- and thread-safety makes life 
 difficult for its users. On simple cost-benefit grounds, I can 
 see using Rust for writing OS drivers (or even an entire OS) 
 or for use in embedded systems, especially if there's a 
 real-time constraint; in other words, where a GC would be 
 unsuitable. But for ordinary applications on today's hardware? 
 Use of Rust instead of D, Go, Nim, etc. makes no sense to me.
Actually, Rust is even worse for embedded, OS, near hardware programming. The memory model just gets in the way of doing those things. Example of things in OS programming are often intrusive containers, pointers/references pointing in all directions and sometimes even to itself, multiple use of containers for the same object, chicken and egg problems. This is where the memory model of just Rust breaks down. Of course you have to use unsafe everywhere but as soon as you do that, things get ugly very quickly. For these tasks C++ is still the obvious choice. However, this is not normal programming and you have to do tricks that you never usually do in application programming. In short Rust is a useless language for embedded and it would take forever to become productive. Also information how to do this in Rust is difficult to find as most of Rust programs are just normal applications and that is also what Rust was originally designed for. I've tried several languages in order to evaluate how it can deal with embedded programs (more advanced than just blinking a LED, real resource handling). I've evaluated Rust, D, Nim, Swift among others and Rust got the place at very bottom by a great margin. There were simply things I couldn't do in Rust and even if it possible it would have taken ages do figure out how to do it. The other languages were more easy, not perfect and you had do deal with some quirks but you understood why and how you could work around them. ...
Useless or not, it is becoming a thing, https://www.autosar.org/news-events/details/autosar-investigates-how-the-programming-language-rust-could-be-applied-in-adaptive-platform-context/ https://opensource.googleblog.com/2022/10/announcing-kataos-and-sparrow.html https://azure.microsoft.com/en-us/blog/delivering-consistency-and-transparency-for-cloud-hardware-security/ https://techcommunity.microsoft.com/t5/internet-of-things-blog/previewing-rust-on-azure-sphere/ba-p/3494988 https://github.com/orgs/esp-rs/projects/1 https://www.eenewseurope.com/en/arm-joins-the-rust-foundation/ https://www.phoronix.com/news/Rust-Is-Merged-Linux-6.1 I could keep posting links about Rust's rise on the embedded space, but I think you got the point. Naturally I also agree that systems programming languages with GC should be used, but unless we have a big name pushing them, affine type systems have won for low level systems coding.
Oct 21 2022
next sibling parent reply Guillaume Piolat <first.last spam.org> writes:
On Friday, 21 October 2022 at 10:16:10 UTC, Paulo Pinto wrote:
 affine type systems have won for low level systems coding.
Not sure it will be Rust though. In the new native language camp, Jai and Odin makes use of Scala-like "context" pointer passed to each function to pass around an allocator, a logger... being true to the monadic nature of allocation and logging. With an important difference there, Odin apparently uses a fixed context, and Jai a custom one where you can put anything. Now THAT is an interesting feature to have for embedded.
Oct 21 2022
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 21 October 2022 at 11:54:59 UTC, Guillaume Piolat 
wrote:
 On Friday, 21 October 2022 at 10:16:10 UTC, Paulo Pinto wrote:
 affine type systems have won for low level systems coding.
Not sure it will be Rust though.
It is also not true. C/C++ are still completely dominating. Reactive systems are also done using special tools (functional style). Low level programming is not some narrow field that can be shoehorned into any singular dev environment.
 nature of allocation and logging. With an important difference 
 there, Odin apparently uses a fixed context, and Jai a custom 
 one where you can put anything.

 Now THAT is an interesting feature to have for embedded.
Implicit context pointers have been suggested for Carbon too. (hidden parameter to functions)
Oct 21 2022
parent reply Guillaume Piolat <first.last spam.org> writes:
On Friday, 21 October 2022 at 12:11:13 UTC, Ola Fosheim Grøstad 
wrote:
 It is also not true. C/C++ are still completely dominating. 
 Reactive systems are also done using special tools (functional 
 style). Low level programming is not some narrow field that can 
 be shoehorned into any singular dev environment.
Of course. In the small field of audio, I still haven't seen a single competitive Rust product, despite a lot more ecosystem work from people. And D is super niche there, it's all C++ except formerly FLStudio and Bitwig maybe (the two best DAWs were NOT made with C++). Ironically, Rust not having a lot of support for classical inheritance means people have been building libraries and framework that lacks that essential implementation-hiding subtyping, meaning a creep up of complexity from their subtypes. But building and agreeing on abstractions is what define the ecosystem.
Oct 21 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 21 October 2022 at 13:53:28 UTC, Guillaume Piolat 
wrote:
 work from people. And D is super niche there, it's all C++ 
 except formerly FLStudio and Bitwig maybe (the two best DAWs 
 were NOT made with C++).
And in addition you have a large number of languages that use DSP building blocks written in C. Both for composition, prototyping and application extensions (like in scriptable audio applications).
 But building and agreeing on abstractions is what define the 
 ecosystem.
One big weakness in C++ and D is that generic definitions cannot be checked without instantiation.
Oct 21 2022
parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Friday, 21 October 2022 at 15:13:44 UTC, Ola Fosheim Grøstad 
wrote:
 On Friday, 21 October 2022 at 13:53:28 UTC, Guillaume Piolat 
 wrote:
 But building and agreeing on abstractions is what define the 
 ecosystem.
One big weakness in C++ and D is that generic definitions cannot be checked without instantiation.
There aren’t many languages that have both, templates and generics; C++/CLI and C++/CX are the only ones I know and I happen to have some experience with them. (In this nomenclature: *template* = independent copy of the implementation for every distinct instantiation, cf. C++ or D templates, especially class templates with mutable static variables; *generic* = one depend on the argument types.) D could introduce generics and it would actually profit more from them than e.g. C++ would because D has first-class reference types and almost no user-defined implicit conversions. Templates are not really a replacement for generics. As an example where generics (would) shine and templates fall flat, consider [range interfaces](https://dlang.org/phobos/std_range_interfaces.html). We have (among others) `InputRange` and `BidirectionalRange`. A function taking an `InputRange!Base` parameter should allow for an argument of type `BidirectionalRange!Derived` (with `Derived` and `Base` classes or interfaces). In D, that is not possible because we cannot express the [variance](https://en.wikipedia.org/wiki/Covariance_and_contravariance (computer_science)) of a type parameter; templates are inherently antithetical to that. Imagine how much more attractive D would be to OO crowd if it had first-class value type boxing, generics with variance and wildcards, and all the other OO stuff modern OO-fist languages minimum to call itself object-oriented. There was some talk (by Átila, IIRC) that having first-class classes and OO in D was a design error. I have no idea whether there is actually a plan to fade those out improve them to be competitive on that front.
Oct 27 2022
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 27 October 2022 at 17:37:59 UTC, Quirin Schroll 
wrote:
 There aren’t many languages that have both, templates and 
 generics; C++/CLI and C++/CX are the only ones I know and I 
 happen to have some experience with them.
I have found that it is to some extent possible to do such type checks of generics with C++ concepts. I've made some attempts for a generic graphics library I've started on, but it gets tedious quite fast. I would imagine you could do some of the same in D in a more ad-hoc matter, but that would be even more tedious. It basically involves setting up all the constraints and then test them with a single static assert (which involves instantiation, but in the definition file without explicitly using the instance methods). The C++ concept-feature is helpful in this regard, but not helpful enough to make it pleasant… which basically limits my eagerness to use of it in practice. Still, a move in the right direction. D has a chance to learn from C++ and create a better concept-feature. Don't replicate it, look at the use cases where C++ concepts become tedious or difficult to get right, then design something better.
 D could introduce generics and it would actually profit more 
 from them than e.g. C++ would because D has first-class 
 reference types and almost no user-defined implicit conversions.
This is probably true, but you could instead try to find a way to clearly specify and statically check template requirements.
 Imagine how much more attractive D would be to OO crowd if it 
 had first-class value type boxing, generics with variance and 
 wildcards, and all the other OO stuff modern OO-fist languages 

 minimum to call itself object-oriented.
That is a reasonable angle given the large number of programmers closer look at how templates are done and find out what is missing. When was the last time a feature was added to support generic programming?
 There was some talk (by Átila, IIRC) that having first-class 
 classes and OO in D was a design error. I have no idea whether 
 there is actually a plan to fade those out improve them to be 
 competitive on that front.
OO is not a mistake, I agree. I find it quite frustrating to not have inheritance when programming in Go. Just basic things like having a linked list node in the super class makes things much simpler/cost-efficient when you are mixing types in data-structures.
Oct 27 2022
prev sibling next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Thursday, 27 October 2022 at 17:37:59 UTC, Quirin Schroll 
wrote:
 Imagine how much more attractive D would be to OO crowd if it 
 had first-class value type boxing, generics with variance and 
 wildcards, and all the other OO stuff modern OO-fist languages 

 minimum to call itself object-oriented. There was some talk (by 
 Átila, IIRC) that having first-class classes and OO in D was a 
 design error. I have no idea whether there is actually a plan 
 to fade those out improve them to be competitive on that front.
without the OOP features Rust is becoming the system language of choice without the OOP features Zig is making a dent without the OOP features The more OOP you put in a language, the worst it becomes features doesn't cut it OOP is nice only when kept very simple and minimal
Oct 27 2022
next sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 27 October 2022 at 19:29:15 UTC, ryuukk_ wrote:
 On Thursday, 27 October 2022 at 17:37:59 UTC, Quirin Schroll 
 wrote:
 [...]
language without the OOP features Rust is becoming the system language of choice without the OOP features Zig is making a dent without the OOP features The more OOP you put in a language, the worst it becomes features doesn't cut it OOP is nice only when kept very simple and minimal
OOP is amazing when you stay true to it, which basically no languages do. The only good example of it is something like smalltalk. Or *maybe* Erlang if you think of each process as an object (Yes, of course there are other languages, but to name some)
Oct 27 2022
prev sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Thu, Oct 27, 2022 at 07:29:15PM +0000, ryuukk_ via Digitalmars-d wrote:
 On Thursday, 27 October 2022 at 17:37:59 UTC, Quirin Schroll wrote:
 Imagine how much more attractive D would be to OO crowd if it had
 first-class value type boxing, generics with variance and wildcards,
 and all the other OO stuff modern OO-fist languages offer. Using

 itself object-oriented.
IMO, D doesn't really need any of the heavyweight OO features because typical idiomatic D code doesn't rely heavily on OO, but on other idioms like structs for by-value exchange of data, ranges, and DbI. When the entire language is predicated on OO, like in Java, then you need all the advanced machinery to make OO more tolerable. But when you can simply step outside of the OO box and solve things with other tools, then there isn't a big need for heavy OO machinery.
 There was some talk (by tila, IIRC) that having first-class classes
 and OO in D was a design error. I have no idea whether there is
 actually a plan to fade those out improve them to be competitive on
 that front.
I think it's a bit extreme to call OO support a design error... but I'd say it's true that in most of my D code, I find little need for OO. D-centric idioms like structs, ranges, DbI, metaprogramming, CTFE, already cover most of the areas that languages like Java use OO for; as a result, the role of OO in D is much narrower than in Java.

 without the OOP features
 
 Rust is becoming the system language of choice without the OOP
 features
 
 Zig is making a dent without the OOP features
 
 The more OOP you put in a language, the worst it becomes
I disagree. OOP itself isn't bad; it has its place. For certain things, like programming widget hierarchies, OO totally makes sense, and I'd even recommend using OO idioms for that. What's bad is the fallacious philosophy that OO is the be-all and end-all of programming paradigms (the fanboy attitude that unfortunately permeated the scene in the early days of Java), where you try to shoehorn OO into everything else where it doesn't fit, ending up with ridiculous things. Like static singleton "classes" with static methods, whose sole purpose of existence is to give you bragging rights that your code is fully OO-certified, without "bad" things like global functions and global variables. (Spoiler: you just used them, only under a different name.) Sometimes, I daresay even oftentimes, an in-register int or by-value struct is good enough (or even better); there is no need to carry around that excess baggage needed for runtime polymorphism and inheritance, just so you can brag that "everything is an object" and OO-approved and certified.

 doesn't cut it
 
 OOP is nice only when kept very simple and minimal
I'd say OOP works very well -- within its own niche. There are many more things in programming than are in the little garden of OO. T -- Two wrongs don't make a right; but three rights do make a left...
Oct 27 2022
prev sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 27 October 2022 at 17:37:59 UTC, Quirin Schroll 
wrote:
 On Friday, 21 October 2022 at 15:13:44 UTC, Ola Fosheim Grøstad 
 wrote:
 On Friday, 21 October 2022 at 13:53:28 UTC, Guillaume Piolat 
 wrote:
 But building and agreeing on abstractions is what define the 
 ecosystem.
One big weakness in C++ and D is that generic definitions cannot be checked without instantiation.
There aren’t many languages that have both, templates and generics; C++/CLI and C++/CX are the only ones I know and I happen to have some experience with them. (In this nomenclature: *template* = independent copy of the implementation for every distinct instantiation, cf. C++ or D templates, especially class templates with mutable static static variables cannot depend on the argument types.) [snip]
Timon argued on the C++ pattern matching thread [1] that we need "a way to parameterize functions and aggregates that is completely erased at runtime (generally useful, not only for lifetimes; e.g., this is how to fix `inout`.)". This bears some similarity with generics. [1] https://forum.dlang.org/post/tj633h$1g4e$1 digitalmars.com
Oct 27 2022
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10/27/22 22:43, jmh530 wrote:
 On Thursday, 27 October 2022 at 17:37:59 UTC, Quirin Schroll wrote:
 On Friday, 21 October 2022 at 15:13:44 UTC, Ola Fosheim Grøstad wrote:
 On Friday, 21 October 2022 at 13:53:28 UTC, Guillaume Piolat wrote:
 But building and agreeing on abstractions is what define the ecosystem.
One big weakness in C++ and D is that generic definitions cannot be checked without instantiation.
There aren’t many languages that have both, templates and generics; C++/CLI and C++/CX are the only ones I know and I happen to have some experience with them. (In this nomenclature: *template* = independent copy of the implementation for every distinct instantiation, cf. C++ or D templates, especially class templates with mutable static variables cannot depend on the argument types.) [snip]
Timon argued on the C++ pattern matching thread [1] that we need "a way to parameterize functions and aggregates that is completely erased at runtime (generally useful, not only for lifetimes; e.g., this is how to fix `inout`.)". This bears some similarity with generics. [1] https://forum.dlang.org/post/tj633h$1g4e$1 digitalmars.com
You can use that for generics if you allow type parameters, but I am not convinced that D is currently willing to add all the type system features (type constraints etc) and backend support [2] that would need to come with that to make it convenient to use. I agree that it would be pretty useful though (and it would enable type checking for some templates too). It can actually be designed to play nice with templates in general (which `inout` and lifetimes would also require). (If you instantiate a template with something that has generic arguments in it, implicitly add generic parameters to the template instance and instantiate it with the appropriate arguments.) [2] Although interestingly, some of that is already implemented in typeinfo; the original non-templated built-in AA implementation was basically a generic type.
Oct 27 2022
prev sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Friday, 21 October 2022 at 11:54:59 UTC, Guillaume Piolat 
wrote:
 On Friday, 21 October 2022 at 10:16:10 UTC, Paulo Pinto wrote:
 affine type systems have won for low level systems coding.
Not sure it will be Rust though. In the new native language camp, Jai and Odin makes use of Scala-like "context" pointer passed to each function to pass around an allocator, a logger... being true to the monadic nature of allocation and logging. With an important difference there, Odin apparently uses a fixed context, and Jai a custom one where you can put anything. Now THAT is an interesting feature to have for embedded.
None of them have the industry backing at the same scale.
Oct 21 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 21 October 2022 at 12:41:07 UTC, Paulo Pinto wrote:
 None of them have the industry backing at the same scale.
There are two key use situations that Carbon is meant to address, according to the authors: 1. C++ interop 2. when Rust doesn't perform as well as you like I don't think Rust will take over low level programming. Rust is more of a high level language with some lower level capabilities. That is sufficient for many applications, of course, but it does not have the key characteristics that allows you to maximize the utilization of hardware.
Oct 21 2022
parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Friday, 21 October 2022 at 12:50:27 UTC, Ola Fosheim Grøstad 
wrote:
 On Friday, 21 October 2022 at 12:41:07 UTC, Paulo Pinto wrote:
 None of them have the industry backing at the same scale.
There are two key use situations that Carbon is meant to address, according to the authors: 1. C++ interop 2. when Rust doesn't perform as well as you like I don't think Rust will take over low level programming. Rust is more of a high level language with some lower level capabilities. That is sufficient for many applications, of course, but it does not have the key characteristics that allows you to maximize the utilization of hardware.
If you bothered to follow the links I posted above, you will see how the likes of ARM,Google Expressif, and Microsoft are of a different opinion, even though they seat at ISO C++. And the car industry standard for high integrity systems is now certifying Rust for the same purpose alongside C++17. But what do they know.
Oct 21 2022
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 21 October 2022 at 13:06:13 UTC, Paulo Pinto wrote:
 And the car industry standard for high integrity systems is now 
 certifying Rust for the same purpose alongside C++17.

 But what do they know.
Certification for embedded is not about maximizing the utilization of hardware. You can do embedded programming in Java too.
Oct 21 2022
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/21/2022 3:16 AM, Paulo Pinto wrote:
 Naturally I also agree that systems programming languages with GC should be 
 used, but  unless we have a big name pushing them, affine type systems have
won 
 for low level systems coding.
D's gc has turned out to be ideal for CTFE programming.
Oct 22 2022
prev sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 20 October 2022 at 14:26:07 UTC, IGotD- wrote:
 On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 [...]
Actually, Rust is even worse for embedded, OS, near hardware programming. The memory model just gets in the way of doing those things. Example of things in OS programming are often intrusive containers, pointers/references pointing in all directions and sometimes even to itself, multiple use of containers for the same object, chicken and egg problems. This is where the memory model of just Rust breaks down. Of course you have to use unsafe everywhere but as soon as you do that, things get ugly very quickly. For these tasks C++ is still the obvious choice. However, this is not normal programming and you have to do tricks that you never usually do in application programming. [...]
I have also experienced this. We tried using Rust at work for embedded but it slowed us down so much to the point we decided to just do it in C instead.
Oct 23 2022
parent reply Sergey <kornburn yandex.ru> writes:
On Sunday, 23 October 2022 at 12:19:24 UTC, Imperatorn wrote:
 On Thursday, 20 October 2022 at 14:26:07 UTC, IGotD- wrote:
 we decided to just do it in C instead.
Sad D-man in BetterC mode
Oct 23 2022
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Sunday, 23 October 2022 at 12:23:14 UTC, Sergey wrote:
 On Sunday, 23 October 2022 at 12:19:24 UTC, Imperatorn wrote:
 On Thursday, 20 October 2022 at 14:26:07 UTC, IGotD- wrote:
 we decided to just do it in C instead.
Sad D-man in BetterC mode
Yup, I'm trying to convince the rest of the team we should go with betterC. But it's hard to get ppl to try new things (except Rust for some reason)
Oct 23 2022
parent reply matheus <matheus gmail.com> writes:
On Sunday, 23 October 2022 at 12:44:15 UTC, Imperatorn wrote:
 ...
 Yup, I'm trying to convince the rest of the team we should go 
 with betterC. But it's hard to get ppl to try new things 
 (except Rust for some reason)
Maybe I'm comparing very different things, but for me this Rust trend reminds me something similar to Ruby On Rails. Some years ago most companies where I live were hiring mostly RoR developers, even the company that I work for, but now at least where I live it's very hard to find a position for RoR, in fact Matheus.
Oct 23 2022
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Sunday, 23 October 2022 at 13:38:03 UTC, matheus wrote:
 On Sunday, 23 October 2022 at 12:44:15 UTC, Imperatorn wrote:
 ...
 Yup, I'm trying to convince the rest of the team we should go 
 with betterC. But it's hard to get ppl to try new things 
 (except Rust for some reason)
Maybe I'm comparing very different things, but for me this Rust trend reminds me something similar to Ruby On Rails. Some years ago most companies where I live were hiring mostly RoR developers, even the company that I work for, but now at least where I live it's very hard to find a position for RoR, developers now. Matheus.
Yeah, that's why I don't like "hyped" languages. language (quite easy to learn), has good support (ecosystem) and IDEs. Sure it's a bit verbose, but the upsides make it worth it. D has so much potential to be a replacement for many other languages. betterC, maybe even R or Julia. What is needs though is to be stable and have an LTS branch. Companies don't really care at all what language you use, they care about economics and risk mitigation. If I say to my team "let's write the next thing in D", the first question will be about ecosystem, IDEs and other things **surrounding** the language, not the language itself, no matter how good it is, unfortunately. I really hope that one day we will have a bigger following (which will enable us to make better tools), because there are so many things D is better at than many other languages.
Oct 23 2022
parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Sunday, 23 October 2022 at 14:55:56 UTC, Imperatorn wrote:
 Yeah, that's why I don't like "hyped" languages.

 language (quite easy to learn), has good support (ecosystem) 
 and IDEs. Sure it's a bit verbose, but the upsides make it 
 worth it.
 D has so much potential to be a replacement for many other 
 languages.

 betterC, maybe even R or Julia.
 What is needs though is to be stable and have an LTS branch.
 Companies don't really care at all what language you use, they 
 care about economics and risk mitigation.
 If I say to my team "let's write the next thing in D", the 
 first question will be about ecosystem, IDEs and other things 
 surrounding the language, not the language itself, no matter 
 how good it is, unfortunately.
 I really hope that one day we will have a bigger following 
 (which will enable us to make better tools), because there are 
 so many things D is better at than many other languages.
That's not all true, TLS version is not needed Go became the cloud native language without that BS bloat driven corporates As they figured it out, Oracle started to speed up development of the language: - multiple GCs - pattern matching - var - data class - green threads - graalvm - record - pattern matching - green thread - nativeaot Go now is being held back by corporates (amazon/google/microsoft), just like rust D should be free to experiment, not every language needs to be taken hostage by corporates As you said, corporates don't care about what language they use, they'll dump it if they find something that suits their cost requirements better - simplifying the language - finishing the existing features - drastically improving ergonomics in some areas - invest massively in tooling - keep experiment with new ideas and take a look at the backlog of DIPs That's what i'd do if i knew how to make and had to work on a language Mistakes of the past need to go, otherwise people will constantly look for alternative, that alternative needs to be D+1 that fixed past mistakes, and not double down on them, because demography mean the people who rely the mistake will disappear, and the new generation of devs will choose something else
Oct 23 2022
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Sunday, 23 October 2022 at 19:39:49 UTC, ryuukk_ wrote:
 That's not all true, TLS version is not needed

 Go became the cloud native language without that BS
But Go has not changed all that much until recently, with minimal breakage.
 Go now is being held back by corporates 
 (amazon/google/microsoft), just like rust
How is Rust held back by corporations though?
 D should be free to experiment, not every language needs to be 
 taken hostage by corporates
[…]
 Mistakes of the past need to go, otherwise people will 
 constantly look for alternative, that alternative needs to be 
 D+1 that fixed past mistakes, and not double down on them, 
 because demography mean the people who rely the mistake will 
 disappear, and the new generation of devs will choose something 
 else
Yes, but since there is no willingness to take breaking changes in D there seems to be some kind of gridlock as far as language design and evolution goes. Right now there seems to be a flurry of alternatives that aim for the same use scenario as C++. Within 5-10 years some of them will gather a following or C++/Rust will evolve fast enough to keep the competing solutions at a distance. How can D position itself without a significant change in strategy, which would require a new leadership style? Can you see that happening within a timespan of 3 years?
Oct 24 2022
prev sibling parent IGotD- <nise nise.com> writes:
On Sunday, 23 October 2022 at 19:39:49 UTC, ryuukk_ wrote:
 Go now is being held back by corporates 
 (amazon/google/microsoft), just like rust

 D should be free to experiment, not every language needs to be 
 taken hostage by corporates

 As you said, corporates don't care about what language they 
 use, they'll dump it if they find something that suits their 
 cost requirements better
I'm not sure what that means. When large companies make languages they can't push too much abstract compiler technology ideas on the masses because that would hurt the adoption. When companies throw millions into new languages, that would be a waste of money if nobody can use it. One use case is Swift which in my mind is not that difficult but still some Apple developers think it is too complicated. The Apple management is keeping the language developers on a leach so that they don't get out of hand with their academics. Imagine trying to push Rust onto Apple developers, that simply wouldn't have worked and they would have rejected it.
Oct 24 2022
prev sibling next sibling parent reply surlymoor <surlymoor cock.li> writes:
On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 [...]
Thanks for the write-up. I'm not endorsing this point of view, but I think the argument made by Rust proponents (fanatics?) would be that your code is unidiomatic, and your point is thereby moot.
Oct 20 2022
parent reply Don Allen <donaldcallen gmail.com> writes:
On Thursday, 20 October 2022 at 19:51:41 UTC, surlymoor wrote:
 On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 [...]
Thanks for the write-up. I'm not endorsing this point of view, but I think the argument made by Rust proponents (fanatics?) would be that your code is unidiomatic, and your point is thereby moot.
Kool-aid does strange things to the human mind :-)
Oct 20 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/20/22 4:33 PM, Don Allen wrote:
 On Thursday, 20 October 2022 at 19:51:41 UTC, surlymoor wrote:
 On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 [...]
Thanks for the write-up. I'm not endorsing this point of view, but I think the argument made by Rust proponents (fanatics?) would be that your code is unidiomatic, and your point is thereby moot.
Kool-aid does strange things to the human mind :-)
I would caution against judgment of Rust based on a newcomer's perspective, though I think it's probably a fair assessment of the *ease of learning* of Rust. I will note that you are not using closures in your D code, but nested functions. Is there not a way to do that in Rust? Many people discount D because their attempts to make it do the things in the way they are used to result in horrible performance, or weird problems. -Steve
Oct 20 2022
parent reply Don Allen <donaldcallen gmail.com> writes:
On Thursday, 20 October 2022 at 21:28:19 UTC, Steven 
Schveighoffer wrote:
 On 10/20/22 4:33 PM, Don Allen wrote:
 On Thursday, 20 October 2022 at 19:51:41 UTC, surlymoor wrote:
 On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 [...]
Thanks for the write-up. I'm not endorsing this point of view, but I think the argument made by Rust proponents (fanatics?) would be that your code is unidiomatic, and your point is thereby moot.
Kool-aid does strange things to the human mind :-)
I would caution against judgment of Rust based on a newcomer's perspective, though I think it's probably a fair assessment of the *ease of learning* of Rust.
I've written about 10,000 lines of Rust over several years, revised many times in consultation with a couple of people in the Rust community who were particularly helpful. I've been writing code professionally and otherwise for longer than most of you, since I'm now 80 (first line of code in 1960 -- IBM 1620 assembly language). I understand Rust pretty well at this point, so I don't think the "newcomer" description applies. The language is more difficult to master than other I've used (a lot). And if you insist on never writing "unsafe", there are things that are simply impossible to do that are routine in more traditional languages. But, much like Haskell, once you satisfy the compiler, your program will be correct, modulo logic errors or doing something stupid in an "unsafe" block. You won't ever see a segfault due to de-referencing an uninitialized pointer and things of that ilk.
 I will note that you are not using closures in your D code, but 
 nested functions. Is there not a way to do that in Rust?
No. Nested functions don't see their enclosing environment in Rust.
 Many people discount D because their attempts to make it do the 
 things in the way they are used to result in horrible 
 performance, or weird problems.
I did run into that in D, mostly in the area of needing to be aware of preventing the GC from snatching strings I'd passed to C code (sqlite) (you and I shared that adventure last year). This came about in my case because I was porting C code to D, which is mostly very easy, but I missed this gotcha.
 -Steve
Oct 20 2022
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/20/22 10:46 PM, Don Allen wrote:

 I've written about 10,000 lines of Rust over several years, revised many 
 times in consultation with a couple of people in the Rust community who 
 were particularly helpful. I've been writing code professionally and 
 otherwise for longer than most of you, since I'm now 80 (first line of 
 code in 1960 -- IBM 1620 assembly language). I understand Rust pretty 
 well at this point, so I don't think the "newcomer" description applies.
OK, apologies.
 The language is more difficult to master than other I've used (a lot). 
 And if you insist on never writing "unsafe", there are things that are 
 simply impossible to do that are routine in more traditional languages.
I agree that if you have to use escapes in your safe code to write useful programs, the utility of the memory safety goes way down. This is why I'm very keen to see D safe be much easier to isolate.
 No. Nested functions don't see their enclosing environment in Rust.
Hm... closures in D typically mean an allocation. So maybe my terminology is messed up.
 Many people discount D because their attempts to make it do the things 
 in the way they are used to result in horrible performance, or weird 
 problems.
I did run into that in D, mostly in the area of needing to be aware of preventing the GC from snatching strings I'd passed to C code (sqlite) (you and I shared that adventure last year). This came about in my case because I was porting C code to D, which is mostly very easy, but I missed this gotcha.
Yes, I remember. I'm still not satisfied with the lack of ability to ensure something is stored on the stack. -Steve
Oct 21 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/21/2022 5:52 PM, Steven Schveighoffer wrote:
 Hm... closures in D typically mean an allocation. So maybe my terminology is 
 messed up.
The original closure implementation in D did not allocate, and simply errored if an allocation was necessary. Sometimes I wonder if it would have been better to not have generalized it.
Oct 21 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/20/2022 7:46 PM, Don Allen wrote:
 I've written about 10,000 lines of Rust over several years, revised many times 
 in consultation with a couple of people in the Rust community who were 
 particularly helpful. I've been writing code professionally and otherwise for 
 longer than most of you, since I'm now 80 (first line of code in 1960 -- IBM 
 1620 assembly language). I understand Rust pretty well at this point, so I
don't 
 think the "newcomer" description applies.
I'm glad you wrote this. I thought I was the oldest D programmer! I'm very pleased there are more of us using D! I hope I'm as sharp as you are when I'm 80.
Oct 21 2022
parent Don Allen <donaldcallen gmail.com> writes:
On Saturday, 22 October 2022 at 01:35:52 UTC, Walter Bright wrote:
 On 10/20/2022 7:46 PM, Don Allen wrote:
 I've written about 10,000 lines of Rust over several years, 
 revised many times in consultation with a couple of people in 
 the Rust community who were particularly helpful. I've been 
 writing code professionally and otherwise for longer than most 
 of you, since I'm now 80 (first line of code in 1960 -- IBM 
 1620 assembly language). I understand Rust pretty well at this 
 point, so I don't think the "newcomer" description applies.
I'm glad you wrote this. I thought I was the oldest D programmer! I'm very pleased there are more of us using D! I hope I'm as sharp as you are when I'm 80.
Thank you. The great comedian Red Buttons, at Sid Caesar's 80th birthday celebration: "When my father turned 80, I asked him "Pop, what does a man of 80 think about? He said '81'".
Oct 22 2022
prev sibling next sibling parent reply rassoc <rassoc posteo.de> writes:
On 20/10/2022 15:37, Don Allen via Digitalmars-d wrote:
 Rust has closures. Great. So here's an example of an attempt to do something
along the lines described above with a single mutable variable:
 
 ````
 fn main() {
      let mut foo = 5;
      let mut bar = || {
          foo = 17;
      };
      let mut baz = || {
          foo = 42;
      };
      bar();
      println!("{}", &mut foo);
      baz();
      println!("{}", &mut foo);
 
 }
 ````
To be honest, these kind of access patterns are smelly and there almost always exists a more elegant alternative. Regarding that example code above, the burrow checker will be happy if you reorder it slightly: ```rust fn main() { let mut foo = 5; let mut bar = || { foo = 17; }; bar(); println!("{}", &mut foo); // just moved this down here let mut baz = || { foo = 42; }; baz(); println!("{}", &mut foo); } ```
Oct 20 2022
next sibling parent reply Don Allen <donaldcallen gmail.com> writes:
On Thursday, 20 October 2022 at 22:41:34 UTC, rassoc wrote:
 On 20/10/2022 15:37, Don Allen via Digitalmars-d wrote:
 Rust has closures. Great. So here's an example of an attempt 
 to do something along the lines described above with a single 
 mutable variable:
 
 ````
 fn main() {
      let mut foo = 5;
      let mut bar = || {
          foo = 17;
      };
      let mut baz = || {
          foo = 42;
      };
      bar();
      println!("{}", &mut foo);
      baz();
      println!("{}", &mut foo);
 
 }
 ````
To be honest, these kind of access patterns are smelly and there almost always exists a more elegant alternative.
"smelly" and "elegant" are in the nose and eye of the beholder. As I said in my original post, this kind of code is very common in Scheme.
 Regarding that example code above, the burrow checker will be 
 happy if you reorder it slightly:

 ```rust
 fn main() {
     let mut foo = 5;
     let mut bar = || {
         foo = 17;
     };
     bar();
     println!("{}", &mut foo);
         // just moved this down here
     let mut baz = || {
         foo = 42;
     };
     baz();
     println!("{}", &mut foo);
 }
 ```
Except the re-ordering you suggest is not possible in the actual code from which this example was derived. In the real code, the mutable variables are sqlite statements where multiple closures refer to several of them and the closures are called in multiple places. You are taking advantage of this simple derived case, where each closure is called in only one place, and also the fact that mutable references are dropped after their last use, to arrange for only one mutable reference to foo active at any time, which is what the borrow checker wants. In the real code, because the closures refer to multiple mutable variables and there are multiple call sites to each closure, it isn't possible to segregate the closures and their call sites to satisfy the borrow checker, but use of interior mutability does work.
Oct 20 2022
parent reply rassoc <rassoc posteo.de> writes:
On 21/10/2022 05:36, Don Allen via Digitalmars-d wrote:
 As I said in my original post, this kind of code is very common in Scheme.
Right, I walked that path before, even shiny R7RS, and I'm glad I went to speech therapy for my lisp.
 where multiple closures refer to several of them and the closures are called
in multiple places
National Spaghetti Day is coming up on January 4th. ;) In all seriousness, though, I'm not here to invalidate your experiences with Rust. While I've been using D for quite a bit now, I get to experience some pretty uncomfortable cognitive dissonance doing so. I still love it, but D often times offers a slightly less performant and reliable way to tackle a certain set of hard problems. Even if I never get to experience Rust professionally, I'm still quite happy that it set a new baseline for safe languages to come and evolve to.
Oct 21 2022
parent reply Don Allen <donaldcallen gmail.com> writes:
On Friday, 21 October 2022 at 07:02:01 UTC, rassoc wrote:
 On 21/10/2022 05:36, Don Allen via Digitalmars-d wrote:
 As I said in my original post, this kind of code is very 
 common in Scheme.
Right, I walked that path before, even shiny R7RS, and I'm glad I went to speech therapy for my lisp.
 where multiple closures refer to several of them and the 
 closures are called in multiple places
National Spaghetti Day is coming up on January 4th. ;)
You should have gone to another therapist to correct your tendency to offer opinions about code you haven't seen.
 In all seriousness, though, I'm not here to invalidate your 
 experiences with Rust. While I've been using D for quite a bit 
 now, I get to experience some pretty uncomfortable cognitive 
 dissonance doing so. I still love it, but D often times offers 
 a slightly less performant and reliable way to tackle a certain 
 set of hard problems. Even if I never get to experience Rust 
 professionally, I'm still quite happy that it set a new 
 baseline for safe languages to come and evolve to.
Since you've said something substantive, I'll comment. I actually agree with you that Rust has shown the world that inherently memory- and thread-safe languages are possible. Haskell did some of that before Rust did, but they didn't quite finish the job. But I think there is an opportunity to create a memory-safe language with a GC that avoids many of the difficulties of Rust. And I think thread-safety should be an option, not a requirement, because there are applications that are inherently single-threaded. Those applications should not have to adhere to the rules that keep multi-threaded applications safe, as is the case in Rust, the only alternative being to sprinkle your code with "unsafe" blocks, or use thread_local!, which works, but makes the code similarly messy.
Oct 21 2022
parent reply IGotD- <nise nise.com> writes:
On Friday, 21 October 2022 at 14:04:25 UTC, Don Allen wrote:
 But I think there is an opportunity to create a memory-safe 
 language with a GC that avoids many of the difficulties of 
 Rust. And I think thread-safety should be an option, not a 
 requirement, because there are applications that are inherently 
 single-threaded. Those applications should not have to adhere 
 to the rules that keep multi-threaded applications safe, as is 
 the case in Rust, the only alternative being to sprinkle your 
 code with "unsafe" blocks, or use thread_local!, which works, 
 but makes the code similarly messy.
It already exists and it is called Swift. A few engineers from the Rust team helped engineer Swift. The syntax similarities between Swift and Rust are obvious. In Swift they added a lot of lowering in order to hide the more explicit Rust syntax. If you see the results after the lowering then the Rust syntax shines through even more. Swift added reference counting as GC (much because of objective-C) and the result is that the language is quite usable, much more easy to use than Rust. You will not end up with senseless life time compiler error as in Rust. Swift isn't safe as "nothing can go wrong" but safe enough for me. For embedded systems, Swift isn't an ideal candidate as it relies on its own foundation library, objective-C runtime and C++ standard library. Though there has been people who has successfully ported Swift to OS-less systems.
Oct 21 2022
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 21 October 2022 at 14:46:16 UTC, IGotD- wrote:
 Swift added reference counting as GC (much because of 
 objective-C) and the result is that the language is quite 
 usable, much more easy to use than Rust. You will not end up 
 with senseless life time compiler error as in Rust.
Swift is probably the best option for writing applications for Apple products, but I don't feel that it will be accepted for portable system level programming, no matter how it changes in the future. Even if it became a Rust/C++ replica it would still be perceived as being beholden to a singular entity. I can see why the Carbon docs put so much emphasis on no entity having more than 50% influence. "Backed by Google" is a selling point, but "Owned by Google" is a liability. As more languages appear I think having a more cooperative collaborative approach to design will be something people look for. Selecting a specific language is a big investment as languages get more complex (even TypeScript has grown to become rather complex). Developers don't want a single "political group" to block a design extension that matters to 20% of the users. Since languages copy features from each other they are sometimes not all that different in ordinary programming, but cultures can be very different still. So that dimension will perhaps be more and more important in the next few decades.
Oct 21 2022
prev sibling parent reply Stefan Hertenberger <SHertenberger Web.de> writes:
On Thursday, 20 October 2022 at 22:41:34 UTC, rassoc wrote:
 On 20/10/2022 15:37, Don Allen via Digitalmars-d wrote:
 Rust has closures. Great. So here's an example of an attempt 
 to do something along the lines described above with a single 
 mutable variable:
 
 ````
 fn main() {
      let mut foo = 5;
      let mut bar = || {
          foo = 17;
      };
      let mut baz = || {
          foo = 42;
      };
      bar();
      println!("{}", &mut foo);
      baz();
      println!("{}", &mut foo);
 
 }
 ````
To be honest, these kind of access patterns are smelly and there almost always exists a more elegant alternative. Regarding that example code above, the burrow checker will be happy if you reorder it slightly: ```rust fn main() { let mut foo = 5; let mut bar = || { foo = 17; }; bar(); println!("{}", &mut foo); // just moved this down here let mut baz = || { foo = 42; }; baz(); println!("{}", &mut foo); } ```
You don't need to reorder, just use references ```rust fn main() { let mut foo = 5; let bar = |val: &mut i32| { *val = 17; }; let baz = |val: &mut i32| { *val = 42; }; bar(&mut foo); println!("{}", &mut foo); baz(&mut foo); println!("{}", &mut foo); } ```
Oct 21 2022
next sibling parent Jack Applegame <japplegame gmail.com> writes:
On Friday, 21 October 2022 at 07:37:41 UTC, Stefan Hertenberger 
wrote:
 You don't need to reorder, just use references

 ```rust
 fn main() {
     let mut foo = 5;
     let bar = |val: &mut i32| {
         *val = 17;
     };
     let baz = |val: &mut i32| {
         *val = 42;
     };
     bar(&mut foo);
     println!("{}", &mut foo);
     baz(&mut foo);
     println!("{}", &mut foo);

 }
 ```
Heh. You don't need closures, just use regular functions.
Oct 21 2022
prev sibling next sibling parent reply matheus <matheus gmail.com> writes:
On Friday, 21 October 2022 at 07:37:41 UTC, Stefan Hertenberger 
wrote:
 ...
 You don't need to reorder, just use references
 ...
First of all I don't use Rust, I took a look years ago and I didn't like its syntax, so I don't know how someone could rewrite the case presented in the original post. But I think people are missing the point of Don Allen, he showed a snipped code and its simplicity, and for it seems it's not easy to do in some languages, at least without changing a lot. For example, I wrote this a while ago: "The problem that took him 5 years to fix in C++, I solved in a minute with D". https://forum.dlang.org/thread/oyfejgtjsupbdgckfdjz forum.dlang.org Matheus.
Oct 21 2022
next sibling parent reply IGotD- <nise nise.com> writes:
On Friday, 21 October 2022 at 10:19:13 UTC, matheus wrote:
 But I think people are missing the point of Don Allen, he 
 showed a snipped code and its simplicity, and for it seems it's 
 not easy to do in some languages, at least without changing a 
 lot.
I think the point is despite the example is very simple, it's required to have very detailed knowledge about the Rust compiler and its lifetime system in order to understand this problem. Sure you rewrite in some undefined "idiomatic Rust" but is it good language design when such detailed knowledge and order of statements is required? D is in the other end of this spectrum, it swallows almost anything.
Oct 21 2022
parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Friday, 21 October 2022 at 10:36:27 UTC, IGotD- wrote:
 On Friday, 21 October 2022 at 10:19:13 UTC, matheus wrote:
 But I think people are missing the point of Don Allen, he 
 showed a snipped code and its simplicity, and for it seems 
 it's not easy to do in some languages, at least without 
 changing a lot.
I think the point is despite the example is very simple, it's required to have very detailed knowledge about the Rust compiler and its lifetime system in order to understand this problem. Sure you rewrite in some undefined "idiomatic Rust" but is it good language design when such detailed knowledge and order of statements is required? D is in the other end of this spectrum, it swallows almost anything.
Yeah, but the ecosystem doesn't swallow anything, that is the problem.
Oct 21 2022
next sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Friday, 21 October 2022 at 10:42:52 UTC, Paulo Pinto wrote:
 On Friday, 21 October 2022 at 10:36:27 UTC, IGotD- wrote:
 On Friday, 21 October 2022 at 10:19:13 UTC, matheus wrote:
 [...]
I think the point is despite the example is very simple, it's required to have very detailed knowledge about the Rust compiler and its lifetime system in order to understand this problem. Sure you rewrite in some undefined "idiomatic Rust" but is it good language design when such detailed knowledge and order of statements is required? D is in the other end of this spectrum, it swallows almost anything.
Yeah, but the ecosystem doesn't swallow anything, that is the problem.
Yes, the ecosystem is the problem. Not the language
Oct 21 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 21 October 2022 at 10:42:52 UTC, Paulo Pinto wrote:
 Yeah, but the ecosystem doesn't swallow anything, that is the 
 problem.
Please stop saying it is an ecosystem issue. That is not they key thing that prevents adoption. This is just a sleeping pill that makes people go for apathy believing that they cannot change the trajectory. Which is wrong. The main issue with D is not lacking an ecosystem, D has an ecosystem that can grow and that allows you to be productive in system level programming. System level programming does not require a gigantic eco system. But D is adding new stuff to a code base that is difficult to evolve rather than focusing on design issues people complain about. The core difference is that C++ and Rust are clearly showing in their releases that they are working on compensating for design flaws that people care about. The main issue for D is a lack of strategy that involves architecting a modern D compiler, that people want to work on, and an objective strategy for selecting design issues that needs to be addressed. Without a solid strategy you can neither get rid of design issues or grow in a predictable manner. For an outsider D as a project looks more like a one-man-person-with-entourage than a cooperative effort. This does not grow confidence in the project. Rust and C++ are much less about any singular entity, but more of a collaborative effort. That is good for confidence and for long term viability and evolution. It is great for D that there is a foundation now, but has it really changed the structure of the project, and how strategies are formed, to any significant degree?
Oct 21 2022
parent reply IGotD- <nise nise.com> writes:
On Friday, 21 October 2022 at 11:51:46 UTC, Ola Fosheim Grøstad 
wrote:
 The main issue for D is a lack of strategy that involves 
 architecting a modern D compiler, that people want to work on, 
 and an objective strategy for selecting design issues that 
 needs to be addressed.

 Without a solid strategy you can neither get rid of design 
 issues or grow in a predictable manner.  For an outsider D as a 
 project looks more like a one-man-person-with-entourage than a 
 cooperative effort. This does not grow confidence in the 
 project.
Yes, that's my take on it too. The only way out of this is that D is forked. Problem with this is that language designers and people with good understanding in compiler technology are not the average programmer and are rare. If you are one of those and want to continue evolving D, then fork it rather than trying to fight this project.
Oct 21 2022
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 21 October 2022 at 13:14:41 UTC, IGotD- wrote:
 The only way out of this is that D is forked.
I don't think forking D is a going to work. I think the future of D depends on how the foundation is structured and how it operates. D needs a _strong_ and _inclusive_ organizer/leader to head the foundation. Without such a person it will be difficult to switch to a new gear. Finding such a leader would probably be the single-most important thing that could happen. (Right now I have some hope for Carbon as a C++ alternative, but it is impossible to tell what Carbon will look like at this point. Not even when it comes to basic things like integer math. Carbon might be great, or it might not be great, or it might not happen at all. We'll see in 5-10 years…)
Oct 21 2022
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/21/2022 6:14 AM, IGotD- wrote:
 Yes, that's my take on it too. The only way out of this is that D is forked.
We welcome DIP proposals from anyone, and once approved, anyone can implement them.
Oct 22 2022
prev sibling parent Bruce Carneal <bcarneal gmail.com> writes:
On Friday, 21 October 2022 at 13:14:41 UTC, IGotD- wrote:
 On Friday, 21 October 2022 at 11:51:46 UTC, Ola Fosheim Grøstad 
 wrote:
 The main issue for D is a lack of strategy that involves 
 architecting a modern D compiler, that people want to work on, 
 and an objective strategy for selecting design issues that 
 needs to be addressed.
 ...
Yes, that's my take on it too. The only way out of this is that D is forked.
... For those with time and a fork-it bent I'd suggest contributing to SDC as an alternative, or prelude, to a complete fork.
Oct 22 2022
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/21/2022 3:19 AM, matheus wrote:
 For example, I wrote this a while ago: "The problem that took him 5 years to
fix 
 in C++, I solved in a minute with D".
 
 https://forum.dlang.org/thread/oyfejgtjsupbdgckfdjz forum.dlang.org
I repeat my request to make it a HackerNews or Reddit article!
Oct 21 2022
prev sibling parent reply Don Allen <donaldcallen gmail.com> writes:
On Friday, 21 October 2022 at 07:37:41 UTC, Stefan Hertenberger 
wrote:
 On Thursday, 20 October 2022 at 22:41:34 UTC, rassoc wrote:
 On 20/10/2022 15:37, Don Allen via Digitalmars-d wrote:
 [...]
To be honest, these kind of access patterns are smelly and there almost always exists a more elegant alternative. Regarding that example code above, the burrow checker will be happy if you reorder it slightly: ```rust fn main() { let mut foo = 5; let mut bar = || { foo = 17; }; bar(); println!("{}", &mut foo); // just moved this down here let mut baz = || { foo = 42; }; baz(); println!("{}", &mut foo); } ```
You don't need to reorder, just use references ```rust fn main() { let mut foo = 5; let bar = |val: &mut i32| { *val = 17; }; let baz = |val: &mut i32| { *val = 42; }; bar(&mut foo); println!("{}", &mut foo); baz(&mut foo); println!("{}", &mut foo); } ```
Which is contrary to the purpose of using closures -- to capture free variables in the lexical environment, rather than having to pass them as arguments. What you have done above could (and should) be re-written with ordinary functions.
Oct 21 2022
next sibling parent Stefan Hertenberger <SHertenberger Web.de> writes:
On Friday, 21 October 2022 at 13:44:56 UTC, Don Allen wrote:
 Which is contrary to the purpose of using closures -- to 
 capture free variables in the lexical environment, rather than 
 having to pass them as arguments. What you have done above 
 could (and should) be re-written with ordinary functions.
You are right, not sure what i had in mind while writing this :(
Oct 21 2022
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/21/2022 6:44 AM, Don Allen wrote:
 Which is contrary to the purpose of using closures -- to capture free
variables 
 in the lexical environment, rather than having to pass them as arguments. What 
 you have done above could (and should) be re-written with ordinary functions.
The way dip1000 works with closures is to treat the uplevel variables as if they are passed by ref to the nested function. Which is of course how they are implemented.
Oct 21 2022
prev sibling next sibling parent reply victoroak <jackpboy gmail.com> writes:
On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 ````
 fn main() {
     let mut foo = 5;
     let mut bar = || {
         foo = 17;
     };
     let mut baz = || {
         foo = 42;
     };
     bar();
     println!("{}", &mut foo);
     baz();
     println!("{}", &mut foo);

 }
 ````
I think the way it would be advised to write it in Rust would be something like this instead of using RefCell: ``` fn main() { struct State { foo: i32 } impl State { fn bar(&mut self) { self.foo = 17; } fn baz(&mut self) { self.foo = 42; } } let mut state = State { foo: 0 }; state.bar(); println!("{}", state.foo); state.baz(); println!("{}", state.foo); } ``` The problem is that both closures have a mutable reference to the same value and this is not allowed in Rust, you could solve this making the functions get a mutable reference to the variable but using a struct in this case is better IMO.
Oct 21 2022
parent reply Don Allen <donaldcallen gmail.com> writes:
On Saturday, 22 October 2022 at 05:35:22 UTC, victoroak wrote:
 On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 ````
 fn main() {
     let mut foo = 5;
     let mut bar = || {
         foo = 17;
     };
     let mut baz = || {
         foo = 42;
     };
     bar();
     println!("{}", &mut foo);
     baz();
     println!("{}", &mut foo);

 }
 ````
I think the way it would be advised to write it in Rust would be something like this instead of using RefCell: ``` fn main() { struct State { foo: i32 } impl State { fn bar(&mut self) { self.foo = 17; } fn baz(&mut self) { self.foo = 42; } } let mut state = State { foo: 0 }; state.bar(); println!("{}", state.foo); state.baz(); println!("{}", state.foo); } ``` The problem is that both closures have a mutable reference to the same value and this is not allowed in Rust, you could solve this making the functions get a mutable reference to the variable but using a struct in this case is better IMO.
I think it's clear that my Scheme-ish attempt to use Rust closures was not a good idea. The fundamental problem with using Rust closures in this way is that the borrow-checker thinks any mutable borrows that occur in the closure happen at the time the closure is defined, not when it is called. This is one of those situations where trying to insure safety at compile time can be too conservative, which the Rust folks concede. Interior mutability and reference counting are both run-time ways to get around the compiler when it prevents you from doing things that are actually safe but can't be proven safe at compile time. I never actually fixed the code from which my example is drawn, which I wrote quite awhile ago, because at that point I'd reached my personal Rust-pain threshold and moved on to D, returning my blood pressure to normal. But if I were going to fix it, I agree with you that your (very nice) solution is preferable. Avoiding closures and instead using functions/methods results in the mutable borrows occurring at call time, which solves the problem, since my call pattern doesn't violate the "one mutable borrow at a time" rule. I'm sure Refcell would also work, as it did with my little example, but it's messier and introduces a bit of runtime overhead (which I doubt would matter in the application in question running on 4 GHz hardware, so I think the readability issue is primary). I'd also add that in effect, what you are doing is manually creating closures by using a struct and struct methods (behind the scenes, Rust closures are built by the compiler with structs in much the same way). But by doing it manually, you get finer grained control over how and when the mutable borrows occur, so they happen in a smarter way than what the compiler is doing.
Oct 22 2022
parent Stefan Hertenberger <SHertenberger Web.de> writes:
I guess, it really depends on what happens in bar and baz but my 
solution would be  something like this.

```rust
fn main() {

     let mut foo = 5;
     let bar = || -> i32 {
         // do something here
         17
     };
     let baz = || -> i32 {
         // do something here
         42
     };
     foo = bar();
     println!("{}", foo);
     foo = baz();
     println!("{}", foo);

}
```
As always one uses the best fitting tool to solve the problem and 
in your case it was D ?!
Oct 23 2022
prev sibling parent reply Dukc <ajieskola gmail.com> writes:
On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 ````
 use std::cell::RefCell;

 fn main() {
     let foo = RefCell::new(5);
     let bar = || {
         *foo.borrow_mut() = 17;
     };
     let baz = || {
         *foo.borrow_mut() = 42;
     };
     bar();
     println!("{}", foo.borrow());
     baz();
     println!("{}", foo.borrow());
     }
 ````
Yes, I believe this shows maybe the biggest weakaness of Rust. I could live with a language having a syntax like that (still better than C++, at least the old standards), but it does slows down working compared to most other new-generation languages. Too bad. Rust's error handling seems so advanced. I'm not talking only about the ability to be safe without a stop-the-world GC, but about it's ability to detect other errors too. A good example is it's UTF-8 string type. Not only it is guaranteed to point to valid memory, it is statically guaranteed to point to valid UTF-8! A D programmer needs to rely on contract programming instead. Although I think that placing a few asserts is still be a good idea even in Rust. Disclaimer: the above is likely to be humbug because I have no usage experience of Rust, only studied it's docs.
Oct 24 2022
next sibling parent reply Don Allen <donaldcallen gmail.com> writes:
On Monday, 24 October 2022 at 20:04:00 UTC, Dukc wrote:
 On Thursday, 20 October 2022 at 13:37:07 UTC, Don Allen wrote:
 ````
 use std::cell::RefCell;

 fn main() {
     let foo = RefCell::new(5);
     let bar = || {
         *foo.borrow_mut() = 17;
     };
     let baz = || {
         *foo.borrow_mut() = 42;
     };
     bar();
     println!("{}", foo.borrow());
     baz();
     println!("{}", foo.borrow());
     }
 ````
Yes, I believe this shows maybe the biggest weakness of Rust.
I'd disagree about "biggest". My use of closures would get me a summons from the Rust Unidiomatic Police. In other words, my guess is that not many run across the problem I did. A more serious weakness, in my opinion, is the difficulty of dealing with global state. Statics must be initialized, but the initializer must be known at compile-time. So if you want to define a global that you need to initialize with a value only known at run-time and will never change again, you must define it as mutable, with all the issues that raises. And its type will need to be Option<the type you really want> and the compile-time-known initializer will have to be None. You then mutate it to be Some(what-you-want) at run-time. References to this will have to be in an "unsafe" block, even though the situation would be perfectly safe if immutable statics could be initialized at runtime (I think they may be trying to fix this with something available only in the nightly version, but I am not positive). Then there's the problem I've mentioned earlier -- Rust considers everything to be multi-threaded, even if it isn't. And it imposes restrictions on the programmer that are only needed in multi-threaded situations, such as considering mutable statics to be unsafe. Even if the mutable static is wrapped in a mutex, you still need to use unsafe blocks to refer to it.
 I could live with a language having a syntax like that (still 
 better than C++, at least the old standards), but it does slows 
 down working compared to most other new-generation languages.

 Too bad. Rust's error handling seems so advanced. I'm not 
 talking only about the ability to be safe without a 
 stop-the-world GC,
Not all GCs are stop-the-world. And, in my opinion, the negativity about garbage collectors is exaggerated. There's an awful lot of software out there written in gc-ed languages, e.g., Python, Go, Javascript, that we all use every day, even on our phones, and that performs adequately or more than adequately.
 but about it's ability to detect other errors too. A good 
 example is it's UTF-8 string type. Not only it is guaranteed to 
 point to valid memory, it is statically guaranteed to point to 
 valid UTF-8! A D programmer needs to rely on contract 
 programming instead. Although I think that placing a few 
 asserts is still be a good idea even in Rust.
Yes, there are a lot of positive things to say about Rust. But for me, the insistence on no GC disqualifies it from use in situations where a GC-ed language would do the job, because of the cost in programming difficulty that that insistence imposes, e.g., lifetime hell and frustrating battles with the borrow-checker. And that difficulty is compounded by the multi-threaded assumption and the handling of statics.
 Disclaimer: the above is likely to be humbug because I have no 
 usage experience of Rust, only studied it's docs.
Oct 25 2022
next sibling parent reply Tejas <notrealemail gmail.com> writes:
On Tuesday, 25 October 2022 at 17:16:58 UTC, Don Allen wrote:
 There's an awful lot of software out there written in gc-ed 
 languages, e.g., Python, Go, Javascript, that we all use every 
 day, even on our phones, and that performs adequately or more 
 than adequately
But Rust is a system level programming language, it was designed for writing device drivers, filesystems, and other resource constrained and latency critical software, where languages with runtime environments can't be used, even if you're okay with them Even the actual software libraries used by higher level languages in mobile applications are wrappers over the extremely power/compute efficient C/C++ libraries that were written with misery and paranoia, it's not as if a higher level languages' tech stack doesn't involve lower level language, but the opposite is true Thus, Rust always assumes the worst case scenarios and makes the programmer distort their code to make it compile, and, unless you use lots of unsafe, the code really belongs to "if it compiles, it doesn't have memory bugs" camp of software
Oct 25 2022
parent reply Don Allen <donaldcallen gmail.com> writes:
On Tuesday, 25 October 2022 at 17:37:22 UTC, Tejas wrote:
 On Tuesday, 25 October 2022 at 17:16:58 UTC, Don Allen wrote:
 There's an awful lot of software out there written in gc-ed 
 languages, e.g., Python, Go, Javascript, that we all use every 
 day, even on our phones, and that performs adequately or more 
 than adequately
But Rust is a system level programming language, it was designed for writing device drivers, filesystems, and other resource constrained and latency critical software, where languages with runtime environments can't be used, even if you're okay with them
That's true and is essentially what I'm saying -- Rust is fine for what it was designed for, but it is not suitable for ordinary application development. But this is ignored by many in the Rust community and even by Mozilla, which, for example, is using Rust in Firefox.
 Even the actual software libraries used by higher level 
 languages in mobile applications are wrappers over the 
 extremely power/compute efficient C/C++ libraries that were 
 written with misery and paranoia, it's not as if a higher level 
 languages' tech stack doesn't involve lower level language, but 
 the opposite is true
Except I'm talking about the pain inflicted on the *user* of the language, not the pain it took to create the language and its supporting libraries.
 Thus, Rust always assumes the worst case scenarios and makes 
 the programmer distort their code to make it compile, and, 
 unless you use lots of unsafe, the code really belongs to "if 
 it compiles, it doesn't have memory bugs" camp of software
There are plenty of examples of gc-ed languages that do the same without Rust's difficulty.
Oct 25 2022
parent reply Sergey <kornburn yandex.ru> writes:
On Tuesday, 25 October 2022 at 18:11:28 UTC, Don Allen wrote:
 On Tuesday, 25 October 2022 at 17:37:22 UTC, Tejas wrote:
That's true and is essentially what I'm saying -- Rust is fine 
for what it was >designed for, but it is not suitable for 
ordinary application development. But this >is ignored by many 
in the Rust community and even by Mozilla, which, for example, 
is using Rust in Firefox
But the browser not really "ordinary" application. And all users will be happy if it will be as fast as possible and consume not too much memory. Actually users will be happy if every app will have those parameters. Instead of that we have Intellij IDEA and Electron apps which are very far from being *blazingly fast*.
Oct 25 2022
parent reply Don Allen <donaldcallen gmail.com> writes:
On Tuesday, 25 October 2022 at 21:38:44 UTC, Sergey wrote:
 On Tuesday, 25 October 2022 at 18:11:28 UTC, Don Allen wrote:
 On Tuesday, 25 October 2022 at 17:37:22 UTC, Tejas wrote:
That's true and is essentially what I'm saying -- Rust is fine 
for what it was >designed for, but it is not suitable for 
ordinary application development. But this >is ignored by many 
in the Rust community and even by Mozilla, which, for example,
is using Rust in Firefox
But the browser not really "ordinary" application. And all users will be happy if it will be as fast as possible and consume not too much memory.
If you think that the user experience would be any different if Mozilla used Go or D for the work they are doing with Firefox, then you and I just need to agree to disagree. I can re-cite my own recent experience, stated here more than once: I wrote a suite of personal financial management applications in C 10 years ago. It got ugly and hard to maintain, so I re-wrote much of it in Rust. When I tired of dealing with Rust's challenges, I turned to D. The performance of the C, Rust and D versions of the most processor-intensive application are within a few percent of each other, indistinguishable in actual use.
 Actually users will be happy if every app will have those 
 parameters. Instead of that we have Intellij IDEA and Electron 
 apps which are very far from being *blazingly fast*.
Electron is at least partly implemented in C++. I've tried the Atom editor, which is based on Electron, and it *is* annoyingly slow. Do you think not using Rust is their problem? Or maybe they got some algorithms wrong, or used badly implemented bloatware, or .... (a long list of how applications can be made to perform badly regardless of programming language).
Oct 26 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 26 October 2022 at 14:59:02 UTC, Don Allen wrote:
 If you think that the user experience would be any different if 
 Mozilla used Go or D for the work they are doing with Firefox, 
 then you and I just need to agree to disagree.
Browsers are generally written in C++? They use a dedicate GC for dealing with javascript objects. The renderer for Chrome called Skia is written in C++ and is gradually moving rendering to the graphics co-processor. You cannot easily do these things with a run-of-the-mill GC as in Go, and not at all with a freeze-the-world GC. Browsers do a lot of work in the background. A browser is basically one gigantic runtime for javascript. You don't want to deal with another heavy runtime at the same time. That would make performance tuning very difficult. That said, I don't know how much Firefox relies on Rust. Wikipedia says that Mozilla dropped Servo (the engine that was being implemented in Rust).
 dealing with Rust's challenges, I turned to D. The performance 
 of the C, Rust and D versions of the most processor-intensive 
 application are within a few percent of each other, 
 indistinguishable in actual use.
You probably didn't generate much garbage. And frankly, you can easily write a well-performing basic financial application in Python without paying any attention to algorithms or memory. So I don't think this is a good use case for comparison.
 Electron is at least partly implemented in C++. I've tried the 
 Atom editor, which is based on Electron, and it *is* annoyingly 
 slow.
Electron is just a stripped down browser with some additonal APIs. Electron applications are written in Javascript. It is possible to make javascript applications perform well, but you need to design the software carefully and do some performance tuning.
Oct 26 2022
parent reply Don Allen <donaldcallen gmail.com> writes:
On Wednesday, 26 October 2022 at 15:48:02 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 26 October 2022 at 14:59:02 UTC, Don Allen wrote:
 If you think that the user experience would be any different 
 if Mozilla used Go or D for the work they are doing with 
 Firefox, then you and I just need to agree to disagree.
Browsers are generally written in C++? They use a dedicate GC for dealing with javascript objects. The renderer for Chrome called Skia is written in C++ and is gradually moving rendering to the graphics co-processor. You cannot easily do these things with a run-of-the-mill GC as in Go, and not at all with a freeze-the-world GC.
Opinion stated as fact. And how do you know that a freeze-the-world GC, if that were used, would be a browser's performance bottleneck, with all the network-imposed delays users experience when browsing? I speak from decades of performance-analysis experience where I found that programmers are horrible at guessing why their programs perform as they do. Which leads to the rule "Do the measurements, then we'll talk". And how, pray tell, would the use of Go or D prevent "moving rendering to the graphics co-processor"? Which, of course, takes performance pressure off the code on running the main processor.
 Browsers do a lot of work in the background. A browser is 
 basically one gigantic runtime for javascript. You don't want 
 to deal with another heavy runtime at the same time. That would 
 make performance tuning very difficult.

 That said, I don't know how much Firefox relies on Rust. 
 Wikipedia says that Mozilla dropped Servo (the engine that was 
 being implemented in Rust).

 dealing with Rust's challenges, I turned to D. The performance 
 of the C, Rust and D versions of the most processor-intensive 
 application are within a few percent of each other, 
 indistinguishable in actual use.
You probably didn't generate much garbage. And frankly, you can easily write a well-performing basic financial application in Python without paying any attention to algorithms or memory. So I don't think this is a good use case for comparison.
Interesting conclusion, based on zero knowledge of what my application does.
Oct 26 2022
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 26 October 2022 at 17:06:33 UTC, Don Allen wrote:
 And how do you know that a freeze-the-world GC, if that were 
 used, would be a browser's performance bottleneck, with all the 
 network-imposed delays users experience when browsing?
This is a useless argument. Browsers support realtime applications.
Oct 26 2022
next sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Wednesday, 26 October 2022 at 17:48:19 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 26 October 2022 at 17:06:33 UTC, Don Allen wrote:
 And how do you know that a freeze-the-world GC, if that were 
 used, would be a browser's performance bottleneck, with all 
 the network-imposed delays users experience when browsing?
This is a useless argument. Browsers support realtime applications.
There is nothing more real time that weapons targeting and guiding systems, where a couple of ms means the wrong guys die, what is a frame dropped in a browser compared with a big hole where it wasn't supposed to be one. US and France have several of those systems powered by bare metal Java with real time GC.
Oct 26 2022
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 26 October 2022 at 18:33:24 UTC, Paulo Pinto wrote:
 There is nothing more real time that weapons targeting and 
 guiding systems, where a couple of ms means the wrong guys die, 
 what is a frame dropped in a browser compared with a big hole 
 where it wasn't supposed to be one.
Apples and oranges. Browser applications generate a lot of garbage, there are many things going on in the background as browsers are high level development environments. There is no way you can use a freeze-the-world GC as the primary collection mechanism and be competitive. And most likely not using Go's GC either. Not to mention that the memory consumption nearly doubles when you start to rely on the GC. If writing a heavy "realtime" runtime using a run-of-the-mill GC was competitive, then people would do it to save money.
Oct 26 2022
prev sibling parent reply Don Allen <donaldcallen gmail.com> writes:
On Wednesday, 26 October 2022 at 17:48:19 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 26 October 2022 at 17:06:33 UTC, Don Allen wrote:
 And how do you know that a freeze-the-world GC, if that were 
 used, would be a browser's performance bottleneck, with all 
 the network-imposed delays users experience when browsing?
This is a useless argument. Browsers support realtime applications.
And are you aware that when and if there is a real-time requirement, you can turn off the GC? And speaking of useless, I'm done discussing this with you.
Oct 26 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Wednesday, 26 October 2022 at 21:17:01 UTC, Don Allen wrote:
 And are you aware that when and if there is a real-time 
 requirement, you can turn off the GC?
Turning off the GC is not an option that will work out as there is no period of time that isn't "realtime", but you can keep GC managed objects on a separate thread. That approach only makes sense if you can separate out and shield significant work suitable for GC from the other work that has to be done. For the most part using owning pointers and arenas is a more flexible approach if you cannot use a generic GC for most of your program. Browsers do use a GC for resources that are "owned" by javascript, but the browser code then have full control over the collection strategy. That is not the case for a generic run-of-the- mill language solution. The moment you have to micromanage a large number of objects by pinning and unpinning them because they are leaving the GC context you might find that the benefits of using a managed solution is lost. So the overall complexity goes down with choosing something more homogeneous (like owning pointers).
Oct 26 2022
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Wednesday, 26 October 2022 at 22:09:46 UTC, Ola Fosheim 
Grøstad wrote:
 On Wednesday, 26 October 2022 at 21:17:01 UTC, Don Allen wrote:
 [...]
Turning off the GC is not an option that will work out as there is no period of time that isn't "realtime", but you can keep GC managed objects on a separate thread. That approach only makes sense if you can separate out and shield significant work suitable for GC from the other work that has to be done. [...]
I don't understand your argument. Why wouldn't it be possible to make a browser with a GC? You mean there are no browsers made in SML, OCaml, Eiffel, D, Go,
Oct 27 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 27 October 2022 at 18:32:15 UTC, Imperatorn wrote:
 I don't understand your argument.
 Why wouldn't it be possible to make a browser with a GC?
Modern browsers such as Firefox and Chrome are nothing like NSCA Mosaic or gopher. They are runtimes for application development/games. You cannot make a competitive runtime if your foundation is a source for non-deterministic effects and unnecessary resource consumption. It is possible, but not workable.
Oct 27 2022
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/27/22 11:50, Ola Fosheim Grøstad wrote:

 Modern browsers such as Firefox and Chrome are nothing like NSCA Mosaic
 or gopher.
Ok.
 They are runtimes for application development/games.
Ok.
 You
 cannot make a competitive runtime if your foundation is a source for
 non-deterministic effects and unnecessary resource consumption.
Your argument seems to be based on finding a narrow case where your point is true and then concluding that some other related thing is false. Here, just because we can imagine a case where "non-deterministic effects and unnecessary resource consumption" can be harmful, D is not usable. That kind of argumentation was used before: - "There are corner cases where ranges are inferior to iterators, so ranges must be bad." This logic is proven to be wrong because we know from experience that ranges are very useful. - "There are corner cases where 'static if' does not make sense, so 'static if' is bad." This conclusion is proven to be wrong because we have tons of experience that 'static if' is very useful. (Some "considerate" C++ "experts" failed on this one.) Now, to break your logic, I present Weka.IO, world's fastest file system, written in D. Period. Having that example in front of me, I bet even I can write a browser that would be considered "modern".
 It is possible, but not workable.
As I've shown above, it is possible and workable. Ali
Oct 27 2022
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 27 October 2022 at 20:54:32 UTC, Ali Çehreli wrote:
 Your argument seems to be based on finding a narrow case where 
 your point is true and then concluding that some other related 
 thing is false. Here, just because we can imagine a case where 
 "non-deterministic effects and unnecessary resource 
 consumption" can be harmful, D is not usable.
No. The argument was whether it makes sense to use Rust for building the core engine of Firefox or not. The position I argued against was that you could just as well do it with a standard freeze-the-world GC or Go with full GC. The argument isn't strictly related to D, that is something you brought to the table. 99% of all languages use some kind of GC, most of the programs written are done using some kind of GC. Having automatic memory management is the norm, not the outlier. That does not mean that non-GC applications can be replaced with a run-of-the-mill GC solution and be competitive. It makes sense to use languages like Rust for even mundane things like cloud web services where you want to conserve memory. I am not a Rust user at this point, but I also don't assume that people who use it don't understand the tradeoffs.
 Now, to break your logic, I present Weka.IO, world's fastest 
 file system, written in D. Period.
Do they use the regular D GC all the way?
 As I've shown above, it is possible and workable.
I have absolutely no idea what you are referring to here.
Oct 27 2022
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/27/22 15:11, Ola Fosheim Grøstad wrote:

 No. The argument was whether it makes sense to use Rust for building the
 core engine of Firefox or not.
No. Your argument was about GC not being usable for such applications.
 The position I argued against was that
 you could just as well do it with a standard freeze-the-world GC or Go
 with full GC. The argument isn't strictly related to D, that is
 something you brought to the table.
I did not bring D to the table. This thread is titled "A D vs. Rust example" where people are trying to convince the OP that their real-world experience is false because browsers support realtime applications as well.
 99% of all languages use some kind of GC, most of the programs written
 are done using some kind of GC. Having automatic memory management is
 the norm, not the outlier.
Everybody knows that.
 That does not mean that non-GC applications can be replaced with a
 run-of-the-mill GC solution and be competitive.
Everybody would agree with that. How does that point make any sense in this discussion though? Who was arguing doing any of that? If you are referring to the claim that some percentage of languages (including D) cannot be used to write a browser, that is simply false. Because my claim is different: Many programming languages (including D) can be written to write a browser. There...
 It makes sense to use
 languages like Rust for even mundane things like cloud web services
 where you want to conserve memory.
What are you saying? Who would ever not want to conserve memory?
 I am not a Rust user at this point, but I also don't assume that people
 who use it don't understand the tradeoffs.
Some people do understand the tradeoffs but many others just follow the tide.
 Now, to break your logic, I present Weka.IO, world's fastest file
 system, written in D. Period.
Do they use the regular D GC all the way?
None whatsoever.
 As I've shown above, it is possible and workable.
I have absolutely no idea what you are referring to here.
I was quoting you. You said "It is possible, but not workable." But now I see: You were using the niche application of "realtime applications in the browser" to prove that a run-of-the-mill GC cannot be used for it. Fine with me as long as you don't argue that a run-of-the-mill GC (e.g. the one in D) cannot be used to write a browser. Ali
Oct 28 2022
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 28 October 2022 at 16:03:07 UTC, Ali Çehreli wrote:
 On 10/27/22 15:11, Ola Fosheim Grøstad wrote:

 No. The argument was whether it makes sense to use Rust for
building the
 core engine of Firefox or not.
No. Your argument was about GC not being usable for such applications.
Which is the same thing. This was the context, Don implied that Mozilla could have used the builtin GC: «If you think that the user experience would be any different if Mozilla used Go or D for the work they are doing with Firefox, then you and I just need to agree to disagree.» They can't without affecting performance and resource usage. It is not competitive. It is possible, but not workable.
 Do they use the regular D GC all the way?
None whatsoever.
Hence the file system example had nothing to do with argument about using the standard GC. Everybody here knows that you can use D as a C/C++ replacement with no GC. But if you remove the GC then there is no point to the argument as then you don't have a significantly lower cost than you get by using Rust.
 As I've shown above, it is possible and workable.
I have absolutely no idea what you are referring to here.
I was quoting you. You said "It is possible, but not workable."
It is possible with the GC, but not workable, i.e. Firefox would not be competitive against Chrome.
 Fine with me as long as you don't argue that a run-of-the-mill 
 GC (e.g. the one in D) cannot be used to write a browser.
It is possible, but not workable… That's just reality. You have to do better than the most used browser for there to be any point to even start on such a venture.
Oct 28 2022
prev sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Wed, Oct 26, 2022 at 05:06:33PM +0000, Don Allen via Digitalmars-d wrote:
[...]
 I speak from decades of performance-analysis experience where I found
 that programmers are horrible at guessing why their programs perform
 as they do. Which leads to the rule "Do the measurements, then we'll
 talk".
[...] +1, speaking as one who writes C every day and who used to write a ton of C++, I can say that most C/C++ programmers are lousy at guessing where the performance bottlenecks actually are. Most of them (including myself) get it wrong 99% of the time, and are liable to optimize prematurely in places that are nowhere near the real bottleneck. These days, whenever people try to tell me X or Y is "inefficient", I just ignore them until they can show me actual measurements. Preferably profiler output that pinpoints where exactly in the code the program is spending most of its time in. T -- People tell me I'm stubborn, but I refuse to accept it!
Oct 26 2022
prev sibling next sibling parent reply Siarhei Siamashka <siarhei.siamashka gmail.com> writes:
On Tuesday, 25 October 2022 at 17:16:58 UTC, Don Allen wrote:
 Yes, there are a lot of positive things to say about Rust. But 
 for me, the insistence on no GC disqualifies it from use in 
 situations where a GC-ed language would do the job, because of 
 the cost in programming difficulty that that insistence 
 imposes, e.g., lifetime hell and frustrating battles with the 
 borrow-checker. And that difficulty is compounded by the 
 multi-threaded assumption and the handling of statics.
When developing C++ code, I was solving this problem by just embedding a Lua interpreter (and also a much less known http://squirrel-lang.org/ because its syntax resembles C). This approach provides GC and easy programming for the parts of a program, which are not performance critical. Seems like Rust also can do this just fine: https://docs.rs/rlua/latest/rlua/
Oct 25 2022
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Tuesday, 25 October 2022 at 17:42:42 UTC, Siarhei Siamashka 
wrote:
 On Tuesday, 25 October 2022 at 17:16:58 UTC, Don Allen wrote:
 [...]
When developing C++ code, I was solving this problem by just embedding a Lua interpreter (and also a much less known http://squirrel-lang.org/ because its syntax resembles C). This approach provides GC and easy programming for the parts of a program, which are not performance critical. Seems like Rust also can do this just fine: https://docs.rs/rlua/latest/rlua/
Hey buddy, someone else on the internet that has used Squirrel. I thought I was alone :D I wish I could have used D instead tho
Oct 25 2022
parent Siarhei Siamashka <siarhei.siamashka gmail.com> writes:
On Tuesday, 25 October 2022 at 17:47:00 UTC, Imperatorn wrote:
 On Tuesday, 25 October 2022 at 17:42:42 UTC, Siarhei Siamashka 
 wrote:
 On Tuesday, 25 October 2022 at 17:16:58 UTC, Don Allen wrote:
 [...]
When developing C++ code, I was solving this problem by just embedding a Lua interpreter (and also a much less known http://squirrel-lang.org/ because its syntax resembles C). This approach provides GC and easy programming for the parts of a program, which are not performance critical. Seems like Rust also can do this just fine: https://docs.rs/rlua/latest/rlua/
Hey buddy, someone else on the internet that has used Squirrel. I thought I was alone :D
Well, it was not too hard to find Squirrel once you decide that you want "something like Lua, but with C syntax" and go to the google search with this request :-) Lua is great, but I wasn't completely happy about 1-based indexing and wanted to try something new. And nowadays I see that there's also mruby competing in the same niche, so there's no shortage of available solutions.
 I wish I could have used D instead tho
Ironically, D was also considered for this particular project, but got rejected because it was seen as a long term maintenance hazard. Thankfully my more experienced colleagues explained me what's wrong with D language and many years later I see that they were absolutely right on every account. Lua or Squirrel interpreter is small and simple enough and can be just included as a part of the C++ project source tree. Even if the upstream developers release new incompatible versions in the future, nobody can force us to upgrade. Being small and simple, the interpreter code is also perfectly maintainable and customizable without depending on any third party. You know that you are in full control and this feels great.
Oct 29 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/25/2022 10:16 AM, Don Allen wrote:
 Not all GCs are stop-the-world. And, in my opinion, the negativity about
garbage 
 collectors is exaggerated. There's an awful lot of software out there written
in 
 gc-ed languages, e.g., Python, Go, Javascript, that we all use every day, even 
 on our phones, and that performs adequately or more than adequately.
The fact that D's GC is what enables advanced CTFE programming is often overlooked. It's a killer feature enabling a killer feature. After all, whatcha gonna do with malloc/free in CTFE?
Oct 27 2022
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 28/10/2022 12:40 PM, Walter Bright wrote:
 After all, whatcha gonna do with malloc/free in CTFE?
Allocate and free memory? CTFE is just an application VM, even if we have limitations, they are not inherent to the theory ;)
Oct 27 2022
parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/27/2022 4:51 PM, rikki cattermole wrote:
 On 28/10/2022 12:40 PM, Walter Bright wrote:
 After all, whatcha gonna do with malloc/free in CTFE?
Allocate and free memory?
I meant this at a more meta level - people write their own allocators a lot.
 CTFE is just an application VM, even if we have limitations, they are not 
 inherent to the theory ;)
Yes, it is technically possible. But there's no actual purpose to malloc/free in CTFE. The GC works just fine, and it's memory safe, and it's much more convenient.
Oct 27 2022
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 27 October 2022 at 23:40:11 UTC, Walter Bright wrote:
 The fact that D's GC is what enables advanced CTFE programming 
 is often overlooked. It's a killer feature enabling a killer 
 feature.
It is clearly better to use high level code in CTFE than system-like code. Maybe you could consider adding more high level features such a comprehensions and generators for the purpose of improved CTFE?
Oct 28 2022
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/28/22 00:25, Ola Fosheim Grøstad wrote:
 On Thursday, 27 October 2022 at 23:40:11 UTC, Walter Bright wrote:
 The fact that D's GC is what enables advanced CTFE programming is
 often overlooked. It's a killer feature enabling a killer feature.
It is clearly better to use high level code in CTFE than system-like code.
Yes, high level code is always better.
 Maybe you could consider adding more high level features such a
 comprehensions and generators for the purpose of improved CTFE?
I want to ask comprehensions and generators as seen in the context of Python but you could not have meant it because Python does not have CTFE. D uses range algorithms for comprehensions and generators. For example, the following program instantiates a struct template with a value computed from a generator: struct S(size_t N) { float[N] arr; } void main() { import std.algorithm : map, sum; import std.range : iota; auto s = S!(iota(10).sum)(); // <-- Generator used in CTFE pragma(msg, s.arr.length); } Ali
Oct 28 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/24/2022 1:04 PM, Dukc wrote:
 it's UTF-8 string type. Not only it is 
 guaranteed to point to valid memory, it is statically guaranteed to point to 
 valid UTF-8!
The trouble with that is much of the UTF-8 out there is not valid. You don't want, for example, your html page to refuse to display at all because there's a couple invalid UTF-8 sequences in it. You don't want your text editor to refuse to load a file with invalid UTF-8 in it, either. You don't want your forms processor to summarily reject anything with invalid UTF-8 in it. A better approach is to have the string processing be tolerant of invalid UTF-8.
Oct 27 2022
parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Thu, Oct 27, 2022 at 04:37:12PM -0700, Walter Bright via Digitalmars-d wrote:
 On 10/24/2022 1:04 PM, Dukc wrote:
 it's UTF-8 string type. Not only it is guaranteed to point to valid
 memory, it is statically guaranteed to point to valid UTF-8!
The trouble with that is much of the UTF-8 out there is not valid. You don't want, for example, your html page to refuse to display at all because there's a couple invalid UTF-8 sequences in it. You don't want your text editor to refuse to load a file with invalid UTF-8 in it, either. You don't want your forms processor to summarily reject anything with invalid UTF-8 in it.
You don't have to refuse anything. Just substitute it with the Unicode replacement character in your standard library, and no downstream code will need to worry about it anymore. And should you ever need to process invalid sequences (e.g., in a utility to repair broken encodings), just read it as binary and process it that way.
 A better approach is to have the string processing be tolerant of
 invalid UTF-8.
Which makes string-processing code more fragile and possibly more complex. Better to let the standard library replace all invalid sequences with the replacement character so that downstream code doesn't have to worry about it anymore. T -- Doubtless it is a good thing to have an open mind, but a truly open mind should be open at both ends, like the food-pipe, with the capacity for excretion as well as absorption. -- Northrop Frye
Oct 27 2022
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 28/10/2022 12:55 PM, H. S. Teoh wrote:
 A better approach is to have the string processing be tolerant of
 invalid UTF-8.
Which makes string-processing code more fragile and possibly more complex. Better to let the standard library replace all invalid sequences with the replacement character so that downstream code doesn't have to worry about it anymore.
Officially you are meant to support only well formed UTF and anything else you are expected to reject. In practice yes, replacement character can be what you decode (which is what I do).
Oct 27 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/27/2022 4:55 PM, H. S. Teoh wrote:
 You don't have to refuse anything.  Just substitute it with the Unicode
 replacement character in your standard library, and no downstream code
 will need to worry about it anymore.
That's one way to deal with it. But until it is so processed, it isn't a string if the string requires strict UTF-8.
 And should you ever need to process invalid sequences (e.g., in a
 utility to repair broken encodings), just read it as binary and process
 it that way.
Yes, but you can't do it with strings, if strings don't allow invalid sequences.
 A better approach is to have the string processing be tolerant of
 invalid UTF-8.
Which makes string-processing code more fragile and possibly more complex.
I've coded a lot of Phobos to be tolerant of invalid UTF-8. It turns out that it's *unusual* to need to decode UTF-8 at all. It's robust, not fragile.
 Better to let the standard library replace all invalid
 sequences with the replacement character so that downstream code doesn't
 have to worry about it anymore.
Then you have another processing step, and have to make a copy of the string. As I wrote, I have some experience with this. Being tolerant of invalid UTF-8 is a winning strategy.
Oct 27 2022
parent reply Dukc <ajieskola gmail.com> writes:
On Friday, 28 October 2022 at 04:27:25 UTC, Walter Bright wrote:
 A better approach is to have the string processing be 
 tolerant of
 invalid UTF-8.
Which makes string-processing code more fragile and possibly more complex.
I've coded a lot of Phobos to be tolerant of invalid UTF-8. It turns out that it's *unusual* to need to decode UTF-8 at all. It's robust, not fragile.
Good point. But it could be easily solved by making the naturally tolerant functions to accept `ubyte`s.
 Better to let the standard library replace all invalid
 sequences with the replacement character so that downstream 
 code doesn't
 have to worry about it anymore.
Then you have another processing step, and have to make a copy of the string. As I wrote, I have some experience with this. Being tolerant of invalid UTF-8 is a winning strategy.
Don't you remember? Ranges are lazy. No copy needed. And IIRC Rust also has a lazy iterator over an unvalidated binary blob to accomplish the same. And it's not an extra step. If you don't validate a string, then the string processing functions (that need to decode) have to do that anyway. The Rust way has the advantages that: - No string handling function needs to throw anything. The could all be `nothrow`. - If two string handling functions that need to decode are chained to each other, they don't need to both reduntantly check for invalid UTF-8. - You don't accidently forget to check for invalid UTF-8, or recheck an already checked string. The first two could also be accomplished by asserting on invalid UTF-8 instead of throwing an exception, but only static guarantees give the third advantage.
Oct 28 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/28/2022 2:07 AM, Dukc wrote:
   - No string handling function needs to throw anything. The could all be 
 `nothrow`.
   - If two string handling functions that need to decode are chained to each 
 other, they don't need to both reduntantly check for invalid UTF-8.
   - You don't accidently forget to check for invalid UTF-8, or recheck an 
 already checked string.
I've discovered that: 1. throwing on invalid UTF-8 is the wrong solution. Phobos' autodecode does that. It was a huge mistake, but is a problem with Phobos, not D itself. 2. very, very few string algorithms have any need to decode the UTF-8. String copying, searching, hashing, etc., all have no need to decode. I've fixed a lot of the algorithms in Phobos to not decode. 3. detecting bad UTF-8 encodings only happens when decoding is needed. It costs nothing extra, as it falls out of the decoding logic. Then, one can decide to safely ignore it, or use the Replacement Char. It works fine. There just is no need to purify the strings.
Oct 29 2022
parent Dukc <ajieskola gmail.com> writes:
On Sunday, 30 October 2022 at 02:29:36 UTC, Walter Bright wrote:

 3. detecting bad UTF-8 encodings only happens when decoding is 
 needed. It costs nothing extra, as it falls out of the decoding 
 logic. Then, one can decide to safely ignore it, or use the 
 Replacement Char.
If the algorithm does not throw on invalid UTF, I guess so.
 It works fine. There just is no need to purify the strings.
No need, but a bit of benefit since some bugs could be catched at compile time. Then again, it'd be catching only one class of errors of the countess one that are possible. Rust's solution would still be of no help if we're excepting letters but receive numbers instead and forget to check. So maybe complexity-to-benefit ratio of it is still unfavourable. Someone with experience with Rust string handling could maybe judge it.
Oct 31 2022