Re: Minimize GC memory footprint
On Wednesday, 3 February 2021 at 13:37:42 UTC, frame wrote: I have to deal with GC as long I want to use other libraries that are relying on it or even just phobos. Conclusion so far (for Windows): 32bit: - GC just doesn't work at all ?? Do you mean no collections happen? 32bit GC should just work. 64bit: - Collections are rare. It can be necessary to call GC.collect() manually. - Scope guards to explicit clean up / free memory at function exit have no deep impact on most cases. - If your application should save memory call GC.minimize() when it's appropriate. It seems that calling GC.enable() if it's already enabled just disables the automatic GC again? Is this a bug? I cannot reproduce it outside my application yet since it's not clear when the GC starts collecting, but it always shows the same behaviour: // GC.enable(); Case A: The app is very kind in memory usage (~20 MB) GC.enable(); Case B: The app is consuming huge amount of memory (~900 MB) GC.disable(); GC.enable(); Case A again GC.disable(); GC.enable(); GC.enable(); Case B again That looks like a bug indeed. I also have to struggle what the specs' text actually mean: This function is reentrant, and must be called once for every call to disable before automatic collections are enabled. I think it means that you need to make sure that enable() is called as many times as disable() is called before collection can happen automatically. — Bastiaan.
Re: Using the Standard Library with C++ Interop
On Friday, 5 February 2021 at 21:40:29 UTC, wolfiesnotfine wrote: In any case, I'm unsure how I would runtime init from C++. Is there a specific function I should call? https://dlang.org/phobos/core_runtime.html#.rt_init Could this be done at compile time in a consteval or constexpr function? This being the runtime, I presume it should be called at run time :-) I haven’t used it, but searching for rt_init should give you some pointers. —Bastiaan
Re: writeln and write at CTFE
On Wednesday, 13 January 2021 at 09:11:53 UTC, Guillaume Piolat wrote: On Wednesday, 13 January 2021 at 08:35:09 UTC, Andrey wrote: Hello all, Tell me please how can I "writeln" and "write" in function that is used in CTFE? At the moment I get this: import\std\stdio.d(4952,5): Error: variable impl cannot be modified at compile time Or may be exist some other ways to do it? pragma(msg, ); This may however not do what you wish it to do: https://forum.dlang.org/post/mailman.4526.1499573493.31550.digitalmars-d-le...@puremagic.com — Bastiaan.
Re: Using a betterC dub package in ordinary D
On Friday, 8 January 2021 at 18:28:36 UTC, Ferhat Kurtulmuş wrote: On Friday, 8 January 2021 at 15:40:12 UTC, Bastiaan Veelo wrote: Hi, When I use earcutd [1] in an ordinary D project, I get a link error for the __D7earcutd12__ModuleInfoZ symbol. [...] Dear Bastiaan, I am not an expert in dub system, but I have just pushed a modification in dub.json. I am not sure if it solves your problem. My modification is "configurations": [ { "name": "default", "targetType": "library" }, { "name": "betterC", "targetType": "library", "dflags": ["-betterC"] } ] now client projects must explicitly pass the subConfiguration parameter to compile it with betterC. Much appreciated Ferhat! This works like a charm. I am kind of surprised that it does, as I expected dvector to need the same treatment. Excellent support by the way, thanks! Off topick, the original js implementation is documented to not generate results that are guaranteed to be correct. I could not find information on what the conditions are that cause deviations, and how large these then can be. Do you have an idea about this or experience with accuracy of the algorithm? I am looking into whether earcutd can replace GLU tesselation. We use the result for engineering purposes (not only visualisation) and correctness is important to us. Thanks! Bastiaan.
Using a betterC dub package in ordinary D
Hi, When I use earcutd [1] in an ordinary D project, I get a link error for the __D7earcutd12__ModuleInfoZ symbol. This is because the earcutd dub.json has `"dflags": ["-betterC"]`. I think this is in error, my understanding of betterC code is that it can be compiled with "-betterC", but does not need to (and must not when used in D context). Am I right? What are the best practices for betterC dub packages? Thanks, Bastiaan. [1] https://code.dlang.org/packages/earcutd
Re: Writing a really fast lexer
On Saturday, 12 December 2020 at 18:15:11 UTC, vnr wrote: On Saturday, 12 December 2020 at 16:43:43 UTC, Bastiaan Veelo wrote: Have you looked at Pegged [1]? It will give you the lexer and parser in one go. I'd be very interested to see how it performs on that kind of input. -- Bastiaan. [1] https://code.dlang.org/packages/pegged Yes, I know Pegged, it's a really interesting parser generator engine, nevertheless, the grammar of what I would like to analyse is not a PEG. But I am also curious to know the performances of this tool for very large inputs. Are you able to share the grammar? Since you plan to parse using recursive descent, I think there is a good chance that the language can be defined as a PEG. I am using it to parse Pascal, whose grammar was defined long before PEG was a thing. — Bastiaan.
Re: Writing a really fast lexer
On Friday, 11 December 2020 at 19:49:12 UTC, vnr wrote: For a project with good performance, I would need to be able to analyse text. To do so, I would write a parser by hand using the recursive descent algorithm, based on a stream of tokens. I started writing a lexer with the d-lex package (https://code.dlang.org/packages/d-lex), it works really well, unfortunately, it's quite slow for the number of lines I'm aiming to analyse (I did a test, for a million lines, it lasted about 3 minutes). As the parser will only have to manipulate tokens, I think that the performance of the lexer will be more important to consider. Therefore, I wonder what resources there are, in D, for writing an efficient lexer. Have you looked at Pegged [1]? It will give you the lexer and parser in one go. I'd be very interested to see how it performs on that kind of input. -- Bastiaan. [1] https://code.dlang.org/packages/pegged
Re: Pass enum variable as const ref arg
On Friday, 4 December 2020 at 12:54:25 UTC, Andrey wrote: Hello, void test(const ref string[3] qazzz) { qazzz.writeln; } void main() { enum string[3] value = ["qwer", "ggg", "v"]; test(value); } Gives errors: It works if you pass `-preview=rvaluerefparam` to the compiler. But the other suggestions are better IMO. —Bastiaan.
Re: Is garbage detection a thing?
On Sunday, 29 November 2020 at 16:05:04 UTC, Mark wrote: Hi, can I ask you something in general? I don't know anyone whom I could ask. I'm a hobbyist with no science degree or job in computing, and also know no other programmers. I have no good understanding why "garbage collection" is a big thing and why "garbage detection" is no thing (I think so). In order to detect garbage, you need extensive run-time instrumentation, the difficulties of which you have indicated yourself. In addition comes that detection depends on circumstance, which is an argument against the debug/release strategy you proposed. There is no guarantee that you’ll find all problems in the debug build. Garbage collection also comes at a runtime cost, but strategies exist to minimise those, and in addition a GC enables valuable language features. One such strategy is to minimise allocations, which improves performance in any memory management scheme. [...] What I don't understand is, when today there exist tools for C++ (allocator APIs for debugging purposes, or Address-Sanitizer or maybe also MPX) to just detect that your program tried to use a memory address that was actually freed and invalidated, why did Java and other languages not stop there but also made a system that keeps every address alive as long as it is used? Elimination of memory problems is much more valuable than detection. Recovering from memory errors at run time is unreliable. One very minor criticism that I have is: With GC there can be "semantically old data" (a problematic term, sorry) which is still alive and valid, and the language gives me the feeling that it is a nice system that way. But the overall behavior isn't necessarily very correct, it's just that it is much better than a corrupted heap which could lead to everything possibly crashing soon. At least in D, you can avoid old data to hang around for too long. See core.memory. Or maybe I could use the safe-c subset in D? But I believe it uses garbage collection. I know nothing about it, sorry. @safe D is not a sub-set, indeed it uses garbage collection. Fact is that there are very few domains where this is a problem. Not all garbage collectors are equal either, so if you think garbage collection is bad in one language, this may not directly apply in another. In D the garbage collector is even pluggable, various implantations exist. Have you seen the GC category on the blog?https://dlang.org/blog/2017/03/20/dont-fear-the-reaper/ BetterC is a subset of D, it does not use garbage collection. You may be interested in current work being done in static analysis of manual memory management in D: https://youtu.be/XQHAIglE9CU The advantage of D is that all options are open. This allows the following approach: 1) Start development without worrying about memory. Should collection cycles be noticeable: 2) Profile your program and make strategic optimisations https://youtu.be/dRORNQIB2wA. If this is not enough: 3) Force explicit collection in idle moments. If you need to go further: 4) Completely eliminate collection in hot loops using @nogc and/or GC.disable. When even this is not enough: 5) Try another GC implementation. And if you really need to: 6) Switch to manual memory management where it matters. This makes starting a project in D a safe choice, in multiple meanings of the word. — Bastiaan.
Re: Can't pass [] to extern function object method
On Wednesday, 18 November 2020 at 10:50:12 UTC, frame wrote: I found the "bug". It was caused by a debug {} statement within a struct method. I assume that the debug symbol is just incompatible called from the DLL context. Were the DLL and main program built in different modes (debug/release)? Then this problem is understandable. Otherwise I find this surprising, and probably worth a bug report? — Bastiaan.
Re: How can execute method in new Thread?
On Saturday, 14 November 2020 at 17:21:15 UTC, Marcone wrote: Error: D:\dmd2\windows\bin\..\..\src\phobos\std\parallelism.d(516): Error: struct `Fruit` does not overload () I think you need to pass the this pointer somehow. This works: import std; struct Fruit { string name; static void printmyname(Fruit thisFruit) { writeln(thisFruit.name); } void showname() { task!printmyname(this).executeInNewThread; } } void main() { Fruit f = Fruit("Banana"); f.showname(); } This does too: import std; struct Fruit { string name; void printmyname() { writeln(name); } void showname() { task!((Fruit me){me.printmyname;})(this).executeInNewThread; } } void main() { Fruit f = Fruit("Banana"); f.showname(); } —Bastiaan.
Re: App hangs, GC.collect() fixet it. Why?
On Monday, 28 September 2020 at 21:58:31 UTC, Steven Schveighoffer wrote: On 9/28/20 3:28 PM, Bastiaan Veelo wrote: I’m leaning towards ditching the memory mapped I/O on the D end, and replace it by regular serialisation/deserialisation. That will be a manual rewrite though, which is a bit of bummer as memory mapped files are widely used in our Pascal code. But this will probably give the best end result. 2 things: 1. I agree this is the answer. If you ever ditch the old Pascal code, then you can reactivate the memory-mapped code. 2. You can possibly do the translation outside of your programs. That is, it wouldn't be entirely impossible to simply have a process running that ensures the "D view" and the "Pascal view" of the same file is kept in sync. Then you can keep the memory mapped code the same, and just define sane structures in your D code. If you aren't required to have both Pascal and D programs reading and writing the file at the same time, this shouldn't be a problem. There is no need to run both versions concurrently. The issue is that design offices typically maintain a library of past designs for as long as they are in existence, to build new designs off of. So being able to read or import the files that were written with an ancient version of our software is very valuable. Our old compiler offered two alternatives for file i/o: one where all elements are of the same type, the other one (memory mapped files) being the "only" option for files of mixed type. Ideally, the structs that are used for i/o do not have any pointers in them, and certainly in the more recent file versions that would be the case. In older versions that might not be the case; then the pointers obviously would be given meaningful values after the structs would have been read back in. These cases we would be able to work around, though, by converting the old structs to new ones upon import. BTW, one further thing I don't understand -- if this is memory mapped data, how come it has issues with the GC? And what do the "pointers" mean in the memory mapped data? I'm sure there's good answers, and your actual code is more complex than the simple example, but I'm just curious. The main problem is that the transpiler doesn't know which structs are used for i/o and would need 1-byte alignment, and which structs have pointers into GC memory and must not be 1-byte aligned. The alternative to switching to serialisation/deserialisation is to stay with the automated translation of the memory mapped file implementation, not automatically 1-byte align every struct but manually align the ones that are used in i/o. This is however sensitive to mistakes, and the translated mmfile implementation has a bit of a smell to it. It is also not portable, as it uses the WinAPI directly. Still, it may be the quickest route to get us back on track. I am very glad to have identified the problem, and there being ways to deal with it. I just hope this will be the last big hurdle :-) -Bastiaan.
Re: App hangs, GC.collect() fixet it. Why?
On Monday, 28 September 2020 at 15:44:44 UTC, Steven Schveighoffer wrote: On 9/28/20 8:57 AM, Bastiaan Veelo wrote: I am glad to have found the cause of the breakage finally, but it won't be easy to find a generic solution... Obviously, this isn't a real piece of code, but there is no way around this. You have to align your pointers. The other option is to not use the GC and use manual memory management. If this is a compatibility thing between D and Pascal, and you absolutely have to have the same layout, is there a way to adjust the structure in Pascal? Like put the elements that misalign the pointers at the end of the structure? Another totally drastic approach would be to supply your own even-more-conservative GC which will scan misaligned pointers. Probably going to hurt performance quite a bit. You might be able to get away with marking only certain blocks as having misaligned pointers, but you will have to scan all the stacks with this assumption. Some more information about the setup you are using might help (I'm assuming D and Pascal are using the same memory in the same process, otherwise this wouldn't be a problem). In particular, where does the data come from, and how malleable is it in your system? Are there times where references to the D data only exist in Pascal? -Steve Thanks a lot for thinking with me. I’m not linking any Pascal objects, so I don’t need to maintain binary compatibility in memory; Only compatibility of data files. The problem arises when those files are read using memory mapped files, from which structs are memcpy’d over. This is of course the result of machine translation of the current Pascal implementation. Manual memory management is an option and would be straightforward in principle, as we’ve done that for ages. The only thing is that this memory cannot contain other allocations on the GC heap, such as strings or other slices, unless they are both aligned and their root is registered. Fixing the alignment in Pascal is possible in principle, but any old files would then need to first be processed by the last Pascal version of the programs, which we then would need to keep around indefinitely. There would also be issues when we port from 32 bit to 64 bit. Another option could be to use 1-byte aligned structs for I/O, and copy the members over in default aligned versions. But this cannot be part of the automated transcompilation. Thanks for suggesting a custom gc, which I had not thought of. I’m leaning towards ditching the memory mapped I/O on the D end, and replace it by regular serialisation/deserialisation. That will be a manual rewrite though, which is a bit of bummer as memory mapped files are widely used in our Pascal code. But this will probably give the best end result. -Bastiaan.
Re: App hangs, GC.collect() fixet it. Why?
On Friday, 5 June 2020 at 21:20:09 UTC, Steven Schveighoffer wrote: This kind of sounds like a codegen bug, a race condition, or (worst case) memory corruption. I think it must have been memory corruption: I had not realized that our old Pascal compiler aligns struct members on one byte boundaries, and also uses ubyte as the base type for enumerations (or ushort if required) instead of uint. When using memory mapped files this binary incompatibility likely caused the corruption. But, after correcting that mistake, suddenly things broke that had been working for a long time. Having no idea what could be wrong this time, I spent quite some time dustmiting (thanks Vladimir!) and manually reducing the code. Voilà: import std.stdio; import core.memory; struct Nothing { } struct Info { align(1): ubyte u; Nothing*[2] arr; } Info* info; void main() { info = new Info; writeln("1"); GC.collect(); info.arr[0] = new Nothing; writeln("2"); GC.collect(); info.arr[1] = new Nothing; writeln("info.arr[0] = ", info.arr[0]); writeln("info.arr[1] = ", info.arr[1]); assert(info.arr[0] != info.arr[1], "Live object was collected!"); } (The assert triggers on Windows, not on run.dlang.org.) Unfortunately for me, I cannot blame this on the compiler. It violates the requirements from the spec: "Do not misalign pointers if those pointers may point into the GC heap" (https://dlang.org/spec/garbage.html) I am glad to have found the cause of the breakage finally, but it won't be easy to find a generic solution... -Bastiaan.
Re: Why Pegged action dont not work in this case ?
On Sunday, 19 April 2020 at 16:47:06 UTC, Basile B. wrote: I 've started experimenting Pegged action. Quickly i got blocked by this problem. The start action works where I use the rule but not directly in the rule. I don't understand the difference between how you use "where" and "directly in". Note that semantic actions are executed during the parsing process, even in branches that eventually fail, before the parser back tracks. They are not a substitute for traversing the final parse tree, rather, they are a method for manipulating the parsing process as it happens. That's why `endResultRecord` is executed directly after `(',' Result)*` succeeds, and `beginResultRecord` is executed directly after `ResultRecord` succeeds (even if `'(gdb)'` would not match). Test program: [...] ResultRecord< {beginResultRecord} Token? '^' ResultClass (',' Result)* {endResultRecord} Remove the space between "<" and "{", then it works. Also I'd like to report that actions dont work with partially specialized templates: --- T handleResultRecord(bool end, T)(T t); // then you use handleResultRecord!true and handleResultRecord!false in the PEG. --- That fails for the same reason as `handleResultRecord!true(1)` fails to instantiate. -- Bastiaan.
App hangs, GC.collect() fixet it. Why?
I've been tracking down a hang in our pilot app. Using writeln, it appears to hang at newing a slice. After many hours of trying things, I discovered that program flow would continue past that point when I inserted a call to `GC.collect()` just before. Then it stalled again at a call to Win32 `SetMenu()`. Again, inserting `GC.collect()` before that made the problem go away. This band-aid isn't going to scale in the long run. I feel I'm treating symptoms, and wonder what the cause is. Any ideas? I know the GC is not disabled somehow because if I print `GC.profileStats()`, I see that there are collections even without my explicit calls to `GC.collect()`. Thanks, Bastiaan.
Re: Postblit segfault.
On Monday, 1 June 2020 at 09:42:44 UTC, Boris Carvajal wrote: On Monday, 1 June 2020 at 06:35:36 UTC, MaoKo wrote: Hello, I don't understand why this code segfault on Reduced to: import std.stdio; struct S {} void main() { S[1] s; writeln(s); } This used to work up to dmd 2.084.1. It fails since 2.085.1. Please file a regression report at https://issues.dlang.org/enter_bug.cgi?product=D — Bastiaan.
Re: CT BitArray
On Thursday, 1 November 2018 at 08:50:38 UTC, Bastiaan Veelo wrote: On Thursday, 1 November 2018 at 00:01:04 UTC, Stefan Koch wrote: On Wednesday, 31 October 2018 at 23:14:08 UTC, Bastiaan Veelo wrote: Currently, BitArray is not usable at compile time, so you cannot do ``` enum e = BitArray([1, 1, 1, 0]); ``` This gives /dlang/dmd/linux/bin64/../../src/phobos/std/bitmanip.d(1190): Error: `bts` cannot be interpreted at compile time, because it has no available source code [] meanwhile use module level BitArrays like ``` immutable BitArray e; static this() { e = BitArray([1, 1, 1, 0]); } ``` Note to self: when this occurs, the above error message does not offer a trace to the place where this originates. To get that, temporarily insert the following at the indicated line in bitmanip.d: ``` if(__ctfe) assert(false, "trap"); ``` --Bastiaan.
Re: New with alias
On Tuesday, 10 March 2020 at 06:09:23 UTC, tcak wrote: I write a code as below: auto result = new char[4]; It allocates memory as expected. This is a slice of four chars, which can be used as a dynamic array. Later I define an alias and do the above step: alias Pattern = char[4]; This is an alias for a static array with a fixed length of four chars. auto result = new Pattern; But compiler says: Error: new can only create structs, dynamic arrays or class objects, not `char[4]`'s Is this a bug, or `alias` doesn't work how I was thinking? It is not a bug. You cannot new static arrays. You can do this, though: Pattern pattern; // One static array of four chars. auto patterns = new Pattern[3]; // A slice with three static arrays of four chars. --Bastiaan.
Re: Specify dmd or ldc compiler and version in a json dub file?
On Tuesday, 8 August 2017 at 09:17:02 UTC, data pulverizer wrote: I would like to know how to specify dmd or ldc compiler and version in a json dub file. Update: you can at least specify these in the toolchain requirements section: https://dub.pm/package-format-json.html#toolchain-requirements I myself am looking for ways to satisfy these automatically, using a tool like dvm (https://code.dlang.org/packages/dvm) in preBuildCommands. Bastiaan.
Re: Slice/Substr [0..?lastIndexOf(".")] How refer itself without create a variable?
On Thursday, 5 December 2019 at 11:28:51 UTC, Marcone wrote: Simple example: writeln("Hi\nHow are you?\nGood".splitLines()[0][0..?lastIndexOf(r"\")]); How to refer to this string in lastIndexOf() without create a variable? Thank you. .splitLines[0] already just produces "Hi", containing no "\", so this example is a bit broken. writeln("#", "Hi\nHow are you?\nGood".splitLines()[0], "#"); // #Hi# You could write a function to work around having to declare a variable: string upto(string input, string delim) { return input[0 .. input.countUntil(delim)]; } void main() { writeln(upto("Up to colon: skip this", ":")); // Up to colon writeln("Up to colon: skip this".upto(":")); // Up to colon } You can use a function literal or lambda, but it isn't pretty: writeln((string s){return s[0..s.countUntil(":")];}("Up to colon: skip this")); // Up to colon writeln((s => s[0..s.countUntil(":")])("Up to colon: skip this")); // Up to colon Bastiaan.
Re: const and immutable values, D vs C++?
On Wednesday, 4 December 2019 at 14:44:43 UTC, Ola Fosheim Grøstad wrote: When is there a noticable difference when using const values instead of immutable values in a function body? And when should immutable be used instead of const? f(){ const x = g(); immutable y = g(); ... do stuff with x and y … } There is a difference I guess if g() returns a reference type and is an inout function. immutable y will only work if the reference returned is immutable. Const is a promise to the rest of the code that you will never mutate it. Immutable is a promise by the rest of the code that it will never mutate. Immutable is more powerful, allowing data sharing in overlapping slices and between threads without locks. Const is more versatile, allowing references to data regardless of its mutability. So if g() always returns immutable, it’s best to receive it as such, not const. If it can be either, it must be received as const. I'm comparing D to C++ and I get the following mapping: Does that make sense at all? D’s const is transitive, C++’s is not. Bastiaan.
Re: Unexpected aliasing
On Tuesday, 12 November 2019 at 08:15:20 UTC, Basile B. wrote: I'm curious to know what is the equivalent in Pascal that your transpiler fails to translate since Pascal records don't have constructors at all. Maybe you used an old school 'Object' ? Note that Extended Pascal is not exactly Pascal. An example: TYPE Ints(upperBound) = ARRAY [1 .. upperBound] of Integer; MyRecord = RECORD integers : Ints(5); END; SchematicRecord(num) = RECORD integers : Ints(num); END; IntsPtr = ^Ints; PROCEDURE myProcedure(PROTECTED VAR someArr : Ints); BEGIN writeln(someArr.upperBound); END; PROCEDURE proc; VAR dynamicInts : IntsPtr; rec : MyRecord; BEGIN dynamicInts = new(10); myProcedure(dynamicInts^); myProcedure(rec.integers); END; In this case, only the upper bound of Ints is parameterized, but the lower bound could be parameterized as well. Records can also be schematized. Procedure arguments can take schemas that are undiscriminated, they carry their schemaparameters as properties. Bastiaan.
Re: Unexpected aliasing
On Monday, 11 November 2019 at 21:52:12 UTC, Jonathan M Davis wrote: On Monday, November 11, 2019 12:17:37 PM MST Bastiaan Veelo via Digitalmars- d-learn wrote: [...] I could use some help in rewriting the code below so that arr1 and arr2 each have their own data; ideally with minimal changes so that I can make the transcompiler do the right thing. Thanks! Bastiaan. void main() { import std.stdio; WrapIntegerArray arr1; arr1[0] = 42; WrapIntegerArray arr2; writeln(arr2[0]); // 42, not 0. writeln("arr1.wrap.arr.ptr = ", arr1.wrap.arr.ptr); writeln("arr2.wrap.arr.ptr = ", arr2.wrap.arr.ptr); // identical assert(arr2[0] == 0); // fails } struct IntegerArray { int[] arr; alias arr this; this(int l) { arr = new int[l]; } } struct WrapIntegerArray { auto wrap = IntegerArray(5); // This is CTFE! :-( alias wrap this; } All struct and class members which are directly initialized must have their values known at compile-time. For structs, that's what goes in the init value for the type. A side effect of this is that it's usually a bad idea to directly initialize dynamic arrays which are member variables. You need to do the initialization in a constructor. And for structs, if you need a no-arg constructor, then you'll need to use a factory function (since structs can't have no-arg constructors). e.g. struct WrapIntegerArray { IntegerArray wrap; alias wrap this; this(int len) { wrap = IntegerArray(len); } } or struct WrapIntegerArray { IntegerArray wrap; alias wrap this; static make() { WrapIntegerArray retval; retval.wrap = IntegerArray(5); return retval; } } So, you could then have something like auto arr1 = WrapIntegerArray(5); arr1[0] = 42; or auto arr1 = WrapIntegerArray.make(); arr1[0] = 42; but if you use the init value (which is what you get if you let the type be default-initialized), then you'll have to first do something to allocate the dynamic array if you want to be able to index it, since if you don't give it a value at compile-time, it's null (and you don't want to give it a value at compile-time, because then every default-initialized struct of that type will refer to the same dynamic array). Of course, you could always just append values, and the dynamic array will be allocated and grow accordingly, but that's obviously not the same as allocating it up front to have a specific length. - Jonathan M Davis Thank you Jonathan. A factory function seems to be what I need, then. It'll be an interesting challenge to have my transpiler detect when a factory function is needed, and making sure that they are called at the right places. But this might escalate since structs can have members that are structs that have a factory function. So the enclosing struct also needs a factory function. And so forth. My problem is the translation of so called schematic arrays, a type that I have only seen in Extended Pascal. A schematic array is a type in which the length of the array is a parameter of the type. Extended Pascal does not have dynamic arrays, so schematic arrays are its attempt at improving a bit on just plain static arrays. The length parameter can be constant, in which it behaves akin to templates (which it doesn't have either), but it can also be set at run time during initialization (so I can't translate it to a template). Maybe I can omit the translation of schematic arrays (IntegerArray in this case) altogether and instead detect where and how they are instantiated. Then replace them with a static array whenever the length is known at compile time, and a dynamic array otherwise. A static array is not nice, but at least they can be members of structs without a factory function. Either way, my transpiler needs to smarten up... Bastiaan.
Re: Unexpected aliasing
On Monday, 11 November 2019 at 20:05:11 UTC, Antonio Corbi wrote: Defining and using a constructor for WrapIntegerArray seems to work: void main() { import std.stdio; WrapIntegerArray arr1 = WrapIntegerArray(5); arr1[0] = 42; WrapIntegerArray arr2 = WrapIntegerArray(5); writeln(arr2[0]); // 42, not 0. writeln("arr1.wrap.arr.ptr = ", arr1.wrap.arr.ptr); writeln("arr2.wrap.arr.ptr = ", arr2.wrap.arr.ptr); // identical assert(arr2[0] == 0); // fails } struct IntegerArray { int[] arr; alias arr this; this(int l) { arr = new int[l]; } } struct WrapIntegerArray { this (int v) { wrap = IntegerArray(5); } IntegerArray wrap; alias wrap this; } Hope this helps. Antonio Thanks, Antonio. My problem is that the length of the array should be a built-in property of WrapIntegerArray (immutable in this case); what I'd actually want is a constructor without arguments. Jonathan's suggestion of using a factory function comes closest to that. Bastiaan.
Unexpected aliasing
Recently I got my first surprise with our use of D. The symptom was that two local variables in two different functions appeared to be sharing data. A simplified example is shown below (the original was machine translated from Pascal and involved templates and various levels of indirection). What I did not know is that the initial value of struct members is a compile time feature, apparently. What I suspect is happening is that the array lives in the static data segment (or is created in the module constructor?) and that the slices inside arr1 and arr2 get initialised to point to that same array. I could use some help in rewriting the code below so that arr1 and arr2 each have their own data; ideally with minimal changes so that I can make the transcompiler do the right thing. Thanks! Bastiaan. void main() { import std.stdio; WrapIntegerArray arr1; arr1[0] = 42; WrapIntegerArray arr2; writeln(arr2[0]); // 42, not 0. writeln("arr1.wrap.arr.ptr = ", arr1.wrap.arr.ptr); writeln("arr2.wrap.arr.ptr = ", arr2.wrap.arr.ptr); // identical assert(arr2[0] == 0); // fails } struct IntegerArray { int[] arr; alias arr this; this(int l) { arr = new int[l]; } } struct WrapIntegerArray { auto wrap = IntegerArray(5); // This is CTFE! :-( alias wrap this; }
Re: Saving and loading large data sets easily and efficiently
On Monday, 30 September 2019 at 20:10:21 UTC, Brett wrote: [...] The way the data is structured is that I have a master array of non-ptr structs. E.g., S[] Data; S*[] OtherStuff; then every pointer points to an element in to Data. I did not use int's as "pointers" for a specific non-relevant reason [...] I would seriously consider turning that around and work with indices primarily, then take the address of an indexed element whenever you do need a pointer for that specific non-relevant reason. It makes I/O trivial, and it is safer too. size_t[] OtherStuff; size_t[int] MoreStuff; Bastiaan.
Re: How to use #pragma omp parallel for collapse(n) in dlang?
On Tuesday, 13 August 2019 at 08:41:07 UTC, ijet wrote: How to use #pragma omp parallel for collapse(n) in dlang? I don’t understand the question. Bastiaan.
Re: 1 new
On Friday, 2 August 2019 at 18:25:28 UTC, jmh530 wrote: When I navigate to https://forum.dlang.org/ I have a message that says "1 new reply" to "your posts." Normally, I click on that "1 new reply" and find the post that's new, go to it, and the message disappears. However, it doesn't seem to go away anymore. I tried looking at many different old posts without luck. At one point it was up to "2 new replies," but I viewed that other post and it went back down to "1 new reply." Does anyone else have this? I always have “2 new replies” on that page, no matter how often I take a look. The feature seems a bit broken to me. Bastiaan.
Re: How to get name of my application (project)
On Saturday, 3 August 2019 at 09:26:03 UTC, Andrey wrote: Hello, how to get name of my application (project) that we write in dub.json? Is there any compile-time constant like __MODULE__? The name of an application is not a compile time constant: you can rename the executable at any time. Like Rémy said, thisExePath.baseName will get you the name at run time. Bastiaan.
Re: Help me decide D or C
On Friday, 2 August 2019 at 13:45:17 UTC, Alexandre wrote: On Friday, 2 August 2019 at 12:30:44 UTC, berni wrote: On Wednesday, 31 July 2019 at 18:38:02 UTC, Alexandre wrote: [...] In my oppinion C should have been deprecated about 50 years ago and it's not worth while to learn it if you are not interested in the history of programming or you have to learn it, because you need to maintain software which is allready written in C. But that's my oppinion; others may have a different sight. [...] Could you elaborate more about C being a burden? I have read so many people saying C gives a great foundation and should be everyone's first language. Now I am confused. One example is this recent post: https://forum.dlang.org/post/yjgkatpbkdyyksldg...@forum.dlang.org “[...] recently all the problems I am having with D are because D is actually superior to C and some assumptions I still have because of C should be uninstalled from my brain.” If you plan on ending up with D anyway, I think that learning C first is an unnecessary detour and can be counter productive in some ways. And if your objective is to have fun, I would recommend against C (except for a masochistic kind of fun). Don’t take the detour, take the D tour! :-) Bastiaan.
Re: Help me decide D or C
On Thursday, 1 August 2019 at 20:02:08 UTC, Aurélien Plazzotta wrote: [...] But don't fool yourself, D is not for beginners. Ali Çehreli is a very skilled programmer, ergo, he can't reason like a new/starting programmer anymore, regardless of his patience and kindness. I am sorry, but this is very strange reasoning. Would you recommend a book on programming written by someone who is not a skilled programmer himself in any language? I certainly would not. Besides, the OP has already expressed his appreciation for Ali’s writing. Bastiaan.
Re: 1 - 17 ms, 553 ╬╝s, and 1 hnsec
On Friday, 17 May 2019 at 18:36:00 UTC, ag0aep6g wrote: I'd suggest "17 ms, and 553.1µs" for a better default (1 hns is 0.1 µs, right?). No weird "hnsecs", no false precision, still all the data that is there. I was going to propose the same. Hns is weird. Bastiaan.
Re: Windows / redirect STDERR to see assert messages
On Sunday, 12 May 2019 at 13:39:15 UTC, Robert M. Münch wrote: When developing Windows GUI applications I use: // detach from console and attach to a new one, works for x86 and x86_64 FreeConsole(); AllocConsole(); freopen("CONIN$", "r", stdin); freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); so that the GUI app opens a console for writeln() output etc. I assumed this should work for assert() messages as well. But it seems it doesn't. If an assert fails, I don't see any output. Is assert using something else? What's wrong about this approach? Are you sure the last call to freopen doesn't return NULL? You are opening the same file twice and I'm not sure that works. Test with `stderr.writeln("test")`. Bastiaan.
Re: CTFE in imported static initializers
On Monday, 13 May 2019 at 20:39:57 UTC, Steven Schveighoffer wrote: Why? I can't even use it at compile time... pragma(msg, moddata.length); Is that a good test or "usable at compile time", though? Isn't pragma(msg) done at an earlier stage than CTFE? I think that was the argument for ctfeWriteln. (We both know that I'm out of my league here, but anyway :)) Bastiaan.
Re: Compile time mapping
On Sunday, 12 May 2019 at 18:47:20 UTC, Bogdan wrote: On Sunday, 12 May 2019 at 17:53:56 UTC, Bastiaan Veelo wrote: If I understand your question correctly, you have two enums of equal length, and you want to convert members across enums according to their position, right? My question was very vague, sorry about that. In my use case I'd like to map SDL2 keyboard scan codes to my own game input keyboard codes. The two enums would look something like this: ``` enum SDL_Scancode { SDL_SCANCODE_UNKNOWN = 0, SDL_SCANCODE_A = 4, SDL_SCANCODE_B = 5, SDL_SCANCODE_C = 6, SDL_SCANCODE_D = 7, } enum MY_Scancode { KEY_A, KEY_B, KEY_C, KEY_D, } ``` The two enums are not of equal length, so in the end I just decided to create an immutable array of type My_Scancode[] where the index is an SDL_Scancode and the value is the corresponding MY_Scancode enum member. I'm ok with using some memory for this, as long as it's as fast as possible. If the only difference is the extra _UNKNOWN member, you can still use the static foreach approach. Just make it a non-template function and rip out the checks, and add a +1 in the right place.
Re: Compile time mapping
On Sunday, 12 May 2019 at 17:53:56 UTC, Bastiaan Veelo wrote: On Saturday, 11 May 2019 at 15:48:44 UTC, Bogdan wrote: What would be the most straight-forward way of mapping the members of an enum to the members of another enum (one-to-one mapping) at compile time? If I understand your question correctly, you have two enums of equal length, and you want to convert members across enums according to their position, right? You can do that with a little bit of template programming and static foreach. The following works irrespective of underlying value and type, the only requirement is that there are no duplicate values: https://run.dlang.io/is/dNssel There was an error in the error reporting. That should teach me to never copy+paste if you can static foreach :-) This one is better: https://run.dlang.io/is/TVl9db
Re: Compile time mapping
On Saturday, 11 May 2019 at 15:48:44 UTC, Bogdan wrote: What would be the most straight-forward way of mapping the members of an enum to the members of another enum (one-to-one mapping) at compile time? If I understand your question correctly, you have two enums of equal length, and you want to convert members across enums according to their position, right? You can do that with a little bit of template programming and static foreach. The following works irrespective of underlying value and type, the only requirement is that there are no duplicate values: https://run.dlang.io/is/dNssel ``` void main() { enum FromEnum {F1 = 10, F2, F3} enum ToEnum {T1 = 20, T2, T3} enum CharEnum : char {C1 = 'c', C2, C3} static assert(to!ToEnum(FromEnum.F2) == ToEnum.T2); static assert(to!ToEnum(FromEnum.F2) == 21); static assert(to!CharEnum(FromEnum.F2) == CharEnum.C2); static assert(to!CharEnum(FromEnum.F2) == 'd'); } // Converts enumerations by position. T to(T, F)(F f) if (is(F==enum) && is(T == enum)) { import std.traits; import std.meta; static assert(NoDuplicates!(EnumMembers!F).length == EnumMembers!F.length, F.stringof ~ " has duplicates."); static assert(NoDuplicates!(EnumMembers!T).length == EnumMembers!T.length, F.stringof ~ " has duplicates."); static assert(EnumMembers!F.length == EnumMembers!T.length, F.stringof ~ " and " ~ T.stringof ~ " differ in length."); static foreach(i, t; EnumMembers!T) if (rank(f) == i) return t; assert(0, "Not an enum member"); } // Returns i if e is the i-th enumerator of E. static size_t rank(E)(E e) if (is(E == enum)) { import std.traits; static foreach (i, member; EnumMembers!E) if (e == member) return i; assert(0, "Not an enum member"); } ```
Re: OT - Git training Lon/HK and book recommendation on taste in programming
On Wednesday, 1 May 2019 at 09:51:01 UTC, Laeeth Isharc wrote: Hi. First question - can anyone recommend git / Gitlab training providers in HK and London? Two distinct audiences - highly intelligent people that may or may not really program, and experienced developers with a finance background that could benefit from knowing how to use git properly (finance is often in the dark ages). On the former we are even getting HR, legal and compliance to start to use git for documents. So some handholding will be required. I would like a combination of classroom, small group on-premise training and somebody being in the office a few hours a week to help show people. No experience is necessarily required for the latter provided you know git well and can patiently explain things in a way less advanced people will understand. It could even be a nice part-time job for a student and we could pay well. Not that we wouldn't look at a professional either - I just mean that I am open minded. I know this is not what you're asking for, but it may come in handy as supporting material: I just watched this introduction [1] to git using my favourite git GUI: SourceTree. The GUI has evolved a bit since the videos were made, but it takes the viewer through the basics at a pace that everybody should be able to follow. Sadly some planned videos in the series were never added. Bastiaan. [1] https://www.youtube.com/playlist?list=PLpL2ONl1hMLtlY1Y7YJNcA5zumvaITLYs
Re: Any full feature xml library available?
On Thursday, 2 May 2019 at 15:50:53 UTC, rikki cattermole wrote: On 03/05/2019 3:36 AM, Russel Winder wrote: On Thu, 2019-05-02 at 02:11 +1200, rikki cattermole via Digitalmars-d- learn wrote: […] It does not. Those features come under the big bad guys feature list. Gonna have to go to C for it. Surely that means you can use Python, Rust, C++, or D rather than having to descend to using C? libxml2 is definitely usable from Python, it must be usable from D. Of course, I am assuming libxml2 has the facilities required. libxml2 is precisely what I meant. We just don't have the libraries written in D at this point. Apparently, bindings to libxml2 existed back in 2008. http://www.dsource.org/projects/bcd/ Bastiaan
Re: druntime giving wrong line for copy assert?
On Tuesday, 30 April 2019 at 13:59:52 UTC, Rudy Raab wrote: The error was on line 36, which is the format, not my bad slice. Is there a reason for this, or is it a bug The message is correct when not using dub: https://run.dlang.io/is/chFTOY I suspect that if you remove the dub related lines and put it in an empty dub project, it will produce a correct message. So it looks like a bug in dub from where I am sitting. Maybe dub adds lines behind the scene? Bastiaan.
Re: Does D have a tool like pySnooper?
On Friday, 26 April 2019 at 16:59:15 UTC, H. S. Teoh wrote: On Fri, Apr 26, 2019 at 02:33:16PM +, Taylor Hillegeist via Digitalmars-d-learn wrote: On Friday, 26 April 2019 at 10:22:49 UTC, Bastiaan Veelo wrote: [...] > Proofing the concept: > --- > mixin(snoop(q{ > int fun(int a, int b) > { > int c = 3; > foreach (i; 1 .. 5) > { > a += i; > } > int d = a + b + c; > return d; > } > })); > --- > > Output: > 2019-Apr-26 10:33:46.0935135 executed line 7: int c > = 3; > 2019-Apr-26 10:33:46.0936716 executed line 10: a > += i; > 2019-Apr-26 10:33:46.0937348 executed line 10: a > += i; > 2019-Apr-26 10:33:46.0937963 executed line 10: a > += i; > 2019-Apr-26 10:33:46.0938583 executed line 10: a > += i; > 2019-Apr-26 10:33:46.0939622 executed line 12: int d > = a + b + > c; Now *this* is some seriously cool stuff. Thanks! A limitation is that snoop() needs to be pure. At one time I had a byLine in there, but for some reason byLine is not pure so that didn't work. I was almost about to see if I could use libdparse in it (run.dlang.io supports it) but I should spend my time on preparing for DConf instead... Feel free to play with it, this stuff is fun! Bastiaan.
Re: Does D have a tool like pySnooper?
On Friday, 26 April 2019 at 08:35:57 UTC, Bastiaan Veelo wrote: On Thursday, 25 April 2019 at 08:44:14 UTC, Dennis wrote: On Monday, 22 April 2019 at 16:24:53 UTC, Taylor Hillegeist wrote: Or would this not be easy at all with D? I don't think so. While there are lots of traits for introspection of declarations, there is no way to introspect lines of code. The whole function would need to be wrapped into a mixin, and the D code would need to be parsed at compile time for this to work. Yes, but I think that might be doable. You wouldn't need a full blown D parser, just one that can identify statements (`;` being an important clue). Not sure whether __LINE__ will be meaningful inside a mixin, though, but that might also be fixable. It would be an interesting challenge. Bastiaan. Proofing the concept: --- mixin(snoop(q{ int fun(int a, int b) { int c = 3; foreach (i; 1 .. 5) { a += i; } int d = a + b + c; return d; } })); --- Output: 2019-Apr-26 10:33:46.0935135 executed line 7: int c = 3; 2019-Apr-26 10:33:46.0936716 executed line 10: a += i; 2019-Apr-26 10:33:46.0937348 executed line 10: a += i; 2019-Apr-26 10:33:46.0937963 executed line 10: a += i; 2019-Apr-26 10:33:46.0938583 executed line 10: a += i; 2019-Apr-26 10:33:46.0939622 executed line 12: int d = a + b + c; https://run.dlang.io/is/Go97hQ Bastiaan.
Re: Does D have a tool like pySnooper?
On Thursday, 25 April 2019 at 08:44:14 UTC, Dennis wrote: On Monday, 22 April 2019 at 16:24:53 UTC, Taylor Hillegeist wrote: Or would this not be easy at all with D? I don't think so. While there are lots of traits for introspection of declarations, there is no way to introspect lines of code. The whole function would need to be wrapped into a mixin, and the D code would need to be parsed at compile time for this to work. Yes, but I think that might be doable. You wouldn't need a full blown D parser, just one that can identify statements (`;` being an important clue). Not sure whether __LINE__ will be meaningful inside a mixin, though, but that might also be fixable. It would be an interesting challenge. Bastiaan.
Re: Logging best practices
On Thursday, 25 April 2019 at 10:33:00 UTC, Vladimirs Nordholm wrote: Hello. Is there a current "Best Practices" for logging in D? For the actual logging, I know of `std.experimental.logger`. However, the `experimental` has kept me away from it. Is it good, or are there any better alternatives? Apart from an open issue I have, https://issues.dlang.org/show_bug.cgi?id=15536, I have used std.experimental.logger successfully here: https://github.com/PhilippeSigaud/Pegged/wiki/Grammar-Debugging Bastiaan.
Re: Logging best practices
On Thursday, 25 April 2019 at 15:51:43 UTC, dangbinghoo wrote: On Thursday, 25 April 2019 at 10:33:00 UTC, Vladimirs Nordholm wrote: Hello. Is there a current "Best Practices" for logging in D? For the actual logging, I know of `std.experimental.logger`. However, the `experimental` has kept me away from it. Is it good, or are there any better alternatives? for the latest alpha version of D release, all std.experimental has been already moved to std. Are you sure about that? https://github.com/dlang/phobos/tree/master/std I think you are confusing the package std.experimental.all that moved to std. It means you can now import all of Phobos by doing `import std;` instead of `import std.experimental.all;`. It does not mean that everything below std.experimental moved to std and thereby lost its experimental status. Bastiaan.
Re: CTFE & code generators based on PEG grammars?
On Saturday, 6 April 2019 at 12:06:22 UTC, Robert M. Münch wrote: The idea is, that I can write a string (or maybe even a scope block?) in my DSL and use a CTFE grammer to transpile the code. Are you aware of Pegged[1]? It’s for exactly that. [1] http://code.dlang.org/packages/pegged
Re: Duplicate class/interface/struct completely
On Tuesday, 26 March 2019 at 05:29:08 UTC, Michelle Long wrote: The idea is to be able to make sure one can modify a class and drop it in for the original and it work in all cases. With alias this, it can fail unless we can alias it too. This sounds like mocking, this answer might be of help: https://forum.dlang.org/post/gdfvbrknbnbfunycb...@forum.dlang.org I don’t know the capabilities of these libraries, but you may want to have a look. Bastiaan.
Re: Why this eponymous template does not compile?
On Monday, 25 March 2019 at 09:27:03 UTC, Victor Porton wrote: /tmp/temp_7F3C101460D0.d(9,5): Error: template instance `synchronizedMemoize!f` template `synchronizedMemoize` is not defined, did you mean sychronizedMemoize(alias fun)()? Why the error? Sometimes, template error messages are hard to get. But this one is pretty clear, to the point that it is difficult for a human to point out clearer. :o)
Re: Compile-time associative array
On Wednesday, 20 March 2019 at 08:11:27 UTC, boolangery wrote: Got it ! Thank you, so I need to write: enum string[string] CtfeFoo = ["foo" : "bar"]; static immutable string[string] Foo; static this() { Foo = CtfeFoo; } string ctfeableFunction() { if (__ctfe) return CtfeFoo["foo"]; else return Foo["foo"]; } void main() { enum a = ctfeableFunction(); auto b = ctfeableFunction(); } Yes, that looks correct to me.
Re: PyD - accessing D class fields in Python
On Monday, 18 March 2019 at 22:25:10 UTC, clothlen wrote: Howdy; I'm trying to extend my Python program with D, but I'm having trouble accessing a D class's field/attribute/property/something. My D file looks like this: ``` module simpletest; import pyd.pyd; import std.stdio; class ExampleTest{ int _a = 3; int a(){ return _a; } void a(int a){ this._a = a; } int b = 4; } extern(C) void PydMain() { module_init(); wrap_class!( ExampleTest, Property!(ExampleTest.a), Property!(ExampleTest.b) // Member!("b") Maybe you need `Member!(“b”, “rw”)`? ); } If that doesn’t work, maybe you find help by filing an issue on PyD.
Re: Compile-time associative array
On Tuesday, 19 March 2019 at 08:50:15 UTC, boolangery wrote: Hi, I want to use a constant associative array in a ctfe-able function. Example: string ctfeableFunction() { return Foo["foo"]; } Then I force ctfe with: enum res = ctfeableFunction(); When I use an enum like: enum Foo = ["foo" : "bar"]; It works fine. D-Scanner keep saying to me: This enum may lead to unnecessary allocation at run-time. Use 'static immutable [...] instead' But it lead to: Error: static variable Foo cannot be read at compile time. So is the only way to make ctfe-able associative array is to use enum instead of static immutable ? Yes, I think so. If you would use the enum AA multiple times, it would allocate a new AA each time, that is wat D-Scanner warns against. I am not sure how the CTFE interpreter is implemented, it could be that a new AA is allocated each time you call ctfeableFunction, at compile time. But unless you also call it at runtime, there should be no extra run time allocations. If you need the AA at run time as well, I would create a static immutable version for that, initialised with the enum. Beware that a CT AA stores its elements in a different order than a RT AA, which you would notice in a foreach, for example.
Re: why is ifThrown un@safe?
On Friday, 15 March 2019 at 19:24:17 UTC, Bastiaan Veelo wrote: Will do the filing and maybe experiment a bit. Bastiaan. https://issues.dlang.org/show_bug.cgi?id=19741
Re: why is ifThrown un@safe?
On Friday, 15 March 2019 at 19:19:41 UTC, H. S. Teoh wrote: On Fri, Mar 15, 2019 at 06:46:25PM +, bauss via Digitalmars-d-learn wrote: On Friday, 15 March 2019 at 18:04:05 UTC, Bastiaan Veelo wrote: > In the code below (https://run.dlang.io/is/d0oTNi), ifThrown > is inferred as un@safe. If instead I write the > implementation of ifThrown out (after res2) then it is > @safe. As far as I can see, there is no real difference. So > why doesn't ifThrown work in this case, and can it be made > to work? [...] Because the handlers may be unsafe. There is no safe overload of ifThrown. However you can work around this using @trusted. I wasn't satisfied with this answer, because in theory the @safe-ness of ifThrown ought to be inferred from the @safe-ness of its arguments, and ifThrown itself shouldn't do anything un-@safe. So I investigated a little further, and found that the problem lies in how ifThrown is declared: CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate(Exception) errorHandler) { ... } The problem is that the second parameter is declared to be a delegate with no further qualifications, which means it defaults to @system. Therefore, even if `expression` and `errorHandler` are both @safe, the compiler will still infer the call to `errorHandler` as @system, and therefore ifThrown will also be inferred as @system. The obvious fix of adding @safe to the second parameter won't work, because that would preclude ifThrown from being used with @system error handlers. So it appears to me that in order to make this work as it should, we need to templatize not only on the return type of the delegate, but on the delegate type itself. Perhaps something along the lines of: CommonType!(T1, ErrorHandler) ifThrown(T1, T2)(lazy scope T1 expression, scope ErrorHandler errorHandler) if (... && is(ErrorHandler == delegate) && is(ReturnType!ErrorHandler : T1)) { ... } This should probably be filed as an enhancement request in bugzilla. T Excellent, thank you. Will do the filing and maybe experiment a bit. Bastiaan.
Re: why is ifThrown un@safe?
On Friday, 15 March 2019 at 18:46:25 UTC, bauss wrote: On Friday, 15 March 2019 at 18:04:05 UTC, Bastiaan Veelo wrote: In the code below (https://run.dlang.io/is/d0oTNi), ifThrown is inferred as un@safe. If instead I write the implementation of ifThrown out (after res2) then it is @safe. As far as I can see, there is no real difference. So why doesn't ifThrown work in this case, and can it be made to work? Thanks! void main() @safe { import std.process; import std.exception; const res1 = execute(["clang", "-v", "-xc++", "/dev/null", "-fsyntax-only"], ["LANG": "C"]) .ifThrown((e) @safe { import std.typecons : Tuple; return Tuple!(int, "status", string, "output")(-1, e.msg); }); // Fails const res2 = () { try { return execute(["clang", "-v", "-xc++", "/dev/null", "-fsyntax-only"], ["LANG": "C"]); } catch (Exception e) { import std.typecons : Tuple; return Tuple!(int, "status", string, "output")(-1, e.msg); } }(); } Because the handlers may be unsafe. But this handler is explicitly marked @safe, and ifThrown is a template, which should infer its attributes, right? There is no safe overload of ifThrown. Could it be added? However you can work around this using @trusted. I know, but since everything really is safe, I'd rather not imply that it might not be. Besides, I failed to use @trusted without introducing a new scope, so I'd have to mark the whole block where `res1` is used as @trusted. Maybe I did that wrong though.
why is ifThrown un@safe?
In the code below (https://run.dlang.io/is/d0oTNi), ifThrown is inferred as un@safe. If instead I write the implementation of ifThrown out (after res2) then it is @safe. As far as I can see, there is no real difference. So why doesn't ifThrown work in this case, and can it be made to work? Thanks! void main() @safe { import std.process; import std.exception; const res1 = execute(["clang", "-v", "-xc++", "/dev/null", "-fsyntax-only"], ["LANG": "C"]) .ifThrown((e) @safe { import std.typecons : Tuple; return Tuple!(int, "status", string, "output")(-1, e.msg); }); // Fails const res2 = () { try { return execute(["clang", "-v", "-xc++", "/dev/null", "-fsyntax-only"], ["LANG": "C"]); } catch (Exception e) { import std.typecons : Tuple; return Tuple!(int, "status", string, "output")(-1, e.msg); } }(); }
Re: Phobos in BetterC
On Friday, 8 March 2019 at 09:24:25 UTC, Vasyl Teliman wrote: I've tried to use Mallocator in BetterC but it seems it's not available there: https://run.dlang.io/is/pp3HDq This produces a linker error. I'm wondering why Mallocator is not available in this mode (it would be intuitive to assume that it's working). Also I would like to know what parts of Phobos are available there (e.g. std.traits, std.typecons...). Thanks in advance. I can’t answer that but you can use C’s malloc directly: https://run.dlang.io/is/fnRFIr Bastiaan.
Re: How to call other variadic function with the same arguments?
On Sunday, 24 February 2019 at 13:09:15 UTC, Victor Porton wrote: Let f be a variadic function: Result f(...); How to implement variadic function g which calls f with the same arguments as one it receives? Result g(...) { // ... } I don’t know if you can, but if at least g is a variadic template function, you can: https://run.dlang.io/is/fhxZuV Bastiaan.
Re: Odd behavior of darray.dup
On Sunday, 24 February 2019 at 12:10:22 UTC, Bastiaan Veelo wrote: 1) You get "immutable(Color)(#{overlap raw, colors})" on immutable Color because the `Color.toString()` method is not const (corrected in the Gist). This is a bug in pixelperfectengine. Likewise, getters like `green()` should be const. Reported. https://github.com/ZILtoid1991/pixelperfectengine/issues/8
Re: Odd behavior of darray.dup
On Saturday, 23 February 2019 at 23:35:14 UTC, solidstate1991 wrote: On Saturday, 23 February 2019 at 19:21:10 UTC, Bastiaan Veelo wrote: It works for me: https://run.dlang.io/gist/473b0021487275751accaebeb00be05c -- Bastiaan Still no luck, not even with memcpy. There's even more mystery as I printed out the original static immutable array's content, which is different from the non-immutable one. Instead of the 32bit hex value of the given color in the format of "0x", I get "immutable(Color)(#{overlap raw, colors})". This might be a bug. Sorry, I didn't realize that my link didn't work (due to issue https://github.com/dlang-tour/core/issues/714). I have instead exported a Gist https://gist.github.com/run-dlang/965a2fb793bda7b1a82b0512d78973f3 that you should be able to use with the "Import Gist" button on https://run.dlang.io/. I have included the relevant bits from pixelperfectengine (slightly modified, see below). If you have further questions, you can do the same so it will be easier to see what is going on. Several things here: 1) You get "immutable(Color)(#{overlap raw, colors})" on immutable Color because the `Color.toString()` method is not const (corrected in the Gist). This is a bug in pixelperfectengine. Likewise, getters like `green()` should be const. 2) Also note that `intToHex()` could simply be implemented using std.format, as row 127 illustrates. 3) You get all zeros because static data needs a static module constructor, added on line 111. 4) As an alternative to static data you could use compile time data (line 118) which does not need a constructor nor `.dup`. Beware that each time you use it though, its value gets copy-pasted into the code like a C #define. Hope this helps, Bastiaan.
Re: Odd behavior of darray.dup
On Friday, 22 February 2019 at 11:36:35 UTC, solidstate1991 wrote: If I want to copy an array of structs with .dup (cannot post the link in question here at the moment due to non-working clipboard, it's Color from pixelperfectengine.graphics.common) I get all zeroes instead of the values from the original array. I haven't disabled post-blit to my knowledge. Is it some kind of a bug, or the .dup function has some behavior that's not currently documented on the site (such as needing a copy constructor)? It works for me: https://run.dlang.io/gist/473b0021487275751accaebeb00be05c -- Bastiaan
Re: Generalizing over function pointers and delegates
On Friday, 15 February 2019 at 17:28:45 UTC, H. S. Teoh wrote: On Fri, Feb 15, 2019 at 05:40:39PM +0100, ag0aep6g via Digitalmars-d-learn wrote: Your fun_to_dlg fails when the function has parameters. Yes. Delegates are basically syntactic sugar for a function pointer with an implicit first parameter. I.e., a delegate like: int delegate(string) dg; is under the hood implemented as the equivalent of: struct _delegate { int function(T* context, string) funcptr; T* context; int opCall(string s) { return funcptr(context, s); } } where T is an appropriate context type, whether an aggregate (struct / class) or an anonymous struct that closes over whatever variables the delegate accesses in its containing scope. For this reason, casting a function pointer to a delegate will not work properly, because the first arguments and number of parameters would not match. T I love this forum!
Re: Generalizing over function pointers and delegates
On Friday, 15 February 2019 at 16:40:39 UTC, ag0aep6g wrote: Your fun_to_dlg fails when the function has parameters. Hah ok. std.functional.toDelegate() does work in its place though. As far as I see, it would be possible make the conversion would work by changing how a delegate's context is passed [1]. But I didn't pursue that idea further, and no one else picked it up either. [1] https://forum.dlang.org/post/ofc0lj$2u4h$1...@digitalmars.com Interesting. Thanks for the link.
Re: Generalizing over function pointers and delegates
On Friday, 15 February 2019 at 14:30:45 UTC, Alex wrote: There is https://dlang.org/library/std/functional/to_delegate.html Ah, there it is :-) Thanks. A templated function also works. ``` int genfun(F)(F dg) {return dg();} int top_level() {return -1;} void main() { int nested() {return -2;} assert(genfun(_level) == -1); assert(genfun() == -2); } ```
Generalizing over function pointers and delegates
Given a function taking a delegate, for example ``` int fun(int delegate() dg) {return dg();} ``` Sometimes we need to call `fun` with a pointer to a nested function and other times with a pointer to a top level function. As function pointers do not implicitly convert to delegates, this does not work without jumping through hoops. One option is to define an overload: ``` int fun(int function() fn) { int nested_fn() { return fn(); } return fun(_fn); } ``` This is clunky and rather a lot of extra lines to work around a language limitation. The limitation seems somewhat artificial, because a delegate /can/ be initialized referencing a top level function (the spec [1] limits that to delegate declarations at module scope, but this limit does not seem to apply [2]). But you cannot /assign/ it a top level function. You can however explicitly assign the `.funcptr` referencing the top level function, leaving the stack frame pointer null. Exploiting this, it is possible to explicitly convert a function pointer into a delegate [2]: ``` Ret delegate(Args args) fun_to_dlg(Ret, Args...)(Ret function(Args args) fun) { Ret delegate(Args) dlg; dlg.funcptr = fun; return dlg; } ``` allowing ``` int top_level() {return -1;} void main() { assert(fun(fun_to_dlg(_level)) == -1); } ``` This may be preferable to the overload, depending on the number of calls like this. But since this is allowed and working, why can't it be done automatically? Or, when implicit conversion is dangerous, why doesn't a cast exist to the effect of my template? Have I overlooked an easier way of doing this? Thanks for any input! Bastiaan. P.S. For the record, the spec also says this: "Future directions: Function pointers and delegates may merge into a common syntax and be interchangeable with each other." I wish that was the case already. [1] Point 9 in https://dlang.org/spec/function.html#closures [2] https://run.dlang.io/is/x8HJaW
Re: Determination of thread status.
On Wednesday, 26 December 2018 at 05:43:47 UTC, Vitaly wrote: On Tuesday, 25 December 2018 at 17:08:00 UTC, Neia Neutuladh wrote: 1. Find the Thread object: Tid threadId = spawn(); auto thread = Thread.getAll.filter!(x => x.id == threadId).front; 2. Check the `isRunning` property. The indirection with spawn() is awkward. Thanks for the answer. I checked. Thread.getAll [x] .id is of type ulong, and spawn is of type Tid, moreover, they do not intersect in value either. But even if the program spawns a single thread, Thread.getAll [x] .isRunning returns true after the function terminates. Perhaps you need to wait some time. You may have to send a message before exiting the function. Just look at the possibilities of std.parallelism. I will gladly try other solutions. I would be grateful for your suggestions. Maybe use spawnLinked()? https://run.dlang.io/is/9xbyAF
Re: Determination of thread status.
On Tuesday, 25 December 2018 at 14:44:43 UTC, Vitaly wrote: Hi all. I can not understand how to track me that the thread has finished work. eg: import std.concurrency; void myThread () { // Do the work } void main () { Tid thread = spawn (& myThread); // It is necessary to check whether the thread has finished its work or is active. } Could you tell me how to do this? std.concurrency is a low-level API. You may be looking for a higher level API: std.parallelism. See Task.done(), https://dlang.org/phobos/std_parallelism.html#.Task.done Bastiaan.
Re: CT BitArray
On Thursday, 1 November 2018 at 00:01:04 UTC, Stefan Koch wrote: Tell me which version are you using and I'll make it for you. By the way this is a really generous offer, thanks for being like that!
Re: CT BitArray
On Thursday, 1 November 2018 at 00:01:04 UTC, Stefan Koch wrote: On Wednesday, 31 October 2018 at 23:14:08 UTC, Bastiaan Veelo wrote: Currently, BitArray is not usable at compile time, so you cannot do ``` enum e = BitArray([1, 1, 1, 0]); ``` This gives /dlang/dmd/linux/bin64/../../src/phobos/std/bitmanip.d(1190): Error: `bts` cannot be interpreted at compile time, because it has no available source code IIUC, that is because `bts` comes from core.bitop but no source code is there. I am guessing these are filled in by compiler intrinsics or the like, and they are unavailable at CT, correct? I suppose that alternative implementations of `btc`, `bts`, `btr`, `bsf` and `bt` could exist that do not use the runtime that could be used if(__ctfe) in the implementation of BitArray, that would make the above code work. Is this feasible? Is there precedent in phobos? Are there complications? Thanks! Oh that ... actually I can fix that with a small patch to dmd. Tell me which version are you using and I'll make it for you. Cheers, Stefan Thank you, Stefan. At the moment we are using latest stable dmd, v2.082.1. I expect to switch to ldc or gdc at a later time. I don't think we'll be patching the compiler, support in the mainline compilers would be much preferable. It is not a blocker either, we can wait as long as it takes and meanwhile use module level BitArrays like ``` immutable BitArray e; static this() { e = BitArray([1, 1, 1, 0]); } ``` It just seemed like a fixable limitation to me, hence my question here. Shall we start with a feature request? Bastiaan.
CT BitArray
Currently, BitArray is not usable at compile time, so you cannot do ``` enum e = BitArray([1, 1, 1, 0]); ``` This gives /dlang/dmd/linux/bin64/../../src/phobos/std/bitmanip.d(1190): Error: `bts` cannot be interpreted at compile time, because it has no available source code IIUC, that is because `bts` comes from core.bitop but no source code is there. I am guessing these are filled in by compiler intrinsics or the like, and they are unavailable at CT, correct? I suppose that alternative implementations of `btc`, `bts`, `btr`, `bsf` and `bt` could exist that do not use the runtime that could be used if(__ctfe) in the implementation of BitArray, that would make the above code work. Is this feasible? Is there precedent in phobos? Are there complications? Thanks!
Re: Dub project has both .sdl and .json files. Is this normal or did I do something wrong?
On Saturday, 4 August 2018 at 17:53:45 UTC, Neia Neutuladh wrote: On Friday, 3 August 2018 at 19:41:32 UTC, Bastiaan Veelo wrote: But if you commit it, and a compiler deprecation causes a dependency in that pinned version to fail to compile, then your app won't compile either, even though your code itself does not suffer from the deprecation and even though a newer release of the dependency is available that solves the deprecations. This means that, if your app is on code.dlang.org, people won't be able to dub fetch && dub run. This is also true if the dependency gets a major version bump and then gets updated for a breaking compiler change. If the dependency range is broad enough, you can `dub upgrade && dub run`. You mean the dependency range in dub.selections.json of an app on code.dlang.org? I would be in favour of it being a range, but I think that is unusual. Usually people just commit the generated file unedited, which seems to always be pinned to the patch level? Anyway, dub documentation could be a lot more verbose on dub.selections.json :-) What advantages does committing dub.selections.json have that outweigh this disadvantage? Dependencies don't always follow semantic versioning. For instance, a binding for a C library that is actively developed might reasonably follow the bound library's versioning. Or the maintainer might make a mistake and commit a breaking change without bumping to a new major version. This is why my top-level projects these days have specific versions of dependencies rather than the more commonly used ranges. I'm only going to test against those specific versions, so why should I claim that my application can use future versions? I know that failing to build is better than potential erroneous execution, so I understand the rationale. It’s just that I get build failures after updating to the newest compiler often enough that it's frustrating. Build failures in tools that I use in my build that is, like dfmt, ddox, scod. It would be OK if dub.selections.json would also pin the compiler version and there were a standard way to select that version (like dvm, but without its shortcomings). That would be good. If I were less lazy, I could add that to dub. It already manages packages; the compiler is just a slightly different dependency. Apart from solving this problem, there are other advantages: 1. It would make it possible to check out an older version of your software and compile it without problems, and be sure that it results in the same binary as when that version was committed. 2. You can easily work with different compilers in different branches. Like using ldc in the release branch of your CI and dmd in your feature branch, or work on porting to a different compiler outside the master branch. But since dub is distributed with the compiler, handling the compiler as a dependency might not be straightforward. How would you prevent getting trapped in an old version when dub downgrades itself? Which of the installed dub versions du you use to do dub upgrade? How would dub appear in dub.selections.json? If you have ideas on this, I am genuinely interested. -Bastiaan
Re: Dub project has both .sdl and .json files. Is this normal or did I do something wrong?
On Tuesday, 19 December 2017 at 10:15:18 UTC, Jacob Carlborg wrote: On 2017-12-18 23:36, WhatMeWorry wrote: [...] But when I look the directory that has the dub.sdl file, I also see a file called dub.selections.json { "fileVersion": 1, "versions": { "derelict-al": "1.0.3", "derelict-assimp3": "1.3.0", "derelict-fi": "2.0.3", "derelict-fmod": "2.0.4", "derelict-ft": "1.1.3", "derelict-gl3": "1.0.23", "derelict-glfw3": "3.1.3", "derelict-util": "2.0.6", "gl3n": "1.3.1" } } So how did this .json file get created and can I just delete it? You should keep it. If you have developed an application it should be committed to git, if it's a library it should not be committed. But if you commit it, and a compiler deprecation causes a dependency in that pinned version to fail to compile, then your app won't compile either, even though your code itself does not suffer from the deprecation and even though a newer release of the dependency is available that solves the deprecations. This means that, if your app is on code.dlang.org, people won't be able to dub fetch && dub run. What advantages does committing dub.selections.json have that outweigh this disadvantage? It would be OK if dub.selections.json would also pin the compiler version and there were a standard way to select that version (like dvm, but without its shortcomings). For example, scod 0.4.4 does not compile with dmd 2.081.1 because of this (https://github.com/MartinNowak/scod/issues/14). Its latest change to dub.selections.json is only three months old, to make it work with dmd 2.080.0. This illustrates that if you're unlucky, you may have to bring out frequent new releases with updates to dub.selections.json (through "dub upgrade") even though your app is stable and doesn't change.
Re: Newbie: out-of-source builds with "dub"?
On Monday, 30 July 2018 at 01:50:23 UTC, CC wrote: [...] My usual modus operandi is: 1. check out the project into some directory "foo". 2. create another directory "foo.build", somewhere outside of "foo". 3. "cd foo.build" 4. Run some configuration script/file located in "foo", to generate "foo.build/Makefile". 5. Run "make". I've started playing with "dub", and it *seems* to assume that you want the files generated during the build process to reside directly inside your checked-out source tree. Is that true? And if so, am I fighting dub's design by attempting out-of-source builds? I haven’t tried it, but from the docs it seems that “--temp-build” does an out-of-source build, although it’s not exactly like your modus operandi.
Re: UCFS does not work for nested functions?
On Monday, 18 June 2018 at 19:31:39 UTC, Steven Schveighoffer wrote: In other words, if UFCS meant that module-level symbols took precedent over local symbols, then it's backwards in terms of which place usually wins. Generally it's the local symbols. Ah, you mean it would have to be that way to prevent breakage. No I would not want it that way. [...] But one thing I will note, is that this is valid today: void bar(int) {writeln("module");} void main() { static void bar(int) {writeln("local");} int x; x.bar; // "module" } Adding UFCS support to locals, which one would be the expected call? It's difficult to imagine the local being the lower priority, but it would have to be that way to avoid code breakage. Thanks, that clarifies it. No turtles for UFCS.
Re: UCFS does not work for nested functions?
On Monday, 18 June 2018 at 17:58:11 UTC, Steven Schveighoffer wrote: On 6/18/18 1:25 PM, bauss wrote: On Monday, 18 June 2018 at 17:16:29 UTC, aliak wrote: On Monday, 18 June 2018 at 14:19:30 UTC, Steven Schveighoffer wrote: On 6/18/18 7:16 AM, Bastiaan Veelo wrote: On Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote: Hi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is: I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ``` It's never been supported, and likely will not be. I think the idea is that you can override expected behavior inside by accidentally defining some function locally with the same name. Wondering how this is different than with non-nested functions? If a global function has the same name as a member function then the member function takes precedence. So wouldn't the same thing just apply here if it were supported? I second this. What then can happen is that your local calls can get hijacked from outside the module, if someone happens to define something later that you happened to import. D tries to avoid such possibilities. There's not much precedent for local symbols being overridden by module-level symbols. -Steve I don't understand. What local symbol would be overwritten by which module-level symbol? Whatever the concerns, what is the difference regarding these concerns between this: ``` // Valid today void bar(int) {} void main() { int x; b.bar; } ``` and this: ``` \\ Invalid today void main() { static void bar(int) {} int x; x.bar; } ```
Re: UCFS does not work for nested functions?
On Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote: Hi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is: I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ```
File.put()
Writing a single value to binary file can be done in (at least) two ways. Let `f` be a `File`: ``` f.rawWrite(()[0 .. 1]); ``` or ``` f.lockingBinaryWriter.put(value); ``` The former way is little talked about, the latter is not even documented. As far as I can see, the latter resolves to the former [1] if we disregard locking, mode switching and keeping a reference count (on Windows). Shouldn't there be a `File.put()` method for the case where you already know that the file is locked and in the right mode? The trick to convert a single value to a range so it can be feeded to `rawWrite` may not be obvious to everyone. Or have I just overlooked the obvious way for writing single values? [1] https://github.com/dlang/phobos/blob/v2.080.1/std/stdio.d#L3102
Re: Line endings when redirecting output to file on windows.
On Monday, 4 June 2018 at 15:31:04 UTC, Steven Schveighoffer wrote: Windows C library has this bizarro mode for FILE * called "text" mode, which is the default. In this mode, it scans all output, and anywhere it sees a '\n', it replaces it with "\r\n". Thanks, Steven.
Re: Line endings when redirecting output to file on windows.
On Sunday, 3 June 2018 at 15:42:48 UTC, rikki cattermole wrote: On 04/06/2018 3:24 AM, Bastiaan Veelo wrote: I need some help understanding where extra '\r' come from when output is redirected to file on Windows. First, this works correctly: rdmd --eval="(\"hello\" ~ newline).toFile(\"out.txt\");" As expected, out.txt contains "hello\r\n". I would expect the following to do the same, but it doesn't: rdmd --eval="write(\"hello\" ~ newline);" > out.txt Now out.txt contains "hello\r\r\n". Who is doing the extra conversion here, and how do I stop it? Thanks! Bastiaan. That would be cmd. Not sure you can stop it without piping it after rdmd to remove the \r. Thanks. It is starting to dawn on me that I shouldn't use `newline` and `toFile` to write text files, but rather always use "\n" as line ending and use `write` for both writing to stdout and file. rdmd --eval="File(\"out.txt\", \"w\").write(\"hello\n\");" and rdmd --eval="write(\"hello\n\");" > out.txt both produce "hello\r\n" on Windows. Am I correct, or is there a more idiomatic way of writing strings to text files?
Line endings when redirecting output to file on windows.
I need some help understanding where extra '\r' come from when output is redirected to file on Windows. First, this works correctly: rdmd --eval="(\"hello\" ~ newline).toFile(\"out.txt\");" As expected, out.txt contains "hello\r\n". I would expect the following to do the same, but it doesn't: rdmd --eval="write(\"hello\" ~ newline);" > out.txt Now out.txt contains "hello\r\r\n". Who is doing the extra conversion here, and how do I stop it? Thanks! Bastiaan.
Re: Template instantiation fails on Linux, succeeds on Windows
On Thursday, 17 May 2018 at 23:18:32 UTC, Basile B. wrote: On Thursday, 17 May 2018 at 22:07:46 UTC, Bastiaan Veelo wrote: Hi! The code in [1] compiles and runs flawlessly on Windows, but not on Linux (neither run.dlang nor Travis docker image). Any idea what can be done? Hello. Yes, add `import core.stdc.stdarg;` in your module and it works. I don't know why it's not required on windows, this is strange. Great! Thanks a lot, Basile! Seems there is room for improvement somewhere, a better error message at the least.
Template instantiation fails on Linux, succeeds on Windows
Hi! The code in [1] compiles and runs flawlessly on Windows, but not on Linux (neither run.dlang nor Travis docker image). Any idea what can be done? errors: Error: undefined identifier __va_list_tag onlineapp.d(282): Error: template instance `onlineapp.SetFactory!byte` error instantiating Error: undefined identifier __va_list_tag onlineapp.d(288): Error: template instance `onlineapp.SetFactory!(Count)` error instantiating Error: undefined identifier __va_list_tag onlineapp.d(290): Error: template instance `onlineapp.SetFactory!char` error instantiating SetFactory is defined on row 233, and it seems that the problem relates to the vararg opIndex. [1] https://run.dlang.io/gist/6dcbe4e82846cbeb3bf478e92a2b6e6f
Re: How to inform dub of generated source files?
On Thursday, 17 May 2018 at 17:42:21 UTC, Bastiaan Veelo wrote: Isn't preGenerateCommands meant to cover this case? Appears to be a bug. Filed https://github.com/dlang/dub/issues/1474
How to inform dub of generated source files?
Hi, Context: https://github.com/veelo/Pascal2D One of my source files is generated by executing `cd source && rdmd generate.d`, which creates the file `source/epparser.d`. (There is actually one step in between, calling `rdmd make.d`, which checks creation times, but that's not relevant here). I have added this step as preGenerateCommands in dub.json [1]. The problem is that the first time `dub build` is run, it does not seem to be aware of `source/epparser.d` and linking fails [2]. A second `dub build` succeeds. Isn't preGenerateCommands meant to cover this case? I can add `epparser.d` in an extra soureFile line in dub.json, which fixes the very first build, but that makes successive builds fail because it causes the file name to appear twice in the arguments to dmd once the file exists. Changing preGenerateCommands into preBuildCommands makes no difference. Thanks! Bastiaan. [1] https://github.com/veelo/Pascal2D/blob/master/dub.json#L22 [2] https://travis-ci.org/veelo/Pascal2D/builds/379096446#L511
Re: Shouldn't D be added to this list?
On Tuesday, 6 February 2018 at 22:36:09 UTC, WhatMeWorry wrote: https://www.khronos.org/opengl/wiki/Language_bindings I was thinking that with derelictGL, D should be on this list? If so, I'm not sure how one would go about this? It is a wiki, anybody can add it, me thinks.
Re: BitArray shift left/right confusion.
On Friday, 2 February 2018 at 00:33:03 UTC, Jakub Łabaj wrote: On the other hand, shifting operators are equally confusing for me, as they are for you - they really work in the other way around! I thought this is a very weird bug, but I found this pull request: https://github.com/dlang/phobos/pull/2844, which states this is the intended behaviour. I don't know if there is anybody that would expect this - it's inconsistent with any other bitset implementation I know from other languages, as well as with what logic suggests. I'm curious if the authors changed their minds in this regard and there is any chance for that to be rewritten? The same confusion existed amongst the authos, that pull was done in reaction to https://github.com/dlang/phobos/pull/2797#discussion-diff-22456052. So the shift direction seems to be as intended (by Martin Nowak at least) but the docs should be clear in what order the bits are printed and indexed. I guess.
Re: `Alias this` to a mixed in property
On Wednesday, 24 January 2018 at 14:21:42 UTC, ag0aep6g wrote: The spec says that you cannot make an overload set just by mixing in multiple functions/methods with the same name. Instead, you have to do it like this: mixin getter g; mixin setter!int s; alias p = g.p; alias p = s.p; https://dlang.org/spec/template-mixin.html#mixin_scope Thanks a lot! I didn't know you could do overloads by way of multiple aliases with the same name. I meant to use this for mixing in multiple instantiations generated from a static foreach over an AliasSeq of types, but generating unique identifiers poses an extra challenge. I may go for string mixin's instead, which I just discovered do work: ``` import std.stdio; enum getter = ` @property int p() { writeln(__LINE__, " mixin getter"); return 3; } `; string setter(string T) pure { return ` @property int p(` ~ T ~ ` arg) { writeln(__LINE__, " mixin setter ` ~ T ~ `" , arg); return 4; } `; } struct S { mixin(getter); mixin(setter("int")); alias p this; } void main(string[] args) { S s; s = 7; int i = s; } ```
`Alias this` to a mixed in property
Hi, `Alias this` to mixed in properties does not seem to work, see below. If you think it should, I'll file an issue. Otherwise: can this be made to work somehow? Interestingly, if you uncomment either the mixin getter or setter (row 36 or 37) and its corresponding use in `main`, then the remaining property works. Does the compiler detect identical names and then does some additional mangling which messes with my `alias this` maybe? ``` import std.stdio; // version = manual; // Manually written property works, obviously. mixin template getter() { @property int p() { writeln(__LINE__, " mixin getter"); return 3; } } mixin template setter(T) { @property int p(T arg) { writeln(__LINE__, " mixin setter ", typeid(T), ' ', arg); return 4; } } struct S { version (manual) { @property int p() { writeln(__LINE__, " manual getter"); return 3; } @property int p(int arg) { writeln(__LINE__, " manual setter int ", arg); return 4; } } else { mixin getter;// row 36 mixin setter!int;// row 37 } alias p this; } void main(string[] args) { S s; s = 7; int i = s; } ``` Error: cannot implicitly convert expression s of type S to int.
Re: Finding ElementType
On Sunday, 7 January 2018 at 13:50:23 UTC, Adam D. Ruppe wrote: On Sunday, 7 January 2018 at 12:40:22 UTC, Bastiaan Veelo wrote: 1) Should we have a reference in the docs for std.traits to std.range.primitive : ElementType? wouldn't hurt i guess 2) Should phobos contain a version without the special narrow string behavior? see ElementEncodingType http://dpldocs.info/experimental-docs/std.range.primitives.ElementEncodingType.html 3) Are there other differences between my version and the phobos version? The Phobos one works on any range, not just built-in arrays. It also returns an answer (void) if you pass it something that has no element type, whereas yours would be a compile error. Thanks.
Finding ElementType
The learn forum is great not only for asking questions, but also for learning from the questions by others: I just learned about the existence of std.range.primitives: ElementType, a function that I have looked for in phobos before, without finding it. I had expected this to be in std.traits or __traits. So I implemented my own: ``` template arrayElementType(T : T[]) { alias arrayElementType = T; } unittest { static assert (is(arrayElementType!(int[]) == int)); } ``` For reference, this is the phobos version: ``` template ElementType(R) { static if (is(typeof(R.init.front.init) T)) alias ElementType = T; else alias ElementType = void; } ``` As far as I can see these are largely equivalent, except that the phobos version has special behavior for narrow strings [1]. This special behavior is actually unwanted in my case. The following questions pop up: 1) Should we have a reference in the docs for std.traits to std.range.primitive : ElementType? 2) Should phobos contain a version without the special narrow string behavior? 3) Are there other differences between my version and the phobos version? Thanks, Bastiaan. [1] https://dlang.org/phobos/std_range_primitives.html#ElementType
Re: Does dub support generating source files?
On Saturday, 6 January 2018 at 13:40:54 UTC, rikki cattermole wrote: On 06/01/2018 1:23 PM, Bastiaan Veelo wrote: I could script a custom preBuildCommand that checks modification dates and supplies the Pegged include path explicitly but that seems hackish and non-portable and typically something that the build system should do. See: https://github.com/Abscissa/gen-package-version If I read this correctly, it basically takes the script route (rdmd) somewhat like the above [1], but taking care to stay portable by inquiring dub. I should be able to make this work, but I wish dub supported adding simple make rules... [1] https://github.com/Abscissa/gen-package-version/blob/515138077fb78af5c4154f13990cee23e54ed9e7/src/genPackageVersion/genDModule.d#L60
Re: Does dub support generating source files?
On Saturday, 6 January 2018 at 13:40:54 UTC, rikki cattermole wrote: On 06/01/2018 1:23 PM, Bastiaan Veelo wrote: Can dub do this or is this a thing for reggae? It must work on Windows though. Thanks! See: https://github.com/Abscissa/gen-package-version That seems to be a good tip, thanks. I'll need to study what's going on there.
Does dub support generating source files?
Hi, One of my source files (epparser.d) should be generated by calling rdmd on another soure file (make.d) and therefore should depend on changes in make.d and an additional module (epgrammar.d). An include path to Pegged is required for compilation. epparser.d should be part of the main project, but make.d and epgrammar.d should not. I have tried using a dub subpackage for this with preBuildCommands ("cd ./subpackage && dub run") in the main project, but that doesn't update epparser.d when epgrammar.d changes (oddly enough; is does update when subpackage targetType is "library", but it must be "executable"). epparser.d should not be generated unnecessarily. I could script a custom preBuildCommand that checks modification dates and supplies the Pegged include path explicitly but that seems hackish and non-portable and typically something that the build system should do. Can dub do this or is this a thing for reggae? It must work on Windows though. Thanks!
Re: BitArray shift left/right confusion.
On Wednesday, 27 December 2017 at 20:45:49 UTC, Biotronic wrote: BitArray is apparently a mess. Thanks for your confirmation, digging and reporting issues https://issues.dlang.org/show_bug.cgi?id=18133 and https://issues.dlang.org/show_bug.cgi?id=18134 (Turns out we both live in the same country).
BitArray shift left/right confusion.
I suppose the following is not a bug, but confusing it is: ``` void main() { import std.stdio; import std.bitmanip; BitArray ba = [1, 1, 1, 1, 1, 1, 1, 1]; writeln(ba);// [1, 1, 1, 1, 1, 1, 1, 1] ba >>= 4; // right shift writeln(ba);// [1, 1, 1, 1, 0, 0, 0, 0] bits shifted left }``` I suppose this is because the array is printed left-to-right, whereas the bits in a byte are typically ordered right-to-left. I suppose I should interpret the bits in the array to increase in significance with increasing index (little endian) and that right-shift means a shift towards less significance (which is to the right in big endian). The documentation of <<= and >>= [1] however just talks about left and right, without defining left and right or clarifying that the directions are reversed from how the array is printed. Is there something I have missed? [1] https://dlang.org/phobos/std_bitmanip.html#.BitArray.opOpAssign.2
Re: Ddoc and struct members
On Thursday, 14 December 2017 at 03:17:10 UTC, rikki cattermole wrote: On 14/12/2017 3:16 AM, n00nb wrote: I don't understand if there is a way to generate documentation for all the members without putting a '///' over every member There isn't. It doesn’t need to take any vertical space though: “If the documentation comment appears on the same line to the right of a declaration, it applies to that.“ [1] [1] https://dlang.org/spec/ddoc.html
Re: ddox empty public methods/interfaces etc
On Friday, 10 November 2017 at 10:12:32 UTC, RazvanN wrote: I don't want to open a new forum thread for this, but if you guys have more experience with ddox can you please explain me how does it work? I expected you can simply run ddox on a .d file and it will output the documentation in some sort of form (json, html or whatever), but from what I saw, you need to pass it the json if you want to use serve-html/generate-html/filter and you have to use dmd to generate the json. Looking on the source code only passing serve-test actually parses the .d file, but the serve-test doesn't seem to be a public parameter. Not sure whether this is on topic, but does dub --build=ddox do what you want?
Re: ldc D compiler installation on windows 10
On Sunday, 6 August 2017 at 23:44:27 UTC, greatsam4sure wrote: Good day. I will appreciate it if anybody here can help me with the step by step way of installing ldc D compiler on windows. I have read online info but i just don't get it. let the process be in steps for easy comprehension.thanks in advance Try this: 1) go to https://github.com/ldc-developers/ldc/releases 2) download the appropriate ldc2-*-msvc.zip 3) unzip it anywhere 4) read the README.txt from that location. If you encounter a problem, try to explain it here as detailed as you can. Regards, Bastiaan.
Re: VibeD - REST API and vibed.web.auth framework
On Sunday, 6 August 2017 at 16:47:14 UTC, holo wrote: Hello I'm trying to use auth framework with REST api ( http://vibed.org/api/vibe.web.auth/ ). Is it possible to use it with registerRestInterface? According to description under: http://vibed.org/api/vibe.web.auth/requiresAuth it should be available on both Web and REST. Here is my example code and compilation errors bellow: [snip] AuthInfo authenticate(scope HTTPServerRequest req, scope HTTPServerResponse res) @safe [snip] And im getting such errors: ms-frontpage ~master: building configuration "application"... ../../.dub/packages/vibe-d-0.7.31/vibe-d/source/vibe/http/server.d(286,33): Deprecation: alias diet.traits.FilterCallback is deprecated - Use SafeFilterCallback instead. source/app.d(14,31): Error: cannot create instance of interface IfOAuthAPI source/service/oauth.d(35,8): Error: @safe function 'oauth.OAuthAPI.authenticate' cannot call @system function 'vibe.http.session.Session.opCast' [snip] Are you aware what @safe does? If you remove it, it probably compiles. From @safe functions you cannot call functions that are not marked @safe or @trusted [1]. Regards, Bastiaan. [1] https://dlang.org/spec/function.html#function-safety
Re: trait detecting anonymous union?
On Tuesday, 23 May 2017 at 01:02:59 UTC, Vladimir Panteleev wrote: On Monday, 22 May 2017 at 21:03:42 UTC, Bastiaan Veelo wrote: Is there a way to detect at CT that S has overlapping data members, when an anonimous union is used as above? I have an implementation here: https://github.com/CyberShadow/rclidasm/blob/31bde3347ec1259026b6ab15e2305f2a99e63a30/src/rclidasm/meta.d#L110-L183 Interesting work. Thanks or sharing! Bastiaan.