Re: Parameters declared as the alias of a template won't accept the arguments of the same type.
On Monday, 2 May 2022 at 20:16:04 UTC, ag0aep6g wrote: On 02.05.22 21:17, Stanislav Blinov wrote: On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote: [...] ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce T Why? That's the issue. It is very possible to deduce T here. Compiler just isn't trying. The function takes an int. Doesn't take a rocket scientist to figure that one out. I take it your answer is that T must be int. But that's nonsense. MyAlias maps all types to int. It's not a bijection, you can't turn it around. That's not my answer. And it is nonsense, because my answer is - what T is irrelevant, MyAlias maps *all* types to int. Therefore `simp` takes an int, which is what the caller is passing.
Re: Parameters declared as the alias of a template won't accept the arguments of the same type.
On Monday, 2 May 2022 at 20:08:48 UTC, Ali Çehreli wrote: On 5/2/22 12:17, Stanislav Blinov wrote: > On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote: > >> Template deduction for aliased function parameter is a very tricky >> argument and it's not so simple to handle in certain cases. Consider >> for example this code: >> >> ```d >> template MyAlias(T){ >> alias MyAlias = int; >> } >> >> T simp(T)(MyAlias!T val){ >> return T.init; >> } >> >> int main(){ >> simp(3);//Impossible to deduce T > > Why? That's the issue. It is very possible to deduce T here. Compiler > just isn't trying. That's fine because D does not promise to solve such problems. It follows simple deduction rules. Words, dear guru. Words have a meaning. It is very possible to deduce here (note the premise). D just isn't trying. That's what I said. You can say "it doesn't promise". Doesn't exactly change the meaning, does it? :) > The function takes an int. How would the solution be? Wouldn't the compiler have to parse all accessible template bodies to figure out which ones fit? Err... yes? That's what it *is* doing already, for all templates. Imagine the following two other templates: template YourAlias(T) { alias YourAlias = int; // Is it this one? } template HerAlias(T) { // ... alias HerAlias = HisAlias!SomeNameInThisScope; // Or thi? } No. HerAlias and YourAlias are different symbols. The compiler would have to solve this problem by digging into HisAlias's SomeNameInThisScope instantiation as well. As far as know, the D language does not work that way. Prolog and friends perhaps? Nope. MyAlias is an alias. A template alias, but an alias nonetheless. It should be resolved prior to trying the overloads. > Doesn't take a rocket > scientist to figure that one out. I think this is one of those cases where it is easier for a human. Although, I think I would have difficulty if there were more than one template parameter. That's what we have compilers for. > I might as well forego the templates and > just write explicit overloads. At which point I would question why use > templates at all. Templates allow single implementations to work for many types, manifest constants, aliases, etc. I wouldn't want to write (or mix-in?) sort() for MyType. Templates are wonderful and their implementation in D is refreshing. It is, until is isn't. Question du jeour is one of those.
Re: Parameters declared as the alias of a template won't accept the arguments of the same type.
On Monday, 2 May 2022 at 16:29:05 UTC, Loara wrote: Template deduction for aliased function parameter is a very tricky argument and it's not so simple to handle in certain cases. Consider for example this code: ```d template MyAlias(T){ alias MyAlias = int; } T simp(T)(MyAlias!T val){ return T.init; } int main(){ simp(3);//Impossible to deduce T Why? That's the issue. It is very possible to deduce T here. Compiler just isn't trying. The function takes an int. Doesn't take a rocket scientist to figure that one out. simp( cast(MyAlias!string) 4);//Also invalid since MyAlias!string is exactly int Yes, invalid, as well it should be. simp!string(4);//Ok, no parameter deduction } ``` No issue here. Instead to use aliases it's better (both in D and in C++) to use constraints/concepts. No. It *would* be better if compiler didn't play stupid here. I shouldn't have to write 50+ more lines boilerplate for what the compiler should be able to figure out. I might as well forego the templates and just write explicit overloads. At which point I would question why use templates at all.
Re: CTFE and BetterC compatibility
On Wednesday, 27 April 2022 at 14:21:15 UTC, Claude wrote: This is a long-standing pain point with BetterC (see https://issues.dlang.org/show_bug.cgi?id=19268). As for this: If I compile without the BetterC switch, compilation actually works but I'll have some linker issues: ``` $ gcc test.d -o test First digit=5 /tmp/ccuPwjdv.o : In function « _D5test5parseFNaAyaZS5test4Data » : test.d:(.text+0x137) : undefined reference to « _d_arraybounds » test.d:(.text+0x183) : undefined reference to « _d_arraybounds » etc... ``` When not using BetterC, but not linking against druntime either, you have to provide your own implementation for those functions. This is e.g. so you can replace druntime with your own version.
Re: std.typecons Typedef initializers?
On Monday, 25 April 2022 at 23:41:47 UTC, Chris Katko wrote: So to use a typedef'd struct... I have to basically add the original type on top of the typedef'd type every time? Surely it's not this clunky? I mean, why even use a typedef then. Why not use just pair, sPair, vPair, etc as separate types with identical members and cast as necessary? I'm not sure what the benefit typedef is adding here. Thanks It could just be an oversight in implementation and worth submitting an enhancement request on bugzilla. Current implementation only defines a constructor that takes rvalue of original type, while what it ought to be doing is defining a variadic template constructor that would forward the arguments to underlying type's constructor. To be fair, as far as your example code goes, it'd almost be easier to indeed simply duplicate the implementations, but have the compiler do it for you, e.g. like this: ```d enum Space { unspecified, screen, viewport, } struct TPair(Space space) { float x, y; } alias Pair = Pair!(Space.unspecified); alias sPair = Pair!(Space.screen); alias vPair = Pair!(Space.viewport); ```
Re: Assigning to array of structs with custom constructor
On Monday, 25 April 2022 at 14:36:25 UTC, cc wrote: ```d struct Foo { string s; this(string s) { this.s = s; } } Foo foo = "a"; Foo[] foos = ["a"]; // Error: cannot implicitly convert expression `["a"]` of type `string[]` to `Foo[]` Foo[] foos = cast(Foo[]) ["a"]; // Error: e2ir: cannot cast `"a"` of type `string` to type `Foo` ``` Was there a way to do this? I thought I recalled seeing something like this before, but I can't seem to find it. Make it explicit: ```d Foo[] foos = [Foo("a")]; ```
Re: How to use destroy and free.
On Monday, 25 April 2022 at 10:13:43 UTC, Alain De Vos wrote: Ali, thanks for the answer but i rephrase my question. How to destroy,free , for garbage-collection-cycle in the destructor of this code : // But How to force destroy and free , GC-cycle for heap object i ? Short answer: use `destroy`. Long answer: don't do that. https://dlang.org/spec/class.html#destructors GC is not guaranteed to call destructors, and in fact it may run into situations when it can't (i.e. objects pointing to one another). Neither does it specify in what order destructors of GC-allocated objects are run (when they are run). If you need deterministic destruction e.g. for resource management, do not use GC.
Re: Variables & kind of memory
On Saturday, 23 April 2022 at 03:41:17 UTC, Alain De Vos wrote: Feel free to elaborate. Variables declared at module scope, and static variables in function/aggregate scopes, unless also annotated as `shared` or `__gshared`, are thread-local, therefore are placed in thread-local storage. That's why you see difference in addresses between e.g. &LV and &SLV in `main`.
Re: Lambda Tuple with Map Reduce
On Wednesday, 20 April 2022 at 08:37:09 UTC, Salih Dincer wrote: On Wednesday, 20 April 2022 at 08:04:42 UTC, Salih Dincer wrote: I get an unexpected result inside the second foreach() loop. Anyone know your reason? It's my fault, here is the solution: ```d foreach(fun; funs) { range.map!(a => fun(a)) .reduce!sum .write(" "); // Ok! } writeln; // "1115 188 102 86 47" ``` With the original version, I'm getting expected results with 2.098.1. run.dlang.io with 'dmd' also shows expected results.
Re: save and load a 2d array to a file
On Tuesday, 19 April 2022 at 06:05:27 UTC, Ali Çehreli wrote: One quirk of rawWrite and rawRead is that they want slices of objects. It is a little awkward when there is just one thing to write and read. Uncompiled but something like this: int i = 42; file.rawWrite(*cast((int[1]*)(&i))); // Casted to be an array of 1 Yuck :) ```d file.rawWrite((&i)[0..1]); ```
Re: Nested function requires forward declaration?
On Thursday, 14 April 2022 at 08:55:25 UTC, Chris Katko wrote: Using DMD. v2.098-beta-2 Not sure if right terminology. But I just wrote a nested function that uses a variable outside its body. The capture (right term?) is obvious where the invocation is. However, I have to move the declaration of the variable to above the nested function for it to compile. Declarations in function scope are processed in order. This includes nested functions: https://dlang.org/spec/function.html#nested (see #8).
Re: How to implement this?
On Friday, 8 April 2022 at 05:53:03 UTC, Elvis Zhou wrote: assumeNoEscapeOrWhatever!DynamicArray structs; structs ~= cast(A*)&b; is it possible? That's what `@trusted` is for. And that's also why it should be used with care, and on the smallest code possible. ```d struct A {} struct B { A a; } struct C { A a; } void main() { A*[] structs; B b; C c; () @trusted { structs ~= cast(A*)&b; structs ~= cast(A*)&c; } (); } ```
Re: A weird example of .toUTF16z concatination side-effects in wcsncat
On Thursday, 7 April 2022 at 10:50:35 UTC, BoQsc wrote: wchar_t* clang_string = cast(wchar_t *)"AA"; You're witnessing undefined behavior. "AA" is a string literal and is stored in the data segment. Mere cast to wchar_t* does not make writing through that pointer legal. Moreover, even if it was legal to write through it, that alone wouldn't be sufficient. From documentation of `wcsncat`: The behavior is undefined if the destination array is not large enough for the contents of both str and dest and the terminating null wide character. `wcsncat` does not allocate memory, it expects you to provide a sufficiently large mutable buffer. For example, like this: ```d // ... auto cls = new wchar_t[256]; cls[] = 0; cls[0..10] = 'A'; wchar_t* clang_string = cls.ptr; // ... ```
Re: How to print or check if a string is "\0" (null) terminated in the D programming language?
On Wednesday, 6 April 2022 at 08:55:43 UTC, BoQsc wrote: I have a feeling that some parts of my code contains unterminated strings and they do overflow into other string that is to be combined. I'd like to take a look at strings, analyse them manually and see if any of them end up terminated or not. Please provide any relevant examples of how you do this. In general, you shouldn't do that. In D, a `string`, `wstring` and `dstring` are slices of corresponding character types, and are *not* null-terminated (and in fact can contain 0 within their representation). However, as Andrea Fontana points out, string literals are null-terminated (but note that the terminator itself isn't included in a `string` initialized with such a literal), and also convert to pointers - these two properties allow using them as arguments to C functions. Thus, since null terminator isn't normally included as part of a string, you'd have to read past array bounds to check if there's a 0 there, and doing so leads to undefined behavior. In fact, you should simply assume that any D string you encounter is not null-terminated. And if you want to ensure you're always passing around null-terminated strings, you should either use the greedy allocating functions such as `toStringz`, or perhaps make your own type that always allocates extra space for a 0.
Re: Is it safe to read to memory after it has been allocated with `pureMalloc` and `pureRealloc`?
On Monday, 4 April 2022 at 07:32:00 UTC, rempas wrote: In other terms, do these functions auto-initialize memory to be ready for use? No. Neither `malloc` nor `realloc` (for which D's `pure...` variants are mere wrappers) are specified to initialize allocated memory. `calloc`, however, is - it initializes allocated block with zeroes.
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 13:38:42 UTC, Vinod K Chandran wrote: On Saturday, 19 March 2022 at 11:47:53 UTC, Stanislav Blinov wrote: No. First of all Thanks for the reply. The answer "No" is a wonder to me. Because, from my point of view, `U` is coming from nowhere. My understanding is, we can use any parameter of a template inside the template. So in this case `U` is not in the parameter list. It is suddenly appearing in that `static if`. It is appearing not in the `static if`, but in the `is` expression, which I described further in the rest of my first reply. Sorry if that wasn't clear. The test is not `T t == U[]`. It is `is(T t == U[], U)`. Okay, I understand. Actually, the lower case `t` is not needed there, you can simply write `is(T == U[], U)`. So the `T` is not the type. It's the parameter. Right ? So a template doesn't need a type. Only the parameter, right ? (I think I am too dumb to ask this. Please forgive me.) Oh don't worry, this topic is not at all obvious with the `is` expression having its own syntax and semantics. `T` is a type, a type you instantiate `rank` with. `template rank(T)` *does* expect a type as a parameter. The other template syntax - `template foo(alias T)` can take as `T` any symbol, not just a type. Yes, and `U` then becomes `int[][]`. Which is why the template recurses down and instantiates itself with `U`, until `T` fails the test. In order to understand this, I need to understand from where the `U` comes. It comes from you, the programmer. Like I said before, `is(T == U[], U)` means "is T an array of some type, the type which I (the programmer) would like to refer to as U?". That's all there is to it (well, not quite, but it should suffice for starters). You're simply introducing an identifier. So, when `T` is an `int[][][]`, naturally, `U` becomes an alias to `int[][]` (look at the converse - when `U` is `int[][]`, `U[]` is naturally an `int[][][]`). You can think of that test as this: ```d import std.traits : isDynamicArray; // ... static if (isDynamicArray!T) { alias U = typeof(T.init[0]); // ... } ``` ...which would roughly be the same thing - you test if `T` is a dynamic array of some type, and then make an alias for that array's element type. It's just that the `is` expression allows you to create such alias in situ.
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 05:54:26 UTC, Vinod K Chandran wrote: Question 1 - `U` is appearing in the first static if statement. But we had to write `U` on the template line, right? Like - `template rank(T, U)` No. Question 2 - The statif if test is - `T t == U[ ]` What does that mean ? The test is not `T t == U[]`. It is `is(T t == U[], U)`. https://dlang.org/spec/expression.html#is-identifier-equal ``` is ( Type Identifier == TypeSpecialization ) The condition is satisfied if Type is semantically correct and is the same as TypeSpecialization. The Identifier is declared to be either an alias of the TypeSpecialization or, if TypeSpecialization is dependent on Identifier, the deduced type. ``` You simply introduce new identifiers. Basically, the test means "is T an array of some type which I would like referred to as U?". Actually, the lower case `t` is not needed there, you can simply write `is(T == U[], U)`. Question 3 - if `T t == U[ ]` is the test, then I think when we pass ```d rank!(int[ ][ ][ ]) ``` The test will be `int[ ][ ][ ] == U[ ]`, Right ? Yes, and `U` then becomes `int[][]`. Which is why the template recurses down and instantiates itself with `U`, until `T` fails the test.
Re: How to remove all characters from a string, except the integers?
On Friday, 4 March 2022 at 19:51:44 UTC, matheus wrote: OK but there is another problem, I tested your version and mine and there is a HUGE difference in speed: string s, str = "4A0B1de!2C9~6"; Unless I did something wrong (If anything please tell). By the way on DMD was worse, it was like 5x slower in your version. To add to the already-mentioned difference in allocation strategies, try replacing the input with e.g. a command-line argument. Looping over a literal may be skewing the results.
Re: How to remove all characters from a string, except the integers?
On Thursday, 3 March 2022 at 12:14:13 UTC, BoQsc wrote: I need to check if a string contains integers, and if it contains integers, remove all the regular string characters. I've looked around and it seems using regex is the only closest solution. ```d import std.stdio; import std.algorithm : find, filter; import std.conv : to; import std.uni : isNumber; void main(string[] args){ if (args.length > 1){ auto filtered = () { auto r = args[1].find!isNumber; // check if a string contains integers return r.length ? r.filter!isNumber.to!string // and if it does, keep only integers : args[1]; // otherwise keep original } (); filtered.writeln; } else { write("Please write an argument."); } } ```
Re: Detecting ElementType of OutputRange
On Saturday, 26 February 2022 at 12:26:21 UTC, Vijay Nayar wrote: On Saturday, 26 February 2022 at 11:44:35 UTC, Stanislav Blinov wrote: https://dlang.org/phobos/std_range_primitives.html#isOutputRange This method requires the caller to explicitly declare the output range element type, which I was hoping to have to avoid, if it can be detected using reasonable assumptions. Considering that `put` is quite typically implemented as a template, I don't think that would be possible in general. The question is, do you really need that? Your `BufferedOutputRange` can test the underlying range using `isOutputRange` in its own implementation of `put`, where the type of element is known, i.e. to test whether it can bulk-write a slice (or a range of) elements or has to make per-element calls to `put`.
Re: Detecting ElementType of OutputRange
https://dlang.org/phobos/std_range_primitives.html#isOutputRange
Re: Differences between lambda function and regular functions in higher order functions
On Monday, 21 February 2022 at 10:04:16 UTC, steve wrote: I am trying to implement a simple map function. I found code to do this in another post but it only seems to work with lambda functions and I do not understand why. Any help would be greatly appreciated ``` import std.stdio; T[] map_vals(T,S)(scope T function(S) f, S[] a){ auto b = new T[a.length]; foreach(i,x;a) b[i] = f(x); return b; } ``` As partypooper says, with that singature it'll only work if you pass function pointer (whereas a lambda converts to one). Alternatively (and how it is typically done in i.e. D's standard library), you can pass your callable as a compile-time argument. This also has an advantage of supporting UFCS, as shown in this example: ```d import std.stdio; // original, needs a function pointer T[] map_vals(T,S)(scope T function(S) f, S[] a){ auto b = new T[a.length]; foreach(i,x;a) b[i] = f(x); return b; } // Takes the callable as a compile-time argument auto map_vals(alias f,S)(S[] a) if (is(typeof(f(a[0] { alias T = typeof(f(a[0])); auto b = new T[a.length]; foreach (i, ref x; a) b[i] = f(x); return b; } auto timestwo(float x) { return 2*x; } void main(){ float[] my_array = [1., 2., 3.]; auto ff = (float x)=>2*x; // This works writeln(map_vals(ff, my_array)); // this works with pointer to timestwo writeln(map_vals(×two, my_array)); // and this works by just passing the symbol name, // also note UFCS syntax: my_array.map_vals!timestwo.writeln; // as does this: my_array.map_vals!ff.writeln; // and this: my_array.map_vals!(x => 2*x).writeln; } ``` Note that `map` already exists in Phobos (https://dlang.org/phobos/std_algorithm_iteration.html#map), and that one makes a lazy range and doesn't allocate.
Re: Function Parameters without Names?
On Saturday, 19 February 2022 at 23:37:01 UTC, Vijay Nayar wrote: What is the main motivator to allow parameters with no names? 1) `extern(C) void* malloc(size_t);` No need for parameter name at all as that is only a declaration. You don't have an implementation thus don't need a name for the parameter. 2) As Ali says, unused parameters (i.e. in template specializations, virtual function overrides, dummy parameters for overload resolution purposes, etc.)
Re: Member function forwarding
On Thursday, 17 February 2022 at 21:17:02 UTC, Andrey Zherikov wrote: On Thursday, 17 February 2022 at 20:59:43 UTC, Andrey Zherikov wrote: Another question: does `auto foo(ARGS...)(ARGS args) { return a.foo(args); }` correctly forward `ref`, `const` etc. arguments? Actually the answer is `NO`. I have to do `auto foo(ARGS...)(auto ref ARGS args) { return a.foo(args); }`. This also doesn't forward correctly. It'll always try to copy all arguments. What would fowrard is ``` import core.lifetime : forward; auto foo(Args...)(auto ref Args args) { return a.foo(forward!args); } ```
Re: what's meaning of "(a) =>"
On Saturday, 5 February 2022 at 15:10:19 UTC, step8 wrote: I'm trying to study D programming Following is code from vibe's example(web_ajax) code: void getDataFiltered(Fields field, string value) { auto table = users.filter!((a) => value.length==0 || a[field]==value)().array(); render!("createTable.dt", table)(); } I can't understand the expression "(a) =>",there is no defination of "a",how does this work? thanks for help `(a) => value.length==0 || a[field]==value` is a https://dlang.org/spec/expression.html#FunctionLiteral (see e.g. #10 there). This one is polymorphic, somewhat equivalent to defining a function such as `bool func(T)(T a) { return value.length==0 || a[field]==value; }` (assuming `value` is accessible to `func`).
Re: ldc executable crashes with this code
On Friday, 4 February 2022 at 11:26:42 UTC, forkit wrote: If I had wrote the code below, then I should not expect anything, whatsoever, from the compiler. () @trustMe_I_am_a_complete_idiot { char[] palindrome = cast(char[])"able was I ere I saw elba"; } (); This is almost exactly what you have to do today, assuming you're using @safe. You'll **have** to write this then: `() @trusted { auto palindrome = cast(char[])"able was I ere I saw elba"; } ();` Instead, you opted to comment out `@safe`. Unfortunately, "@safe by default" idea was brutally eviscerated. As others have already stated, casting immutability away is something that has to be supported, e.g. to interface with const-agnostic APIs. `@safe` requires such casts to be more verbose, with good reason.
Re: passing a variadic parameter to randomSample
On Tuesday, 25 January 2022 at 22:07:43 UTC, Ali Çehreli wrote: On 1/25/22 13:55, forkit wrote: > auto RandomChoice(R...)(R r) Watch out though: The compiler will compile a different function per set of values. For example, there will be separate RandomChoice instances for ("hello") vs. ("world"). Huh? Perhaps you meant "for ("hello") vs. ("hello", "world")"? Because it would be the same instantiation for a single string argument :)
Re: Linkage question
On Monday, 24 January 2022 at 17:23:01 UTC, frame wrote: I understand that the linkage must match but besides the name mangling, what's happen here? What is the difference if I remove the `extern (C)` part from the T alias? The difference is in how arguments are being passed, which you seem to have discovered already :) Would like to know where the linkage format is defined, thx. It should be here: https://dlang.org/spec/abi.html although IIRC it might not be 100% up to date.
Re: map question
On Sunday, 23 January 2022 at 09:38:57 UTC, Siarhei Siamashka wrote: On Sunday, 23 January 2022 at 09:08:46 UTC, Stanislav Blinov wrote: Using `iota` here incurs additional computation and argument copies that are actually never used, i.e. wasted work. So I'd say go with `generate`, as that seems the intent. Isn't this normally a compiler's job to eliminate all unused computations and copies? It is the programmer's job long before it is the compiler's. It can do wonders on your "minimal" code but it's not its job to read your mind. ```D auto foobar1(size_t n) { return n.iota.map!(_ => 123).array; } auto foobar2(size_t n) { return generate!(() => 123).take(n).array; } ``` LDC with "-O -release" command line options generates pretty much identical code for foobar1 and foobar2 (I'm only showing the main loop, but the rest is also the same): ``` 20: 48 39 c8cmp%rcx,%rax 23: 74 18 je 3d <_D2zz7foobar1FNaNbNfmZAi+0x3d> 25: c7 04 8a 7b 00 00 00movl $0x7b,(%rdx,%rcx,4) 2c: 48 83 c1 01 add$0x1,%rcx 30: 48 39 cbcmp%rcx,%rbx 33: 75 eb jne20 <_D2zz7foobar1FNaNbNfmZAi+0x20> ``` ``` 20: 48 39 c8cmp%rcx,%rax 23: 74 18 je 3d <_D2zz7foobar2FNaNbNfmZAi+0x3d> 25: c7 04 8a 7b 00 00 00movl $0x7b,(%rdx,%rcx,4) 2c: 48 83 c1 01 add$0x1,%rcx 30: 48 39 cbcmp%rcx,%rbx 33: 75 eb jne20 <_D2zz7foobar2FNaNbNfmZAi+0x20> ``` Do you have a better example to demonstrate `generate`'s superiority? Try actual work instead of returning a literal :) Like e.g. calling dice(50, 50). One thing to note though - `generate` will always eagerly call its function at least once. Which of course should also be considered in choosing the desired implementation. I.e. if your `n` comes from user and is allowed to be 0, then `generate` becomes an inferior choice.
Re: map question
On Saturday, 22 January 2022 at 23:54:27 UTC, forkit wrote: On Saturday, 22 January 2022 at 19:55:43 UTC, Stanislav Blinov wrote: thanks for the explanation. That really helped :-) writeln( generate!(() => dice(0.6, 1.4)).take(howManyTimes) ); [1, 1, 1, 1, 0] (or after reading Ali's response - getting rid of rnd, and using _ ) writeln( howManyTimes.iota.map!(_ => dice(0.6, 1.4)) ); [1, 0, 1, 1, 1] They produce exactly the same thing, so I guess it comes down to personal choice now. Using `iota` here incurs additional computation and argument copies that are actually never used, i.e. wasted work. So I'd say go with `generate`, as that seems the intent.
Re: map question
On Saturday, 22 January 2022 at 19:32:07 UTC, forkit wrote: trying to make sense of the below: // --- module test; import std; void main() { auto rnd = Random(unpredictableSeed); int howManyTimes = 5; // ok - using 'e =>' makes sense writeln(howManyTimes.iota.map!(e => rnd.dice(0.6, 1.4)).format!"%(%s,%)"); // ok - though using 'howManyTimes =>' doesn't make much sense?? writeln(howManyTimes.iota.map!(howManyTimes => rnd.dice(0.6, 1.4)).format!"%(%s,%)"); // NOT ok - using '5 =>' - but isn't this effectively the same as above line? //writeln(howManyTimes.iota.map!(5 => rnd.dice(0.6, 1.4)).format!"%(%s,%)"); } // --- No, it's not the same. 'Tis not really a "map question", looks more like a question about https://dlang.org/spec/expression.html#function_literals (see #10). In the second case, you're defining a lambda with single parameter named `howManyTimes`, which is not at all related to your local variable of the same name. Third case is invalid, as you're effectively trying to do this: auto func(T)(T 5) { return rnd.dice(0.6, 1.4); } Which, of course, doesn't make any sense, does it? :) Given your use case (call a function N times), I think `generate` would be more appropriate here: ```d import std.random; import std.stdio; import std.range : generate, take; void main() { auto rnd = Random(unpredictableSeed); int howManyTimes = 5; generate!(() => rnd.dice(0.6, 1.4)).take(howManyTimes).writeln; } ```
Re: forward tuple arg to local variable + dtor
On Saturday, 22 January 2022 at 18:00:58 UTC, vit wrote: I want implement something like this: Scratch the previous reply, 'twas a brain fart... Simply take by value, no need for extra copies at all in that case. Arguments themselves will become those copies as needed. ```d import std.meta : allSatisfy; enum bool isRcPtr(T) = is(T == RcPtr!U, U); //@safe access to data of multiple ref counted objects: public auto apply(alias fn, Args...)(Args args) if (allSatisfy!(isRcPtr, Args)) { @property auto ref elm(alias param)()@trusted{ return param.get(); } return fn(staticMap!(elm, args)); } ```
Re: forward tuple arg to local variable + dtor
On Saturday, 22 January 2022 at 18:00:58 UTC, vit wrote: I want implement something like this: ... Take by value and make a copy without forwarding: ```d import std.typecons : Tuple; import std.meta : allSatisfy; enum bool isRcPtr(T) = is(T == RcPtr!U, U); //@safe access to data of multiple ref counted objects: public auto apply(alias fn, Args...)(Args args) if (allSatisfy!(isRcPtr, Args)) { Tuple!Args params = args; // borrow all @property auto ref elm(alias param)()@trusted{ return param.get(); } return fn(staticMap!(elm, args)); // staticMap over original args tuple } ``` Or make a helper function that takes by value and forward to that: ```d template apply(alias fn) { private auto impl(Args...)(Args args) { @property auto ref elm(alias param)()@trusted{ return param.get(); } return fn(staticMap!(elm, args)); } auto apply(Args...)(auto ref Args args) if (allSatisfy!(isRcPtr, Args)) { import core.lifetime : forward; return impl(forward!args); // impl takes by value - RcPtrs passed by reference will be copied } } ```
Re: automate tuple creation
On Friday, 21 January 2022 at 03:50:37 UTC, forkit wrote: I might have to use a kindof stringbuilder instead, then write a massive string once to the file. You're using writeln, which goes through C I/O buffered writes. Whether you make one call or several is of little consequence - you're limited by buffer size and options.
Re: automate tuple creation
On Thursday, 20 January 2022 at 12:15:56 UTC, forkit wrote: void createUniqueIDArray(ref int[] idArray, int recordsNeeded) { idArray.reserve(recordsNeeded); debug { writefln("idArray.capacity is %s", idArray.capacity); } // id needs to be 9 digits, and needs to start with 999 // below will contain 1_000_000 records that we can choose from. int[] ids = iota(999_000_000, 1_000_000_000).array; // NOTE: does NOT register with -profile=gc int i = 0; int x; while(i != recordsNeeded) { x = ids.choice(rnd); // ensure every id added is unique. if (!idArray.canFind(x)) { idArray ~= x; // NOTE: does NOT register with -profile=gc i++; } } } Allocating 4 megs to generate 10 numbers??? You can generate a random number between 99900 and 10. ``` immutable(int)[] createUniqueIDArray(int recordsNeeded) { import std.random; import std.algorithm.searching : canFind; int[] result = new int[recordsNeeded]; int i = 0; int x; while(i != recordsNeeded) { // id needs to be 9 digits, and needs to start with 999 x = uniform(999*10^^6, 10^^9); // ensure every id added is unique. if (!result[0 .. i].canFind(x)) result[i++] = x; } import std.exception : assumeUnique; return result.assumeUnique; } void main() { import std.stdio; createUniqueIDArray(10).writeln; } ``` Only one allocation, and it would be tracked with -profile=gc...
Re: why there is a [] at the end of assocArray
On Wednesday, 19 January 2022 at 13:15:35 UTC, michaelbi wrote: foreach(line; > File("input.txt").byLine.map!(a=>a.idup).array.transposed) so why there is a [] at the end of assocArray printed? thanks. ...because there's an empty line at the end of input.txt?
Re: A slice consisting of non-consecutive elements of an array?
On Thursday, 13 January 2022 at 19:52:27 UTC, forkit wrote: Any idea on how I can get a ptr (without hardcoding C style) e.g. something like this: immutable(string)*[] pointers = strings.filter!(x => x == "one").to!pointers.array; ```d import std.stdio : writeln; import std.algorithm : filter, map, each; import std.range : array; void main() @safe { immutable strings = ["one", "one", "two", "one", "two", "one", "one", "two"]; immutable(string)*[] pointers = strings.filter!(x => x == "one").map!((ref x) @trusted => &x).array; pointers.each!(p => writeln(p - &strings[0])); } ```
Re: Returning value by ref does not create a ref. Is this intentional?
On Wednesday, 5 January 2022 at 04:35:12 UTC, Tejas wrote: ```d import std.stdio:writeln; ref int func(return ref int a){ a = 6; // modifies a as expected return a; } void main(){ int a = 5; auto c = func(a); // I expected c to alias a here c = 10; // Expected to modify a as well writeln(a); // prints 6 :( } ``` The [spec](https://dlang.org/spec/function.html#ref-functions) states: Ref functions allow functions to return by reference, meaning that the return value must be an lvalue, and the lvalue is returned, not the rvalue. Then why does the reference to `a` not get returned ? It is returned. But initializing `c` with it makes a copy. This will mutate `a`: ``` func(a) = 10; ```
Re: Mixin a function into a struct only if no member with that name already exists
On Wednesday, 29 December 2021 at 10:14:13 UTC, Tobias Pankrath wrote: How do I mixin a function only if it is not already present? Perhaps use opDispatch?
Re: AA and struct with const member
On Wednesday, 29 December 2021 at 02:33:08 UTC, frame wrote: On Wednesday, 29 December 2021 at 01:11:13 UTC, Stanislav Blinov wrote: Because opIndexAssign cannot distinguish at compile time between initialization and assignment: ```d Stuff[Key] aa; aa[key] = Stuff(args); // ostensibly, initialization aa[key] = otherStuff; // assignment to existing value ``` Same syntax, different behavior. This can only be caught at runtime. `require` and `update` though should be able to pull this off, and that they don't is a bug. Of course but opIndexAssign() isn't there in my example. The compiler should call runtime's _aaGetY() or something like that directly. It is doing that. You've asked why that should be compile error, and the answer is - because there's no way to distinguish between initialization and assignment here. I.e. you can't make one line compile and the other - not. Either both compile, or both don't. So if you allow them to compile, you'll have to have a runtime check, throwing an exception on attempt to assign. Which is just horrible. Better to leave the assignment a compile error, and make `require` and `update` do the job they're supposed to be doing.
Re: Is there a way to make a function parameter accept only values that can be checked at compile time?
On Tuesday, 28 December 2021 at 22:30:30 UTC, Ali Çehreli wrote: On 12/28/21 2:06 PM, Steven Schveighoffer wrote: void print_num(int mul)(int num) { Wasn't there a way of telling whether an 'auto ref' parameter is copied or not? void print_num()(int num, auto ref int mul) { // ? } And that would indicate that the argument was an rvalue? __traits(isRef, mul). I realize that rvalues are not exactly what the OP is interested in. Yup, different thing. One can also do this kind of stuff: ```d import core.stdc.stdio; struct Literal(alias val) { enum value = val; } enum lit(alias val) = Literal!val.init; void print_num(Arg)(int num, Arg mul) { static if (is(Arg == Literal!val, alias val)) { static if (is(typeof(val) == string)) printf("mul by compile-time string \"%s\"!\n", val.ptr); else static if (is(typeof(val) == int) && (val == 3)) printf("mul by compile-time 3!\n"); else printf("mul by compile-time thing\n"); } else { printf("mul by runtime thing\n"); } } void main() { print_num(10, lit!"hello"); // mul by compile-time string "hello"! print_num(10, lit!3); // mul by compile-time 3! print_num(10, lit!'a'); // mul by compile-time thing print_num(10, 10); // mul by runtime thing } ```
Re: AA and struct with const member
On Tuesday, 28 December 2021 at 22:46:16 UTC, frame wrote: On Tuesday, 28 December 2021 at 10:02:13 UTC, tsbockman wrote: // Should be a compile-time error, because it might reassign: test[key] = S(value); This might be a typo in your example but why should it be a compile-time error, it cannot know if the key already exists in compile time on a variable. First time initialization should always work anyway. Because opIndexAssign cannot distinguish at compile time between initialization and assignment: ```d Stuff[Key] aa; aa[key] = Stuff(args); // ostensibly, initialization aa[key] = otherStuff; // assignment to existing value ``` Same syntax, different behavior. This can only be caught at runtime. `require` and `update` though should be able to pull this off, and that they don't is a bug.
Re: How to loop through characters of a string in D language?
On Thursday, 23 December 2021 at 07:14:35 UTC, Salih Dincer wrote: It seems faster than algorithms in Phobos. We would love to see this in our new Phobos. ```d void mallocReplace() void normalReplace() string result = str.replace(';',""); }/* Console Out: Replace: 436 msecs Malloc : 259 msecs */ ``` You're comparing apples and oranges. When benchmarking, at least look at the generated assembly first. replace is not in Phobos, it's a D runtime vestige. It's not getting inlined even in release builds with lto, whereas that manual version would. Also, benchmark with runtime strings, not literals, otherwise the compiler might even swallow the thing whole. What you're benchmarking is, basically, inlined optimized search in a literal versus a function call.
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 15:42:59 UTC, russhy wrote: Please keep us updated, that'll be interesting to see how a pure D printf would look like! It already exists, it's called std.format.write.formattedWrite, in terms of which things like std.stdio.writef are implemented.
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 18:03:09 UTC, rempas wrote: > Now the problem is that I want it to get the name of so > symbol and add it to a string literal. Let's check this example: enum state(alias name) = `name` ~ ` = 10;`; https://dlang.org/spec/traits.html#identifier
Re: dynamic array + copy ctor
On Sunday, 19 December 2021 at 22:29:21 UTC, vit wrote: Hello, Why is copy ctor in this example not called? Because D runtime isn't properly married to copy constructors yet. I.e. it's a bug, a variant of this one: https://issues.dlang.org/show_bug.cgi?id=20879
Re: How to define property type to Array!struct?
On Wednesday, 15 December 2021 at 11:36:41 UTC, Manfred Nowak wrote: On Tuesday, 14 December 2021 at 08:28:01 UTC, WebFreak001 wrote: [...] Alternatively, remove the template `()` from your `struct Header` What is the semantic sense of a template having no parameters? Although the documentation declares such a template to be syntactically correct, not a single example suggests a meaning. To add to other responses, certain features are only available for templates, such as constraints and `auto ref` parameters.
Re: Passing a derived class where base class is defined as ref parameter
On Tuesday, 14 December 2021 at 17:20:18 UTC, chopchop wrote: I am using the "ref" here (I put tinyurl to avoid over-referencing the post instead of the github page itself): https://tinyurl.com/bdddkmub I would like to be able to pass any kind of console to updateFoodToken ( Console c ), ie either a winconsole or a nixconsole, which are derived from Console. I mean I probably have a cognitive bias of being a c++ dev. Let me explain. If I was coding in C++ I would pass "A&". Not "const A&", because I do two function calls with console - for example console.gotoxy(...) - but those 2 members functions are not suffixed "const". Since it is work in progress, I dont even know if I am going to modify those functions at the end or do something else with console... Simple. Don't take a `ref`. Just take a `Console`. Classes in D are reference types, you're not making a copy as you would in C++ if you were to write `updateFoodToken(Console c)`.
Re: Immutability and arrays
On Tuesday, 14 December 2021 at 15:28:30 UTC, Steven Schveighoffer wrote: All the other problems you are having are deriving from this problem. Not exactly. One of the problems seems to be a genuine bug: ```d struct S { int[] x; // doesn't even participate here, neither would postblit this(ref return scope inout S other) { x = other.x.dup; } void opAssign(ref return scope inout S other) { x = other.x.dup; } } void main() { immutable(S)[] src = [S([1, 2]), S([3, 4])]; auto dst = new S[src.length]; //dst[0 .. $] = src[0 .. $]; // this fails to compile even with opAssign defined // this works: foreach (i, ref it; dst) it = src[i]; } ``` Spec: https://dlang.org/spec/arrays.html#array-copying ...contents of the array are the target of the assignment... Per that wording, slice assignment should perform the equivalent of that foreach loop (after overlap checks, etc.). It doesn't, just tries implicit conversion, and fails. Now, since we have copy ctors, slice assignment should, ostensibly, attempt to copy-assign elements (i.e. absent opAssign, try the copy ctor first).
Re: Immutability and arrays
On Tuesday, 14 December 2021 at 08:44:02 UTC, rumbu wrote: I am trying to understand why in this two different cases (Simple and Complex), the compiler behaviour is different. ```d struct SimpleStruct { int x;} struct ComplexStruct { int[] x; } void main() { SimpleStruct[] buf1; immutable(SimpleStruct)[] ibuf1; buf1[0 .. 10] = ibuf1[0 .. 10]; //this works ComplexStruct[] buf2; immutable(ComplexStruct)[] ibuf2; buf2[0 .. 10] = ibuf2[0 .. 10]; //error cannot implicitly convert expression `ibuf2[0..10]` of type `immutable(ComplexStruct)[]` to `ComplexStruct[]` } ``` Because is(typeof(immutable(ComplexStruct).x) == immutable(int[])). Can't bind an array of immutable to array of mutable. This would require a deep copy, i.e. copy constructor.
Re: A debug class has started
On Monday, 13 December 2021 at 20:58:42 UTC, forkit wrote: immutable(char)[] replaceChar(char* str, ulong len, char ch1, char ch2) //snip return to!(immutable(char)[])(str); } You're calling a `to` on a char pointer, which, ostensibly, would look for null terminator. Which there may not be any if you do a .dup.
Re: Why code failed to compile for foo2?
On Saturday, 11 December 2021 at 23:44:59 UTC, Adam Ruppe wrote: On Saturday, 11 December 2021 at 23:17:17 UTC, Stanislav Blinov wrote: ? No. If it was unsatisfied constraint, the error would've shown that. And if you try to instantiate it, you'll see it is an unsatisfied constraint anyway. There's two layers of failure here. Using Unqual there is pretty iffy, i wouldn't bother with it at all, but if you do anything, instead qualify it const. But either way, then the constraint still fails since int isn't unsigned. I'd really recommend simplifying this a lot. ??? There is no unsatisfied constraint, it doesn't get there :) unq.d(6): Error: template `unq.foo2` cannot deduce function from argument types `!()(int)` unq.d(2):Candidate is: `foo2(T)(Unqual!T x)` ...because passed argument - `int` - becomes `Unqual!T`, making `T` unknown - template arg list is empty. Deduction fails :) If `int` is an `Unqual!T`, what is `T`? The constraint is testing `T`. Now, if you explicitly instantiate - sure, you'd get unsatisfied constraint. But the OP seems to want IFTI, which simply can't work here. @apz28, I can't figure out the intent here. To convert result of abs to an unsigned?
Re: Why code failed to compile for foo2?
On Saturday, 11 December 2021 at 22:59:52 UTC, Adam Ruppe wrote: On Saturday, 11 December 2021 at 22:50:45 UTC, apz28 wrote: void foo2(T)(Unqual!T x) if(isUnsigned!T) {} This means it treats foo2 as if it doesn't exist unless T is unsigned... onlineapp.d(15): Error: template `onlineapp.foo2` cannot deduce function from argument types `!()(int)` onlineapp.d(7):Candidate is: `foo2(T)(Unqual!T x)` */ And this is telling you it had a signed value - int - which means it doesn't match. For the other ones, the functions still exist, so it does whatever conversion it needs. Whereas with the template that constraint means the compiler acts like it doesn't exist at all and thus doesn't even attempt an automatic conversion. ? No. If it was unsatisfied constraint, the error would've shown that. What's going on here is that the argument being passed is an int, when the parameter is an Unqual!T. So, https://dlang.org/spec/template.html#ifti would fail because there is no way of figuring out a T from an Unqual!T. Hence the message: cannot deduce function.
Re: How to loop through characters of a string in D language?
On Saturday, 11 December 2021 at 09:34:17 UTC, Ola Fosheim Grøstad wrote: void donttrythisathome(string s, char stripchar) @trusted { import core.stdc.stdlib; char* begin = cast(char*)alloca(s.length); A function with that name, and calling alloca to boot, cannot be @trusted ;)
Re: How to loop through characters of a string in D language?
On Friday, 10 December 2021 at 23:53:47 UTC, Ola Fosheim Grøstad wrote: ```d char[] dontdothis(string s, int i=0, int skip=0){ if (s.length == i) return new char[](i - skip); if (s[i] == ';') return dontdothis(s, i+1, skip+1); auto r = dontdothis(s, i+1, skip); r[i-skip] = s[i]; return r; } ``` That is about 500% not what I meant. At all. Original code in question: - duplicates string unconditionally as mutable storage - uses said mutable storage to gather all non-semicolons - duplicates said mutable storage (again) as immutable I suggested to make the second duplicate conditional, based on amount of space freed by skipping semicolons. What you're showing is... indeed, don't do this, but I fail to see what that has to do with my suggestion, or the original code. Scanning short strings twice is not all that expensive as they will stay in the CPU cache > when you run over them a second time. ```d import std.stdio; @safe: string stripsemicolons(string s) @trusted { int i,n; foreach(c; s) n += c != ';'; // premature optimization auto r = new char[](n); foreach(c; s) if (c != ';') r[i++] = c; return cast(string)r; } ``` Again, that is a different algorithm than what I was responding to. But sure, short strings - might as well. So long as you do track the distinction somewhere up in the code and don't simply call this on all strings.
Re: How to loop through characters of a string in D language?
On Friday, 10 December 2021 at 13:22:58 UTC, Matheus wrote: My C way of thinking while using D: import std; string stripsemicolons(string input){ char[] s = input.dup; int j=0; for(int i=0;i Oooh, finally someone suggested to preallocate storage for all these reinventions of the wheel :D I would suggest instead of the final idup checking the length and only duplicating if certain waste threshold is broken, otherwise just doing https://dlang.org/phobos/std_exception.html#assumeUnique (or a cast to string). The result is unique either way. Threshold could be relative for short strings and absolute for long ones. Makes little sense reallocating if you only waste a couple bytes, but makes perfect sense if you've just removed pages and pages of semicolons ;) Be interesting to see if this thread does evolve into a SIMD search...
Re: How to loop through characters of a string in D language?
On Wednesday, 8 December 2021 at 22:18:23 UTC, forkit wrote: It's also worth noting the differences in compiler output, as well as the time taken to compile, these two approaches: (1) string str = "abc;def;ab".filter!(c => c != ';').to!string; (2) string str = "abc;def;ab".replace(";", ""); see: https://d.godbolt.org/z/3dWYsEGsr You're passing a literal. Try passing a runtime value (e.g. a command line argument). Also, -O2 -release :) Uless, of course, your goal is to look at debug code.
Re: Any workaround for "closures are not yet supported in CTFE"?
On Wednesday, 8 December 2021 at 08:07:59 UTC, Petar Kirov [ZombineDev] wrote: ```d interface ICallable { void opCall() const; } alias Action = void delegate(); struct A { Action[] dg; } ``` At this point why not just call a spade a spade and store an array of ICallables directly? :) I mean, why store fat pointers to fat pointers?
Re: Mixin template overloads not working
On Friday, 3 December 2021 at 10:42:37 UTC, Rumbu wrote: Bug or feature? Is there any workaround? The error message explains what to do :) Error: class `mixinover.AnotherVisitor` use of `mixinover.Visitor.visit(S s)` is hidden by `AnotherVisitor`; use `alias visit = Visitor.visit;` to introduce base class overload set
Re: sleeping vs sched_yield
On Thursday, 2 December 2021 at 23:29:17 UTC, Chris Katko wrote: there's: ```d import core.thread; Thread.sleep( dur!("msecs")(10) ); ``` but what if you want to simply yield all remaining time back to the time scheduler? Is there a D std.library accessible version of POSIX sched_yield: There's https://dlang.org/phobos/core_thread_osthread.html#.Thread.yield It seems I can (thanks to the amazing work of D community) simply do: ```d extern(C) int sched_yield(void); // #include ``` however, how does the linker know I need and not some local library, or SDL library, or SDL2.0 library, etc. Shouldn't I be specifying the library somewhere? Linker doesn't need sched.h. Like H.S.Theoh said, it'll look for that symbol in libraries you're linking against. sched_yield is in libc, and by default you do link against that. ``` source/app.d(226,16): Error: cannot have parameter of type `void` ``` Should that be corrected in the compiler? Shouldn't () and (void) be interchangeable as long as you're not doing void*? No: https://dlang.org/articles/ctod.html#funcvoid
Re: bool empty() const for ranges
On Friday, 26 November 2021 at 10:44:10 UTC, Salih Dincer wrote: * Is the const essential for ranges? * Is it possible to rewind the pointer (```Node * head;```) when my head is empty by the const? `empty` is not required to be `const`, but it is required to yield the same result if called multiple times without mutating the range (see https://dlang.org/phobos/std_range_primitives.html#.isInputRange). In other words, you really ought not to mutate the range in implementation of `empty`, or at least not to the extent you seem to want to.
Re: Include .def definition file information for the linker into a .d source file
On Thursday, 25 November 2021 at 09:00:52 UTC, Imperatorn wrote: What most ppl do in that case is to just provide a script, for example build.cmd that just does what it needs. The user just clicks the script and it does everything for them. "How can I make it so that I don't need an extra file written in another language?" "Just add yet another file written in yet another language". Nice going there :) Build scripts never have been scalable. A good language shall only require a compiler and source file(s). No extra voodoo mumbojumbo. This is why we have all those pragmas and the -i switch.
Re: Any additions for write-to-file short program
On Thursday, 18 November 2021 at 22:20:48 UTC, pascal111 wrote: In next program that rewrites original written texts into new files, I see that it may need some additions or we can accept it like this because it's just a simple program that achieve its task and doesn't need any philosophical additions. If "the task" is to copy a file, then this program, as presented, may fail at it. If you're going to do any exception handling at all, a question must be answered: what to do in case the algorithm is interrupted before completing? I.e. if the `while` loop throws an exception, which it can do on any line except for braces. Is it acceptable to leave the output file containing only part of input data, perhaps even no data at all? Or should you catch the exception and delete the output file? Will that even be possible?..
Re: using __traits to get line number of a member
On Sunday, 14 November 2021 at 04:05:45 UTC, forkit wrote: However, there is no isClass method. Why not? How do I determine if a member is a class.. I wonder... ``` static if (is(something == class)) { /* ... */ } ``` or, if member is an instance ``` static if (is(typeof(something) == class)) { /* ... */ } ``` Ditto for interfaces, structs, unions.
Re: using __traits to get line number of a member
On Saturday, 13 November 2021 at 08:04:56 UTC, forkit wrote: int i; foreach(m; __traits(allMembers, mixin(__MODULE__))) // ... __traits(getLocation, mixin(m))[1]); What you really should be doing is this: ```d static import mod = mixin(__MODULE__); foreach (i, name; __traits(allMembers, mod)) { // ... __traits(getLocation, __traits(getMember, mod, i)); // ... } ``` Otherwise you might run into name conflicts, and get location of a wrong symbol. Also if you really want to be generic you should couple it with `__traits(getOverloads)`, like the docs for getLocation suggest.
Re: using __traits to get line number of a member
On Saturday, 13 November 2021 at 05:31:51 UTC, forkit wrote: Code below is self explanatory. Any assistance on how to get the line number is welcome ;-) https://dlang.org/spec/traits.html#getLocation That?
Re: Completing C code with D style
On Thursday, 11 November 2021 at 22:10:04 UTC, forkit wrote: It's called 'staged learning'. Staged learning is the only way for humans to learn, due to the limitations of the human cognitive system. Specifically, the way short-term memory and long-term memory facilitate learning. Those who lack this understanding of how humans learn, tend to throw too much at novices. Like making a simple program do a bunch of extra work for literally no reason? Also, this apparent drive towards requiring novices to understand the implications of their code, in terms of optimising the assembly that gets produced, is just nonsense. They'll never get pass the for loop! This has nothing to do with "optimising the assembly".
Re: Completing C code with D style
On Thursday, 11 November 2021 at 21:56:19 UTC, Ali Çehreli wrote: On 11/11/21 11:34 AM, Stanislav Blinov wrote: > Pessimization, though, is laughably easy, and > should be avoided at all costs. I am not passionate about this topic at all and I am here mostly because I have fun in this forum. So, I am fine in general. However, I don't agree that pessimization should be avoided at all costs. I like D because it allows me to be as sloppy as I want to fix my code later on when it really matters. And when is that? And why is it not now? You mean prototyping? You can do that in any language, not sure what's special about D here. Sure, prototype away. No one gets everything right in a single keystroke. > Not caring about *that* is just bad engineering. There wasn't a problem statement with the original code. So, we understood and valued it according to our past experiences. For example, most of us assumed the program was about 10 integers but I am pretty sure that array was just an example and the program was meant to deal with larger number of arrays. What difference does that make? You still don't want to do any unnecessary work, whether you're dealing with one puny array or a million of them. Another example is, you seem to value performance over maintainability because you chose to separate the selection letters without getting any programmatic help from any tool: I didn't "choose" that. That's Siarhei Siamashka's version, fixed up to use `each` instead of `map!text.join`, because latter serves no useful purpose. That is a weird comparison anyway. Performance OVER maintainability? There's nothing "more performant" or "less maintainable" in the input handling code, as it's the same as original. write("Would you like in list (e=evens, o=odds, b=both)? "); readf(" %c", &even); if ((negativity == 'b') && (even == 'b')) For example, the 'b's in that last line may be left behind unmodified if someone changes the help text alone. Let me see if I get this straight now... are you seriously talking about protecting against this program being altered by a goldfish? Because in that case, I'd best not write any code altogether. Someone someday may put an extra semicolon somewhere, the thing would stop compiling, and I'll be totally ruined. ...Perhaps let's actually stay on this planet? Someone may find that kind of coding "bad engineering" that shoul be avoided at all cost. Sure. Someone definitely may. It'd certainly be nice to decouple input from logic. That doesn't take 14 times more code and AAs to do though. Just sayin' ;) (Not to defend myself but my associative array was exactly because I could not bring myself to separate those selection letters from the help text. I simply could not show unmaintainable code to a beginner.) The original UI code is four lines. Four. Not fool-proof, input's not even validated. But four lines. Yours is fifty five, just to construct and present the UI and read input. Consequently, original program is about 14 times easier to maintain than yours. What did I miss?
Re: Completing C code with D style
On Thursday, 11 November 2021 at 00:11:07 UTC, H. S. Teoh wrote: It depends on what you're doing. In the OP's example, yeah worrying about allocations is totally blowing things out of proportions. But that's the thing. How would one ever learn to know where that dividing line is if all the learning material they see teaches them the opposite - to not know or care? 'Twas a simple task: traverse an array and print numbers out of it based on a predicate. That is all the original program did. How does doing (LOTS) more than that make any of it easier to understand, let alone equivalent to execute? forkit says: "if I was writing millions of processes across 1000s of servers..." No. Just... no. If I've only ever written "convenient" pessimized code, I won't magically start lighting up those wasted transistors just because I got a new job. I'll just be writing the same "convenient" pessimized code, only it would now span 1000s of servers. Which is the exact effing situation that we're in already!
Re: Completing C code with D style
On Wednesday, 10 November 2021 at 23:15:09 UTC, forkit wrote: On Wednesday, 10 November 2021 at 22:17:48 UTC, russhy wrote: On Wednesday, 10 November 2021 at 06:47:32 UTC, forkit wrote: btw. My pc has 24GB of main memory, and my CPU 8MB L3 cache. So I really don't give a damn about allocations .. not one little bit ;-) Having the right mindset helps not make these mistakes in the future Changing habits is hard, make sure to train yourself to pick the right one, early if possible Umm.. you kinda missed the last part of my post... ..where I said..'Now if I were running a million processes across 1000's of servers, I probably would give a damn.' Your CPU executes code speculatively, and in parallel. That's just the way it is, it's how the machine works. Therefore, you simply cannot afford to NOT think about that. You're just wasting your machine time if you're not caring about that. Consequently, you're wasting your time, someone else's time, and, well, money. No, it's not a million processes across 1000s of servers, it's at least two processes across n cores, each of which has m ALUs. (At least two because the OS is involved). But it's two processes from you, two processes from me, four from the other guy, and pretty soon you have a monster that struggles to utilize even a tenth of your machine. All because "I'll care about it tomorrow". C'mon... nothing in my code was 'unacceptable' in terms of speed or efficiency. Making code transformations to improve speed and efficieny are important, but secondary. A newcomer cannot improve code that they do not understand ;-) Yes, optimization is hard. Pessimization, though, is laughably easy, and should be avoided at all costs. "I don't care" is the number 1 reason for the atrocious situation with software that we're in right now. And people tend to come up with all sorts of ridiculous excuses, but most of them, distilled, do amount to "I don't care". My phone is a thousand times faster, and has two million times more memory, than the thing that guided Apollo 11 to the Moon. And yet it sometimes takes longer to react to my keystrokes than roundtrip for a radio signal to the Moon *and* back. My desktop is two times faster, and has eight times more memory, than my phone. But it consistently takes THREE TIMES the roundtrip of a radio signal to the Moon and back to start Visual Studio. Heck, it will take longer than the roundtrip of a radio signal to the Moon and back to post this message after I hit "Send". And I'm reasonably certain this news server is not on the Moon. This all is, plainly, ridiculous. Picking understandable code first, IS right. No. "Understability" is subjective. Show me some code in Scala or Fortran, I won't make heads or tails of it, even though it may be perfectly obvious to the next guy who also never saw either language. What's "right" is writing code that doesn't perform, or cause, any unnecessary work. It may not be fast, but at least it won't be slow for no reason. In any case, I say again, this thread is not about writing performance code per se, but about presenting code to new-comers, that they can make some sense of. And how does invoking extra work help with that? Coupled with not even explaining what that extra work is and why it is there? Taking some C code, and writing/presenting it in D (or vica-versa) in such a way that you can longer make any sense of it, is kinda futile. Original C code from the first post can only fail on I/O, which is arguably out of your control. And the meat of it amounts to 10 conditional stores. Your implementations, in both C and D, are a very, very far distance away from that. Like I mentioned before, the whole algorithm can already complete even before a single `malloc` call starts executing. Not caring about *that* is just bad engineering. If you're writing C, or D, you're not writing pulp fiction for the masses. There are other languages for that.
Re: Wrong result with enum
On Thursday, 11 November 2021 at 09:11:37 UTC, Salih Dincer wrote: Unless explicitly set, default type is int. 110 is greater than int.max. 11 ```d enum w = 100_000; size_t b = w * w; // size_t b = 10 * 10; // ??? assert(b == 10_000_000_000); // Assert Failure ``` The w!(int) is not greater than the b!(size_t)... That code is ``` size_t b = int(w) * int(w); ``` That is, `multiply two ints and assign result to a size_t`. Multiplication of two ints is still an int though, and you can't fit ten billion in an int, so that's overflow. It doesn't matter that you declare `b` as `size_t` here. Overflow happens before that assignment.
Re: Wrong result with enum
On Thursday, 11 November 2021 at 05:37:05 UTC, Salih Dincer wrote: is this a issue, do you need to case? ```d enum tLimit = 10_000; // (1) true result enum wLimit = 100_000; // (2) wrong result ``` https://dlang.org/spec/enum.html#named_enums Unless explicitly set, default type is int. 110 is greater than int.max.
Re: Completing C code with D style
On Wednesday, 10 November 2021 at 06:47:32 UTC, forkit wrote: btw. My pc has 24GB of main memory, and my CPU 8MB L3 cache. So I really don't give a damn about allocations .. not one little bit ;-) That's not the point. The point is the program is doing unnecessary non-trivial work while introducing additional failure paths. It certainly has ways to go to reach Ali's AA solution, but still... To put things in perspective, the algorithm can easily complete before malloc even returns (heck, before it even starts executing). There's what, 11 cmovs at most? It would take several dozen instructions, a couple of loops and a few other branches just to find malloc when you first call it. Not to mention it itself making that syscall and setting up its bins... And I'm not even talking about optimization. Just, uh, non-pessimization.
Re: Completing C code with D style
On Tuesday, 9 November 2021 at 11:03:09 UTC, forkit wrote: They both produce exactly the same output. But do vastly different things. But I tell ya.. the cognitive load .. well.. it increased dramatically ;-) Of course it did. Cuz you overthunk it. Dramatically. Your D version allocates memory, for no good reason. I mean, to store results, but you already have storage for them, so kinda pointless. Your C version, OTOH, stores results on stack (so again, why did you allocate for them in D?..), but allocates some "string builder" for... what, exactly? The program is filter, or sort + partition. Requires 0 allocations in C or D.
Re: auto ref function parameter causes that non copyable struct is copied?
On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote: ``` auto gen() { Foo f; // <--- this one f.n = 42; return value(f.move()); } void main() { Foo f; f = gen().unwrap.move; } ``` ~this(0) ~this(0) ~this(0) ~this(42) <- this is a copy (that shouldn't exist) being destroyed ~this(0) ~this(42) Is it a copy? I think the first destructor call is one of `f` in `gen` (marked by the comment above)
Re: How do I assign attributes of a function to another function?
On Friday, 5 November 2021 at 06:19:16 UTC, Li30U wrote: ...e.g. ```d // ... mixin ("ReturnType /*...snip...*/ " ~ member ~ "()(Parameters! /*...snip...*/ ``` Note the `()` before parameter list. This would make your member function a function template, for which attributes will be inferred by the compiler based on the calls you make in the function body. Of course, making it a template like this makes it non-composable with that same type as you're only inspecting functions, so you wouldn't be able to do e.g. a Group!(Group!(A, 3), 4);
Re: How do I assign attributes of a function to another function?
On Friday, 5 November 2021 at 06:19:16 UTC, Li30U wrote: I am creating a templated object that is a storehouse for a heap object and executes their methods and returns an array of results. With the help of a template, I want to achieve this, but I want to assign the same attributes to the function. How can one pass the attributes of a function to another function? There's https://dlang.org/spec/traits.html#getFunctionAttributes . Or you could define your functions as function templates, letting the compiler infer attributes. Especially as it looks like you function's attributes may not be made the same as the ones you defer to: since you're allocating with the GC, your function cannot be @nogc even if a deferred one can.
Re: Completing C code with D style
On Wednesday, 3 November 2021 at 00:50:51 UTC, Siarhei Siamashka wrote: !text.join("\n").writeln; Ahem... You've turned a program that does not allocate to a program that allocates who knows how much memory? And Ali... associative arrays? For this? What are you trying to teach the good beginner here? :D ```d import std.stdio, std.algorithm; void main() { auto numbers = [-3, 14, 47, -49, -30, 15, 4, -82, 99, 26]; char negativity, even; write("Would you like in list (n=negatives, p=positives, b=both)? "); readf(" %c", &negativity); write("Would you like in list (e=evens, o=odds, b=both)? "); readf(" %c", &even); if ((negativity == 'b') && (even == 'b')) { // don't do any unnecessary work numbers.each!writeln; } else { numbers.filter!(x => !((negativity == 'n' && x > 0) || (negativity == 'p' && x < 0))) .filter!(x => !((even == 'e' && (x % 2)) || (even == 'o' && !(x % 2 .each!writeln; } } ```
Re: Does associative array change the location of values?
On Saturday, 30 October 2021 at 22:47:57 UTC, Elronnd wrote: If the GC were moving, it would also have to move the pointers you took to AA elements. You would never get stale pointers in any event. Who said you would?..
Re: Does associative array change the location of values?
On Saturday, 30 October 2021 at 20:19:58 UTC, Imperatorn wrote: https://dlang.org/spec/garbage.html#pointers_and_gc What test could be written to verify the behaviour? Assuming the GC was moving? You'd need a loop allocating different sizes, storing the addresses somewhere the GC won't see (i.e. in memory allocated not with the GC: malloc, VirtualAlloc, mmap...), orphaning some allocations, repeating a bunch of times, and then comparing addresses of remaining allocations with stored ones. Behavior would very much depend on the GC implementation, so would a concrete test. Point is, it's allowed to move so we have to assume it would even if it doesn't, and relying on it not moving (i.e. depending on concrete addresses) is UB.
Re: Does associative array change the location of values?
On Saturday, 30 October 2021 at 18:31:16 UTC, Andrey Zherikov wrote: I did small test and it printed the same values three times so even rehash doesn't change the address of the value: So it seems pretty safe to store a pointer to a value in AA. And I agree that this should definitely be documented. Address itself may change though. While the AA won't move stuff around, a GC might. I don't think current GC moves anything, but it's definitely allowed to. Which would be transparent to your code so long as you don't depend on the value of address itself :) https://dlang.org/spec/garbage.html#pointers_and_gc
Re: Does associative array change the location of values?
On Saturday, 30 October 2021 at 17:45:57 UTC, Steven Schveighoffer wrote: You said "deallocating unreferenced elements". I thought you meant elements unreferenced by the AA. Yup, I misunderstood you :) What I mean is, the AA isn't going to change implementations where it now deallocates values that may still have existing references. If that's the case, we can state that in the docs. e.g.: Removing a key does not deallocate the value that was removed. The value's lifetime is managed by the GC and will be alive until there are no references to that value. :whateveritistodoathumbsuphere:
Re: Does associative array change the location of values?
On Saturday, 30 October 2021 at 16:55:03 UTC, Steven Schveighoffer wrote: auto v = k in aa; aa.remove(k); How can the GC/compiler work out that there is still a reference? ??? The same way it does for all other references. I think either you misunderstood me, or I misunderstood you.
Re: Does associative array change the location of values?
On Saturday, 30 October 2021 at 11:59:15 UTC, Steven Schveighoffer wrote: It should be documented. There isn't a valid way to remove these requirements, even if they are currently just an implementation detail -- code already depends on these properties. And D is a GC-based language, especially when using AAs. There is no reason to introduce undefined behavior for existing usage. You won't introduce UB by deallocating unreferenced elements, which a given GC *may* be able to figure out. Therefore I object to "AAs do not deallocate the key/value pairs ever" part. Strongly :) Until such time that such a requirement is indeed set in stone, and not incidental.
Re: Does associative array change the location of values?
On Friday, 29 October 2021 at 21:00:48 UTC, Steven Schveighoffer wrote: This is incorrect, the buckets are each heap allocated. Just the array of bucket pointers would change. In addition, AAs do not deallocate the key/value pairs ever. You are safe to obtain a pointer to a value and it will stay there, even if you remove the key. Who's going to document these implementation details? ;) I mean, if no one, then the above shouldn't be stated. Wouldn't you agree? Given the premise of the question at hand, it does seem useful to know these. But at least one should stress what is and isn't subject to change (even if unlikely).
Re: Linker issues with struct postblit
On Friday, 29 October 2021 at 11:05:14 UTC, Imperatorn wrote: On Thursday, 28 October 2021 at 01:39:10 UTC, Thomas Gregory wrote: I am a maintainer of the [dhtslib](https://github.com/blachlylab/dhtslib) package and I have been running into issues with a new implementation of reference counting we are using. [...] Postblit? https://dlang.org/spec/struct.html#struct-postblit
Re: Bitfileds Error: no identifier for declarator
On Thursday, 28 October 2021 at 05:20:35 UTC, data pulverizer wrote: I am trying to compile the following items: struct sxpinfo_struct { mixin(bitfields!( // ... uint, "debug",1, // ... } ``` But I get the error... `debug` is a language keyword, try a different one, like "debug_". That error message though, much wow.
Re: What's the point of static arrays ?
On Friday, 10 July 2020 at 10:13:23 UTC, wjoe wrote: So many awesome answers, thank you very much everyone! Less overhead, Using/needing it to interface with something else, and Efficiency are very good points. However stack memory needs to be allocated at program start. I don't see a huge benefit in allocation speed vs. heap pre-allocation, or is there? Stack is allocated by the OS for the process when it's started. Reserving space for stack variables, including arrays, is effectively free, since the compiler assigns offsets statically at compile time. I mean 1 allocation vs 2 isn't going to noticeably improve overall performance. A GC allocation is way more complex than a mere bump-the-pointer. If your program is trivial enough you may actually find that one extra GC allocation is significant in its runtime. Of course, if you only ever allocate once and your program runs for ages, you won't really notice that allocation. a[] What happens here exactly ? This: int[10] a; int[] slice = a[]; assert(slice.ptr == &a[0]); assert(slice.length == 10); assert(a.sizeof == 10 * int.sizeof);// 40 assert(slice.sizeof == (int[]).sizeof); // 16 on 64 bit I read the chapters in Ali's book (thank you very much for such a great book, Ali) on arrays and slicing prior to asking this question and I came to the following conclusion: Because a static array is pre-allocated on the stack, doesn't have a pointer/length pair, is addressed via the stack pointer, and due to the fact that a slice is a pointer/length pair and because a slice is technically the meta data of a dynamic array, a view into (part) of a dynamic array, No. A slice is just a pointer/length pair - a contiguous view into *some* memory, regardless of where that memory came from: void takeASlice(scope void[] data) // can take any slice since any slice converts to void[] { import std.stdio; writefln("%x %d", data.ptr, data.length); } int[10] a; takeASlice(a); // a[] takeASlice(a[1 .. $-1]); // a[1 .. 9] struct S { float x, y, z; float dx, dy, dz; } S s; takeASlice((&s)[0 .. 1]); // Slicing a pointer, not @safe but can be done. takeASlice(new int[10]); // Array, GC allocation takeASlice([1, 2, 3, 4]); // Array literal, may or may not be GC-allocated `takeASlice` has no knowledge of where the memory came from. Dynamic arrays only ever come into the picture if you try to manipulate the slice itself: resize it, append to it, etc. that it's not possible to slice a static array because the slice would technically be akin to a dynamic array and hence be incompatible. Incompatible to what? int[10] a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; a[0 .. 2] = a[2 .. 4]; assert(a[0] == 3); assert(a[1] == 4); int[10] b = void; b[] = a[]; assert(b == [3, 4, 3, 4, 5, 6, 7, 8, 9, 10]); struct SuperSpecializedArray(T, size_t S) if (S > 0) { T[S] elements; struct SuperSpecializedArrayRange { typeof(elements) e; this(SuperSpecializedArray a) { e = a.elements; // copies } // ... } } Upon creation of a SuperSpecializedArrayRange, the array is copied, but more importantly, data which may not ever be needed is copied and that's supposed to be a big selling point for ranges - only ever touching the data when it's requested - am I wrong ? Ranges need not be lazy. They can be, and most of them should be indeed, but they need not be. And, as you yourself point out, in your case `e` can just be a slice, and your range becomes lazy.
Re: How to ensure template function can be processed during compile time
On Wednesday, 8 July 2020 at 20:11:05 UTC, IGotD- wrote: int v; enum sz = mySize!int // works, returns 46 enum sz2 = mySize(v) // doesn't work. Error: variable v cannot be read at compile time Here we have a difference between C++ and D as C++ was able infer the size of v during compile time. To add to other respondents' replies, you can pass something that is known at compile time, for example the .init value: int v; enum sz2 = mySize(v.init); static assert(sz2 == 46); This way the compiler is able to evaluate `mySize` at compile time. Or use an alias template argument: auto mySize(alias v)() { return v.sizeof + 42; } int v; enum sz = mySize!int; enum sz2 = mySize!v; static assert(sz == sz2); static assert(sz == 46);
Re: constructing labels for static foreach inside switch inside foreach
On Wednesday, 8 July 2020 at 02:06:01 UTC, Steven Schveighoffer wrote: Seems simple enough, except that this inner portion is unrolled, and if I have more than one type to run this on, I already have an "innerloop" label defined. Is there a way to define a label using a mixin or something? or do I have to wrap this in a function? Is there another way to approach this? Can't you put a single label after your outer foreach and goto it?
Re: opApply and attributes
On Tuesday, 7 July 2020 at 13:33:41 UTC, Paul Backus wrote: You can make opApply a template: int opApply(Dg)(Dg dg) if (is(Dg : scope int delegate(ref E))) { // etc. } Because `scope int delegate(ref E) @safe` implicitly converts to `scope int delegate(ref E)`, this version will accept both @safe and non-@safe delegates. (And likewise for the other function attributes.) Yeah, but unfortunately then this won't work: foreach(elem; test) { assert(elem == key); } you'd have to spell out the types for `elem`.
Re: BetterC Bug? Intended Behavior? Asking Here As Unsure
On Monday, 6 July 2020 at 20:06:51 UTC, Kayomn wrote: Something discovered in the D Language Code Club Discord server with the help of Wild is that the following code: struct Test { ~this() {} } void tester(Test test, Test[] tests...) { } extern(C) void main() { tester(Test(), Test()); } Raises the "TypeInfo cannot be used with ~betterC" error. It seems to be due to an inclusion of both the destructor and the non-vararg and vararg argument matching from testing. Anyone know a way around this without resulting to the rather hacky solution of just having 1 argument and always assuming that at least 1 argument is present? Here is a code demo setup for demonstrating the potential problem: https://run.dlang.io/is/A6oIpl This seems to compile: struct Test { ~this() {} } void tester(size_t n)(Test[n] tests...) if (n > 0) {} extern(C) void main() { tester(Test(), Test()); } No assumptions, though `tester` does become a template. I'd say the original error should be reported on bugzilla, if it isn't already; if only for the error message which is ridiculously obscure.
Re: Print only part of a stack trace
On Wednesday, 1 July 2020 at 18:30:15 UTC, Dennis wrote: I have a function that checks a global error constant of a C library (OpenGL) like this: ``` void assertNoOpenGLErrors() { if (glGetError() != GL_NO_ERROR) { assert(0); // stack trace points to here instead of caller } } ``` And I would like to rewrite it to this: ``` void assertNoOpenGLErrors() { if (glGetError() != GL_NO_ERROR) { print(getStackTrace().filterTrace()); exit(); } } ``` void assertNoOpenGLErrors(string file = __FILE__, int line = __LINE__, string func = __PRETTY_FUNCTION__) { if (glGetError() != GL_NO_ERROR) { print(file, ":", line, ":", func, ": blah"); exit(); } } :)
Re: Progress printing with threads?
On Wednesday, 1 July 2020 at 07:52:28 UTC, AB wrote: Hello. I am unsure how to proceed about printing progress in my program. Is it a good idea to std.concurrency.spawn a new thread?.. This example code shows my situation: MmFile input = new MmFile(/* ... */); ulong fileSize= input.length; for (ulong i = 0; i < fileSize; ++i) { // ... } If you can only update the progress between iterations I don't see why you would use threads here. A timer should suffice: import std.datetime.stopwatch; MmFile input = new MmFile(/* ... */); ulong fileSize= input.length; autosw = StopWatch(AutoStart.yes); for (ulong i = 0; i < fileSize; ++i) { // ... if (sw.peek >= 2.seconds) { writefln("Progress: %5.2f%%", i*100.0/fileSize); sw.reset; } }
Re: idiomatic output given -preview=nosharedaccess ,
On Tuesday, 30 June 2020 at 20:04:33 UTC, Steven Schveighoffer wrote: The answer is -- update Phobos so it works with -nosharedaccess :) Yeah... and dip1000. And dip1008. And dip... :)
Re: Privatize a few members to allow messing with them #11353
On Tuesday, 30 June 2020 at 19:58:05 UTC, matheus wrote: +loc.linnum = loc.linnum + incrementLoc; This works because it was declared: void linnum(uint rhs) { _linnum = rhs; } Right? Almost. Given these definitions: @safe @nogc pure @property { const uint linnum() { return _linnum; } void linnum(uint rhs) { _linnum = rhs; } } This: loc.linnum = loc.linnum + incrementLoc; is rewritten as: loc.linnum(loc.linnum() + incrementLoc);
Re: Privatize a few members to allow messing with them #11353
On Tuesday, 30 June 2020 at 19:42:57 UTC, matheus wrote: in this case this was more a style thing than anything else right? Or is there something I'm not able to see? Before the change, linnum and charnum are public variables, one can do a += on them. After the change, they become properties accessing, as the PR says, private variables: @safe @nogc pure @property { const uint linnum() { return _linnum; } const uint charnum() { return _charnum; } void linnum(uint rhs) { _linnum = rhs; } void charnum(uint rhs) { _charnum = rhs; } } ...with which the += won't work (at least this variant, as the getter isn't returning ref).
Re: scope guard question
On Monday, 29 June 2020 at 22:31:12 UTC, Arjan wrote: So when no inner scope is present, the scope exit 'runs' after the return? Is that indeed expected behavior according to the specification? Yes. A scope ends at the '}'. Destructors and scope guards execute then, after the return.
Re: [DIP1000] Something I don't quite understand regarding 'scope'
On Monday, 29 June 2020 at 06:21:43 UTC, ag0aep6g wrote: Since `local` and `writeln` are templates, the attributes for their parameters are inferred from their bodies. `local!(int*)` doesn't do anything with the parameter, so it's inferred as `scope`. `writeln!(int*)` apparently does something that prevents `scope` from being inferred. Thanks. It would appear indeed that inference fails for some reason. Explicitly marking args as 'scope' for `writeln` and `File.write` lets them compile. I wonder if there's a way to find exactly what it is in either of those that prevents the compiler from inferring 'scope'.
Re: reference variables don't exist, but can simulate them
On Monday, 29 June 2020 at 02:11:15 UTC, NonNull wrote: Deprecation: Cannot use alias this to partially initialize variable j of type refer. Use j._() This is for the line j=3 What is this about? Where does this hidden rule come from? That one comes from [1]. But there are quite a few more "hidden" rules that you're violating here. Try putting @safe on your main and compiling with -preview=dip1000 (for dmd, refer to your compiler's help if you're using others). The bulk of escape analysis is only done for @safe, and only with that DIP enabled (IIRC only some trivial checks are done otherwise). [1] https://issues.dlang.org/show_bug.cgi?id=19441