Re: how to debug memory errors
On Tuesday, 8 November 2016 at 07:39:12 UTC, Era Scarecrow wrote: On Tuesday, 8 November 2016 at 06:04:59 UTC, thedeemon wrote: On Tuesday, 8 November 2016 at 05:36:22 UTC, Era Scarecrow wrote: Hmmm.. I had the impression that if something was referenced by another object, then it couldn't be collected, Another *live* object, I.e. reachable from globals and stack. If you have a big tree and it becomes unreachable (you only had a pointer to its root and you nulled it), then this whole tree becomes garbage, and its nodes and leafs will be collected in unpredictable order, with destructors being run in unpredictable order, even when these dead nodes reference each other. And I can't help but hope it would start at the largest/base object and work it's way up. Or the largest object and then work it's way down. Alright... One of the reasons it is not specified is that very often the hierarchy is not a simple tree, but a graph with possibly many cycles. As a matter of fact, very often child nodes have pointers to parent nodes, so that what is logically a tree is practically a graph with lots of cycles. So it is not possible to identify a root object which does not have incoming dead pointers, and no guarantee can be provided.
Re: how to debug memory errors
On Sunday, 6 November 2016 at 21:46:52 UTC, Øivind wrote: Hi, My app occasionally gives me a *** Error in `./hauto-test': double free or corruption (fasttop): 0x7f504c002a60 *** but gives me the following on every termination core.exception.InvalidMemoryOperationError@src/core/exception.d(693): Invalid memory operation How do I go about debugging and resolving these? -Øivind I think that "Invalid Memory Operation" is the error the GC gives you when you try to allocate memory during the collection phase (i.e. inside a destructor). I suggest you avoid doing so. I don't know if the double free problem is related to this. It may as well be a totally unrelated bug of some container you are using.
Re: check instance of nested variadic template
On Saturday, 5 November 2016 at 13:34:51 UTC, Gianni Pisetta wrote: When i have time i will test it with ldc and see if the result is the same, then it will probably be a front-end bug and i will report it as an issue. I think it has already been reported. https://issues.dlang.org/show_bug.cgi?id=13372
Re: strange -fPIC compilation error
On Tuesday, 1 November 2016 at 18:13:32 UTC, TheGag96 wrote: On Monday, 31 October 2016 at 07:16:50 UTC, Sebastien Alaiwan wrote: Hello, From GCC 6.2, -fpie is becoming the default setting at compile and at link time. As dmd uses GCC to link, now the code needs to be compiled with a special option. Which means you need, at the moment, to add the following options to your dmd.conf: -defaultlib=libphobos2.so -fPIC (the change from GCC is related to security and address space randomization). So does this mean it's now impossible to compile statically until this gets fixed? It's impossible with the default `libphobos2.a`. I didn't try, but I'm quite confident that if you clone the Phobos repository and rebuild the library yourself with -fPIC, you can then link it statically to PIE executables.
Re: strange -fPIC compilation error
On Monday, 31 October 2016 at 00:08:59 UTC, Charles Hixson wrote: So now I removed the repository version of dmd and dub, downloaded DMD64 D Compiler v2.072.0-b2, used dkpg to install it, and appear to get the same errors. (Well, actually I removed the commenting out of the code, but it compiles and runs properly with ldc2.) I don't think it's a problem of DMD. This is due to your gcc installation being hardened, that is, configured to produce PIE by default. To produce PIE, the linker needs to be fed PIC, which DMD does not produce by default. The -fPIC flags makes DMD produce PIC out of your sources. The problem is, libphobos2.a (the static version of Phobos) is not compiled with -fPIC, so even if your code is PIC, gcc will complain. The workaround is to use -defaultlib=libphobos2.so to dynamically link with the shared version of Phobos. Being it a shared object, it does not give any problem with PIE. Looking on internet, I didn't find any clue about Debian shipping an hardened gcc, but this is the only cause I can think of for the behaviour you are experiencing.
Re: Parse a String given some delimiters
On Sunday, 30 October 2016 at 20:50:47 UTC, Alfred Newman wrote: Hello, I'm migrating some Python code to D, but I stuck at a dead end... Sorry to provide some .py lines over here, but I got some doubts about the best (fastest) way to do that in D. Executing the function parsertoken("_My input.string", " _,.", 2) will result "input". Parsercount("Dlang=-rocks!", " =-") will result 2, Thanks in advance You can take inspiration from the following snippet: = import std.stdio, std.regex; void main() { string s = "Hello.World !"; auto ss = split(s, regex(`\.| `)); ss.length.writeln; ss[1].writeln; } =
Re: strange -fPIC compilation error
On Sunday, 30 October 2016 at 18:02:28 UTC, Charles Hixson wrote: dmd --version DMD64 D Compiler v2.071.2 Copyright (c) 1999-2015 by Digital Mars written by Walter Bright on debian testing. dub is installed via apt-get. Should I revert to an earlier version? Or what? The program: importstd.stdio; voidmain() {//int[]t1; //t1~=1; //t1~=2; //writeln ("t1 = ", t1); } fails with the 442 lines of error: /usr/bin/ld: test.o: relocation R_X86_64_32 against symbol `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(exception_224_3b4.o): relocation R_X86_64_32 against symbol `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(exception_227_4a2.o): relocation R_X86_64_32 against symbol `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(exception_229_5cc.o): relocation R_X86_64_32 against symbol `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(dmain2_626_47b.o): relocation R_X86_64_32 against symbol `_D6object9Throwable7__ClassZ' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(dmain2_628_776.o): relocation R_X86_64_32 against symbol `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(dwarfeh_62b_6b9.o): relocation R_X86_64_32 against symbol `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC ... /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(aaA_51a_53e.o): relocation R_X86_64_32 against symbol `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Nonrepresentable section on output collect2: error: ld returned 1 exit status --- errorlevel 1 Are you on Ubuntu 16.10, or some other system with an hardened toolchain? If that's the case, you should compile with `-fPIC -defaultlib=libphobos2.so`. You can put those options in your dmd.conf configuration file, so that you don't have to type them every time.
List defined version specifications
Hi! A simple question: is there a way to list all defined version specifications? Something like: pragma(msg, __traits(allVersions)); Example output (DMD on Ubuntu x64, release build): [all, D_InlineAsm_X86_64, X86_64, Posix, linux, DigitalMars, CRuntime_Glibc, D_Version2, LittleEndian, D_LP64, D_HardFloat, D_SIMD, D_NoBoundsChecks, ELFv2] Thank you in advance.
Re: Symbol lookup failed in imported module
On Sunday, 2 October 2016 at 20:12:16 UTC, rumbu wrote: [...] I think you'll find the following article really interesting. It talks exactly about what you are experiencing. http://dlang.org/hijack.html
Re: Getting consistent behavour for class properties
On Sunday, 2 October 2016 at 17:10:58 UTC, mikey wrote: There is already a degree of transparency with how properties being handled for example in allowing properties to be an lvalue if they have a setter. t.val = 42; Actually, this is not specific to properties, as it also works on "standard" methods, if they have a single parameter: import std.stdio; void main() { writeln = 42; }
Re: Getting consistent behavour for class properties
On Sunday, 2 October 2016 at 14:26:46 UTC, mikey wrote: [...] Yeah, a property is quite different from a variable. In fact, a property may refer to a computed value, which may not have an address and as such cannot be modified: @property auto currentTimeMillis() { return currentTimeNanos/100; } So it is correct that `+=` doesn't work with properties, and neither does the "addressof" operator `&` (it returns the delegate). Having a getter property return by ref circumvents this issue, but has the drawback of bypassing any check that a setter property would do. If you want to use properties as getters/setters and also want compound assignments to work, you can easily achieve that with a wrapper template as this[1] one. [1] http://pastebin.com/38n0fEtF
Re: how to access struct member using [] operator?
On Sunday, 25 September 2016 at 09:01:44 UTC, Namespace wrote: import std.stdio; struct Something { int x, y; float z; auto opIndex()(string member) { switch (member) { case "x": return this.x; case "y": return this.y; case "z": return this.z; default: assert(0); } } } void main(string[] args) { Something s; writeln(s["x"]); writeln(s["z"]); } Doesn't work. s["x"] is returned as float in this example. The reason is, opIndex cannot magically change return type based on the passed-in string.
Re: Can someone explain to me the design choices for this function definition?
On Thursday, 22 September 2016 at 20:35:13 UTC, e-y-e wrote: [...] Disclaimer: my answers are just early guesses. 1. Why is openRight a runtime flag? Is there really a use case for this? Runtime evaluation is more flexible. The reason to have compile-time evaluation is to allowed aggressive specialization, highly tuned codegen and different attribute inference. If that flag is going to add a single very cheap branch (compared to the total cost), then it may not be worth to have it as a compile-time argument, as this would increase the number of instantiations and slightly reduce the flexibility. But there is a second possible explanation, see below. 2. Why is openRight not a Flag type? It may be that until is quite old, predating the extensive usage of Flag, and maybe also the extensive use of compile-time flags.
Re: D code optimization
On Thursday, 22 September 2016 at 16:09:49 UTC, Sandu wrote: It is often being claimed that D is at least as fast as C++. Now, I am fairly new to D. But, here is an example where I want to see how can this be made possible. So far my C++ code compiles in ~850 ms. I assume you meant that it runs in that time. While my D code runs in about 2.1 seconds. Benchmarking C++ vs D is less trivial than it looks, for various reasons: - compiler optimizations: - which compilers (both C++ and D) are you using? Are you aware of the differences in code optimization between DMD, GDC and LDC? - which flags are you passing to your C++ and D compilers? - your code is actually testing the compiler ability in loop unrolling, constant folding and operation hoisting - code semantics: C++ and D, when they look similar, they usually produce the same results, but the often behave very differently internally: - in the posted code you allocate a lot of managed memory, putting a big burden on the garbage collector, which in C++ you don't do, because you talk directly to the C runtime So it's difficult to extract useful data from this kind of benchmark.
Re: Module Clarification
On Thursday, 22 September 2016 at 14:29:20 UTC, Jonathan Marler wrote: Actually, the more I think about it, I'm not sure there's a good reason for the "package.d" semantics to exist. I guess it establishes a pattern when people would like to combine smaller modules into one public module, but it doesn't have to be used that way. The opposite is true that you could use a normal module (not a package.d module) to publicly import smaller modules: Instead of: foo/package.d // publically imports fooPart1 and fooPart2 foo/fooPart1.d foo/fooPart2.d What was wrong with: foo.d // still publically imports fooPart1 and fooPart2 foo/fooPart1.d foo/fooPart2.d If the package.d file didn't exist, then I don't think there would be any problem with hierarchical modules. Is this the right conclusion? Was package.d a mistake? Maybe the reasoning is that D doesn't really like hierarchical modules, so creating them should look a bit odd? foo/package.d foo/bar/package.d foo/bar/baz/package.d I think that having package.d provides a better layout. Look at the difference between this: ls std/experimental drw-rw-rw- allocator drw-rw-rw- logger drw-rw-rw- ndslice -rw-rw-rw- typecons.d and this: ls std/experimental drw-rw-rw- allocator -rw-rw-rw- allocator.d drw-rw-rw- logger -rw-rw-rw- logger.d drw-rw-rw- ndslice -rw-rw-rw- ndslice.d -rw-rw-rw- typecons.d Having to put part of a package outside the package folder is ugly to see and a bit more difficult to manage.
Re: Iterate over two arguments at once
On Monday, 19 September 2016 at 18:10:22 UTC, bachmeier wrote: Suppose I want to iterate over two arrays at once: foreach(v1, v2; [1.5, 2.5, 3.5], [4.5, 5.5, 6.5]) { ... } I have seen a way to do this but cannot remember what it is and cannot find it. You can use std.range.zip: https://dlang.org/phobos/std_range.html#.zip Or std.range.lockstep: https://dlang.org/phobos/std_range.html#.lockstep
Re: Embed glade file into a binary
On Saturday, 17 September 2016 at 19:01:10 UTC, Geert wrote: On Saturday, 17 September 2016 at 18:36:52 UTC, llmp wrote: On Saturday, 17 September 2016 at 18:18:37 UTC, Geert wrote: I've compiled a small application, and it runs when i execute it at the same directory where is the glade file. Is there a way to embed a glade file into a binary? enum fileContent = import(file); fileContent is a static array of ubyte. the compiler must know the path to "file" via -J"dir/subdir" Thanks! I've just tried that, but i get an error message with the xml file content, and this at the end: // More XML here... True True name="receives_default">True True True 2 True True 6 ': File name too long // End of message. This is part of the application code: [...] enum fileContent = import("vista.glade"); [...] g.addFromFile(fileContent); window = cast(Window)g.getObject("Win_01"); } // More code here ... } [...] addFromFile expects the *name* of the file. Because you already have the *contents* of the file, you should change method. Maybe addFromString is the correct one, but I'm not sure.
Re: Mutable class reference to immutable class
On Saturday, 10 September 2016 at 19:46:51 UTC, Jonathan Marler wrote: This is been bugging me for a while. Is it possible to have a mutable reference to an immutable class? [...] You are probably looking for std.typecons.Rebindable: https://dlang.org/phobos/std_typecons.html#.Rebindable
Re: inferred vs. annotated attributes
On Saturday, 10 September 2016 at 08:23:35 UTC, Q. Schroll wrote: Is there a difference between inferred and annotated attributes? Example: struct X(T) { this(S)(in S[] arr) // inferred pure { } } void main() pure { X!uint mut = [ 1, 2 ]; // proves inference (cf. main is pure) // immutable X!uint imm1 = [ 1, 2 ]; // auto imm2 = immutable X!uint([1, 2]); } The commented lines yield error messages claiming the constructor cannot deduce function from argument types !()(int[]) immutable, however it can, if "pure" is explicitly annotated. Is this a bug or did I get something wrong about inference / unique expressions? A method (included ctors) that is not annotated const, nor immutable, nor inout, is implicitly mutable. This implies that your ctor is mutable, and as such it cannot create immutable instances. If you add another ctor marked immutable, everything works. An alternative is to mark the ctor as inout. I tested this solution and it works, but I'm not sure if it is by design.
Re: Functions, nothrow and assert
On Thursday, 8 September 2016 at 11:40:17 UTC, Russel Winder wrote: Is the fact that: void f() nothrow { assert(1 == 0); } int main() { f(); return 0; } compiles fine but at run time f does indeed throw an exception what should happen? If it is what does nothrow actually mean? To expand on the previous correct answers, nothrow is about not throwing Exceptions. Exceptions are part of the normal flow of the program: they are used to signal recoverable errors, much like error codes. Errors, on the other hand, are unrecoverable system failures that should not be catched (catching them is undefined behaviour, I think) and will surely lead to a crash. Errors are not covered by nothrow. Asserts throw Errors, not Exceptions. The reason is that asserts are used to test conditions that must hold, at the point that an optimizing compiler can analyze the expression inside the assert and optimize the executable based on the truthness of that condition. So if an assert is found false at runtime, the code may not be able to work at all. That's why asserts throw Errors and not Exceptions.
Re: Instantiating a class with range template parameter
On Thursday, 8 September 2016 at 08:20:49 UTC, Jon Degenhardt wrote: I've been generalizing output routines by passing an OutputRange as an argument. This gets interesting when the output routine is an virtual function. Virtual functions cannot be templates, so instead the template parameters need to be part of class definition and specified when instantiating the class. An example is below. It works fine. One thing I can't figure out: how to provide the range parameter without first declaring a variable of the appropriate type. What works is something like: auto writer = stdout.lockingTextWriter; auto x = new Derived!(typeof(writer)); Other forms I've tried fail to compile. For example, this fails: auto x = new Derived!(typeof(stdout.lockingTextWriter)); I'm curious if this can be done without declaring the variable first. Anyone happen to know? --Jon Full example: import std.stdio; import std.range; class Base(OutputRange) { abstract void writeString(OutputRange r, string s); } class Derived(OutputRange) : Base!OutputRange { override void writeString(OutputRange r, string s) { put(r, s); put(r, '\n'); } } void main() { auto writer = stdout.lockingTextWriter; auto x = new Derived!(typeof(writer)); x.writeString(writer, "Hello World"); } I think that auto x = new Derived!(typeof(stdout.lockingTextWriter()))(); // note the parenthesis should work. But usually, you save the writer inside the object and make a free function called `derived` (same as the class, but with lowercase first). You define it this way: auto derived(OutputRange)(auto ref OutputRange writer) { auto result = new Derived!OutputRange(); result.writer = writer; // save the writer in a field of the object return result; } void main() { auto x = derived(stdout.lockingTextWriter); x.writeString("Hello world"); // the writer is saved in the object, no need to pass it }
Re: Templates problem
On Wednesday, 7 September 2016 at 11:37:44 UTC, Russel Winder wrote: I'd prefer immutable, but const sometimes has to do. The idea is to find out how to enforce single assignment in D. Everything depends on what you mean by "single assignment". If you mean "I can't use opAssign", then const is definitely too strong. In this case, you can write a simple type wrapper that disables opAssign, while providing all other functionalities. If you mean "Methods do not mutate objects; instead, they return new objects, mutated", the issue is deeper. In fact, input ranges and output ranges cannot (by definition) fulfill this requirement. Other ranges (forward, bidirectional, random) can fulfill this requirement, but it's very expensive, as it requires a new copy of every range every time you want to popFront or popBack. The same goes for every other type with mutable methods. If you really want this behaviour, you can easily write (again) a type wrapper that forwards every const method call while intercepting every mutable method call and applying it to a new copy that is returned. But I think it will severely hurt performance and readability.
Re: Templates problem
On Wednesday, 7 September 2016 at 08:19:39 UTC, Russel Winder wrote: On Tue, 2016-09-06 at 14:50 +, Lodovico Giaretta via Digitalmars-d- learn wrote: […] From a quick look, it looks like `results` is a `const(TickDuration[3])`, that is a fixed-length array. And fixed-length arrays aren't ranges. If you explicitly slice them, they become dynamic arrays, which are ranges. So the solution is to call `map` with `results[]` instead of `results`. So trying with results[] leads to: run_checks.d(21): Error: mutable method std.algorithm.iteration.MapResult!(function (TickDuration t) => to(t).total(), const(TickDuration)[]).MapResult.opIndex is not callable using a const object run_checks.d(21): Error: mutable method std.algorithm.iteration.MapResult!(function (TickDuration t) => to(t).total(), const(TickDuration)[]).MapResult.opIndex is not callable using a const object run_checks.d(21): Error: mutable method std.algorithm.iteration.MapResult!(function (TickDuration t) => to(t).total(), const(TickDuration)[]).MapResult.opIndex is not callable using a const object yes, the message is repeated three times, for unknown reason. Possibly because the compiler is fairly certain I am not going to believe it. So the upshot of this is that I can't work with const data, which is dreadful in these days of single assignment being the way of doing things. So what is the way of constructing a range from a const array? If it involves copying then D is doomed. And yes I am under stress as I am trying to pitch D to Python people next week. You have your const fixed-length array. You slice it and you obtain a const range to feed map. Now map will not return you an array. Because most of the time you don't need it. It will return you a range that lazily computes its elements on demand. No memory allocation at all. You can do a foreach on that range. If you need to access those elements more than once, instead of recomputing each of them every time it is accessed, you can store the results of the map. You simply have to use .array on the map result. This will allocate memory and give you an array with your results. Otherwise, no allocation at all. That result array can be const, if you want. If you need to access your elements only once, there's no need to have an array. I really don't see what's not working in this. And by the way, there's no need to put const on everything. An optimizing compiler is often able to infer things, especially for stack allocated local variables.
Re: Template constraints for reference/value types?
On Tuesday, 6 September 2016 at 20:46:54 UTC, Jon Degenhardt wrote: Is there a way to constrain template arguments to reference or value types? I'd like to do something like: T foo(T)(T x) if (isReferenceType!T) { ... } --Jon You can use `if(is(T : class) || is(T : interface))`. If you also need other types, std.traits contains a bunch of useful templates: isArray, isAssociativeArray, isPointer, ...
Re: Templates problem
On Tuesday, 6 September 2016 at 14:38:54 UTC, Russel Winder wrote: The code fragment: const results = benchmark!(run_mean, run_mode, run_stdDev)(1); const times = map!((TickDuration t) { return (to!Duration(t)).total!"seconds"; })(results); seems entirely reasonable to me. However rdmd 20160627 begs to differ: run_checks.d(20): Error: template std.algorithm.iteration.map!(function (TickDuration t) => to(t).total()).map cannot deduce function from argument types !()(const(TickDuration[3])), candidates are: /usr/include/dmd/phobos/std/algorithm/iteration.d(450): std.algorithm.iteration.map!(function (TickDuration t) => to(t).total()).map(Range)(Range r) if (isInputRange!(Unqual!Range)) Failed: ["dmd", "-v", "-o-", "run_checks.d", "-I."] and I have no idea just now why it is complaining, nor what to do to fix it. From a quick look, it looks like `results` is a `const(TickDuration[3])`, that is a fixed-length array. And fixed-length arrays aren't ranges. If you explicitly slice them, they become dynamic arrays, which are ranges. So the solution is to call `map` with `results[]` instead of `results`.
Re: Inexplicable invalid memory operation when program terminates
On Monday, 5 September 2016 at 17:33:17 UTC, pineapple wrote: I have a program which I have stripped down to a single offending line which, when present in my program, causes an invalid memory operation to occur after main has evaluated: import mach.sdl.window; void main(){ auto win = new Window(300, 300); } The program is a bit larger than that, but I do not get the error when I comment out that instantiation and the things dependent on it. I commented out the body of the constructor that is being called, and I still get the error. Am I missing something or is this an obnoxious bug with the GC? InvalidMemoryOperationError is raised when you try to allocate memory inside a destructor called by the GC. I see from your repository that the destructor of Window uses a function called log defined by yourself. That function uses writeln internally. writeln is not @nogc, so it may be that that call to log in the destructor is actually allocating memory.
Re: Getting the superclass of a type?
On Monday, 5 September 2016 at 15:20:10 UTC, pineapple wrote: I'd like to be able to write something like this, but I haven't been able to find anything in the docs class Base{} class Sub: Base{} static assert(is(SuperClassOf!Sub == Base)); https://dlang.org/phobos/std_traits.html#.BaseClassesTuple
Re: delegates, lambdas and functions pitfall
On Monday, 5 September 2016 at 12:15:35 UTC, dom wrote: [...] You misunderstood the error message and the lambda syntax (it also happened to me the first time). The grammar says that you can use one of these syntaxes: 1) `(arguments) {block of code}` 2) `(arguments) => expression`, which is equivalent to `(arguments) {return expression;}` 3) `{block of code}`, which is equivalent to `(){block of code}`. So if you write `(arguments) => {block of code}`, this is equivalent to (see rule 2) `(arguments) { return {block of code}; }`. And because of rule 3, it becomes `(arguments) { return (){block of code} }`. So what you have is a function that returns a function. That's why it does not match your signature. The fact that the compiler also adds nothrow, @nogc, @safe is not important in this case, as those attributes can be implicitly casted away.
Re: How it's better to store data from DB?
On Monday, 5 September 2016 at 10:00:26 UTC, Suliman wrote: Usually I am storing daba from DB as array of structures. Something like: struct MyData { int id; string name; int age; } MyData mydata; Then I am creating array of structures: MyData [] mydatas; And fill data in my code. Then append it to `mydatas` to get it iterable. But is it's good? Maybe there there is better way? I need main -- be able iterate thru the data. Any other variants? It depends on your specific use case. My advice is to try *not* to store the data in memory. I mean, if your first operation on the array is to filter it (but that should be done directly in the sql queries) or if you manage to do everything while iterating it only once, then you can avoid creating the array. Create a range that wraps the query result set and iterate it. This way you maintain in memory just one element at a time. This is akin to what you usually do in JDBC (I used that a lot, while in D I don't have any db experience). But of course there are cases in which this advice is not applicable.
Re: Template-style polymorphism in table structure
On Monday, 5 September 2016 at 06:45:07 UTC, data pulverizer wrote: On Sunday, 4 September 2016 at 14:49:30 UTC, Lodovico Giaretta wrote: Your getCol(i) could become getCol!T(i) and return an instance of GenericVector!T directly, after checking that the required column has in fact that type: GenericVector!T getCol!T(size_t i) { if(typeid(cols[i]) == typeid(GenericVector!T)) return cast(GenericVector!T)cols[i]; else // assert(0) or throw exception } I just realized that typeid only gives the class and not the actual type, so the object will still need to be cast as you mentioned above, however your above function will not infer T, so the user will have to provide it. I wonder if there is a way to dispatch the right type by a dynamic cast or I fear that ZombineDev may be correct and the types will have to be limited, which I definitely want to avoid! ZombineDev is definitely correct, in that one thing is the static type, and another thing is the dynamic type. The type of a variable, or the return type of a method are based on the static type, computed at compile time. The "true" dynamic type is only available at runtime. That's why I was showing you the use of tuples. If your code does not have branches that assign different column types, having the types statically determined as template parameters is the best choice. If you really need dynamic types, then there's no alternative: the user must explicitly cast things to the correct dynamic type (my version of getCol is just a nice wrapper to do that). In fact, idiomatic D code tries to avoid dynamic types when possible, preferring templates.
Re: How compiler detects forward reference errors
On Sunday, 4 September 2016 at 19:15:15 UTC, Igor wrote: So, you are saying compiler is keeping a kind of linked list of dependencies and then checks if any of those lists are circular? But how exactly would that list be structured since one expression can have multiple dependencies, like: enum a = b + c + d + e; enum b = 10 + c; enum c = d + e + a; ... Disclaimer: I don't know how the D compiler works internally. I just happen to know how generic compilers usually work. I think the easiest solution is to keep a stack of what you are doing. So in your last example, we start with evaluating a. We first see that a depends on b. So we switch evaluating b. As we do so, our stack contains a and b. We see that b depends on c. So we switch to evaluate c. Our stack becomes a, b, c. We see that c depends on d. So we evaluate d. Our stack is a, b, c, d. You didn't give a definition for d. Let's assume it does not depend on anything. So we successfully evaluated d. So we get back to c. Our stack is a, b, c. We see that c also depends on e. So we evaluate e. Our stack is a, b, c, e. You didn't give a definition for e. Let's assume it does not depend on anything. So we successfully evaluated e. So we get back to c. Our stack is a, b, c. We see that c also depends on a. So we evaluate a. Our stack becomes a, b, c, a. Ops... Our stack contains a two times. This means that to evaluate a we need the value of a. So we tell the user that we cannot proceed further. By the way, the stack also tells us how a depends on itself. In fact, the stack a, b, c, a tells us that a depends on b which depends on c which depends on a. I hope this is a clear enough explanation. If not, feel free to ask further.
Re: Template-style polymorphism in table structure
On Sunday, 4 September 2016 at 14:24:12 UTC, data pulverizer wrote: On Sunday, 4 September 2016 at 14:20:24 UTC, data pulverizer wrote: On Sunday, 4 September 2016 at 14:07:54 UTC, data pulverizer wrote: @Lodovico Giaretta Thanks I just saw your update! @Lodovico Giaretta BTW what do you mean that my code is not very D style? Please expand on this ... The constructors can be less. In fact, a typesafe variadic ctor also works for the single element case and for the array case. But you already recognized that. Instead of reinventing the wheel for your GenericVector!T, you could use an `alias this` to directly inherit all operation on the underlying array, without having to reimplement them (like your append method). Your getCol(i) could become getCol!T(i) and return an instance of GenericVector!T directly, after checking that the required column has in fact that type: GenericVector!T getCol!T(size_t i) { if(typeid(cols[i]) == typeid(GenericVector!T)) return cast(GenericVector!T)cols[i]; else // assert(0) or throw exception } Another solution: if you don't need to dynamically change the type of the columns you can have the addColumn function create a new type. I show you with Tuples because it's easier: Tuple!(T,U) append(U, T...)(Tuple!T tup, U col) { return Tuple!(T,U)(tup.expand, col); } Tuple!int t1; Tuple!(int, float) t2 = t1.append(2.0); Tuple!(int, float, char) t3 = t2.append('c');
Re: Template-style polymorphism in table structure
On Sunday, 4 September 2016 at 09:55:53 UTC, data pulverizer wrote: [...] Your code is not very D style and, based on your needs, there may be better ways to achieve your goal, but without knowing your use case, it's difficult to give correct advice. Talking about that writeln statement, your code is not working because of a known compiler bug [1]. If you change your interface BaseVector to an abstract class and add the needed override annotation to GenericVector, then typeid returns the expected result. [1] https://issues.dlang.org/show_bug.cgi?id=13833
Re: How compiler detects forward reference errors
On Saturday, 3 September 2016 at 14:06:06 UTC, Igor wrote: Can anyone explain in plain English how does compiler process and detect a "test.d(6) Error: forward reference of variable a" in following code: import std.stdio; enum a = 1 + b; enum d = 5 + a; // No error here enum b = 12 + c; enum c = 10 + a; // error here void main() { writeln("Hello World!", b); } a needs b to be initialized. So b must be initialized before a. Let's write this b->a. Now b needs c. So c->b. c needs a, so a->c. If we sum everything, we have that a->c->b->a. This mean that to initialize a we need b, to initialize b we need c, but to initialize c we need a. So to initialize a we need a, which is not possible. We need a before having initialized it. On the other hand, a->d is not a problem, as d can be initialized after a.
Re: InterlockedIncrement, InterlockedCompareExchange, etc
On Sunday, 28 August 2016 at 21:52:48 UTC, Illuminati wrote: The interlocked functions generate memory barriers, does atomicOp do that? Also D doesn't seem to have a volitile keyword anymore which is required to prevent the compiler from prematurely optimizing critical code. I'm under the impression that atomicOp does not generate memory barriers. In fact, in its implementation, it uses atomicLoad with relaxed memory ordering. There is however a function in core.atomic to generate a full memory barrier, if you need it. By the way, can I ask you why you need this? Is it for low-level data sharing or for hardware access? If it is for low-level data sharing, then you probably don't need volatile, as shared should be enough. If it is for hardware access, the situation is more complex, but I'm sure I've seen some threads about how to implement Volatile!T in a few lines of code recently.
Re: InterlockedIncrement, InterlockedCompareExchange, etc
On Sunday, 28 August 2016 at 19:53:51 UTC, Illuminati wrote: What are the D equivalents to these types of functions? I do not see anything in core.atomic that can accomplish this. I have tried to include core.sys.windows.winbase but still get linker errors(I've also directly tried importing kernel32 using various methods and still nothing). Regardless, would be nicer to have a more portable solution. I'm not an expert in this field (so probably I'm missing something), but I would think that InterlockedIncrement could be done with atomicOp!"+"(val, 1) and InterlockedCompareExchange with cas.
Re: __traits(getOverloads, Type, member) order of elements in tuple.
On Monday, 22 August 2016 at 12:14:41 UTC, Alexandru Ermicioi wrote: Good day. In current implementation of dmd/ldc/gdc, does this trait guarantee, that the order of elements returned in tuple, is same, in several calls of it on same Type and member? Also, is guaranteed that in future versions of dmd, the order of elements won't change? The official spec [1] does not state anything about this, but for other similar traits it says that the order is not defined and should not be relied upon, so I'm inclined to think that getOverloads works that way too. Definitely worth an enhancement request, to document this thing. [1] https://dlang.org/spec/traits.html
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 20:36:54 UTC, Engine Machine wrote: On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta wrote: [...] You're right. I didn't realize that variables could be shadowed in classes. Seems dangerous. D doesn't allow shadowing in a normal context and gives an error so I don't know why it wouldn't do that in classes. (since it wasn't giving an error I thought it wasn't shadowing) You are right. It is very bad. But as far as I know Java and C++ allow this too. I will open an enhancement request (if there's none about this), to gather some feedback on the matter.
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta wrote: On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote: [...] The problem of this code has nothing to do with aliases. They work correctly. The problem is variable shadowing. In the following code, Child has two x variables, one of which is only accessible from a Parent reference, the other only from a Child reference. class Parent { int x; } class Child: Parent { int x; // this shadows Parent.x int y; } void main() { Child child = new Child(); Parent parent = child; child.x = child.y = 3; parent.x = 2; assert(child.x == 3); assert((cast(Child)parent).x == 3); assert((cast(Parent)child).x == 2); assert(parent is child); // same object (remember that a class is already a pointer); assert( != ); // but there are two different pointers on the stack (pointing to the same object) } A patch to your code that makes it work, with the parts not displayed unchanged: class base { int x; } class T(A...) : Rebind!(T!A, EraseLast!A) { static if(A[$-1] == "Animal") int y; else static if (A[$-1] == "Dog") int z; else static if (A[$-1] == "Pug") int s; }
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote: [...] The problem of this code has nothing to do with aliases. They work correctly. The problem is variable shadowing. In the following code, Child has two x variables, one of which is only accessible from a Parent reference, the other only from a Child reference. class Parent { int x; } class Child: Parent { int x; // this shadows Parent.x int y; } void main() { Child child = new Child(); Parent parent = child; child.x = child.y = 3; parent.x = 2; assert(child.x == 3); assert((cast(Child)parent).x == 3); assert((cast(Parent)child).x == 2); assert(parent is child); // same object (remember that a class is already a pointer); assert( != ); // but there are two different pointers on the stack (pointing to the same object) }
Re: compile error while use `extern(C++, class)`
On Thursday, 18 August 2016 at 16:19:41 UTC, Johan Engelen wrote: On Thursday, 18 August 2016 at 11:43:03 UTC, Lodovico Giaretta wrote: Which compiler version are you using? On DMD 2.071.0 this does not work. Note: this does work with LDC 1.1.0 even though it is based on DMD 2.071. https://github.com/ldc-developers/ldc/releases/tag/v1.1.0-beta2 Well, LDC 1.1.0 is based on DMD 2.071.1, while I tested the above code on asm.dlang.org with DMD 2.071.0, so maybe on DMD 2.071.1 it works too. On nightly it works for sure. So again nothing wrong here, just a matter of having the most recent compiler version.
Re: compile error while use `extern(C++, class)`
On Thursday, 18 August 2016 at 11:11:10 UTC, mogu wrote: On Thursday, 18 August 2016 at 10:45:14 UTC, Lodovico Giaretta wrote: Which kind of error? An error message by the compiler? One by the linker? The compiler crashes? Compiler Error exactly. The minimal code is(dmd or ldc2 in ubuntu 16.04 lts): ``` extern (C++, struct) class A {} ``` Error: identifier expected for C++ namespace found 'struct' when expecting ')' declaration expected, not ')' Which compiler version are you using? On DMD 2.071.0 this does not work. On nightly build it compiles without errors. So probably it is a feature that is present, but didn't ship yet. I suggest you download the latest beta or a nightly build from the site.
Re: Sequence separation
On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote: On 08/17/2016 08:38 PM, Engine Machine wrote: On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta wrote: [...] You mean something like: struct MySequence(Args...) { enum length = Args.length; alias args = Args; } alias x = MySequence!(a, b, MySequence!(c, d)); static assert(x.length == 3) static assert(x.args[2].length == 2); Thanks, basically works. How can I test, though, if a argument uses a MySequence? I can't do if (Args[0] == MySequence) because MySequence is templated. While I could test for a length, that doesn't work because some types have a length. I could add another enum to MySequence, but again, not safe. I could do some string tests, but that doesn't work. in your exmaple, if (x.args[2] == MySequence) ?? I simply need to differentiate between a parameter/arg being a MySequence and not. With MySequence being a type, you can do this: static if (is(x.args[2] == MySequence!Args, Args ...)) { ... } Aside from this check, there is probably not much use for MySequence being a type. So I'm be tempted to find a way to do the check with a raw template MySequence. import std.traits: TemplateOf; static if (__traits(isSame, TemplateOf!(x.args[2]), MySequence)) { ... } std.traits.TemplateOf extracts the symbol representing the uninstantiated template. __traits(isSame, symbol1, symbol2) evaluates at compile time to true if and only if the two symbols represent the same thing (be it a type, an uninstantiated template, an instantiated one or whatever else).
Re: having a trivial anonymous function call in template prevents compilation?
On Wednesday, 17 August 2016 at 13:21:16 UTC, Cauterite wrote: On Wednesday, 17 August 2016 at 13:18:06 UTC, Adam D. Ruppe wrote: Best you can do is use them in an alias argument directly, but you cannot use them in an enum argument. I think you missed the point; it works perfectly fine without having this `({return 0;})()` in the template body (which, as far as I can see, doesn't appear to interact at all with the template argument). I think he meant that ({ return 0;})() cannot be executed at compile time and assigned to an enum. That's why the instantiation is failing.
Re: Sequence separation
On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe wrote: On Tuesday, 16 August 2016 at 19:17:27 UTC, Engine Machine wrote: alias x = AliasSeq!(a, b, AliasSeq!(c, d)); results in a flat sequence. I would like to be able to keep them separate so I can have sub sequences. wrap them in a struct. You mean something like: struct MySequence(Args...) { enum length = Args.length; alias args = Args; } alias x = MySequence!(a, b, MySequence!(c, d)); static assert(x.length == 3) static assert(x.args[2].length == 2);
Re: Template type reduction
On Tuesday, 16 August 2016 at 19:23:51 UTC, Engine Machine wrote: On Tuesday, 16 August 2016 at 17:39:14 UTC, Lodovico Giaretta wrote: On Monday, 15 August 2016 at 19:31:14 UTC, Engine Machine wrote: [...] I don't know if this is exactly what you want: = import std.traits: hasMember; struct Q(T) if (hasMember!(T, "x")) { T s; @property auto x() { return s.x; } } auto makeQ(T)(auto ref T val) { return Q!T(val); } auto s = myTypeWithFieldX(); auto q = makeQ(s); assert(q.x == s.x); = `Q` can store any type with an `x` field and gives access to it. The auxiliary function `makeQ` acts as a constructor for `Q` with template parameter deduction. I realize now that D simply cannot do what I ask directly because It's type parameters are part of the type. It can't be told that in some cases they are not. Any use of the parameters, as I am using them, will result in this issue. I'm now trying a different method which builds the based types using partial oop and partial CT code. The CT code is only for performance and convenience anyways. You are right in that it is not possible to strip part of the type informations. The only problem is Q is still defined by T. Your makeQ then requires the type implicitly, which I don't necessarily have. You've simply added complexity to the problem but the issue is still there. How is it possible that you don't have T? Your variable will surely have a type! Can you provide more background? Because maybe I'm not completely getting your point here...
Re: Template type reduction
On Monday, 15 August 2016 at 19:31:14 UTC, Engine Machine wrote: Suppose I have a templated type like struct S(T) { int x; static if (T is Y) int y; } I would like to be able to create a reference to S(T) for any T, struct Q { S!* s; // Can hold any type of S. } and be able to access s.x, since it is common to all S. Can D do anything like this? It is sort of like runtime inheritance, but at the compile time level. I do not want to have to cast to S!T every time just to access x, e.g., struct Q { Object s; } which is too general as s can be things that are not of type S!*. Is this possible? I don't know if this is exactly what you want: = import std.traits: hasMember; struct Q(T) if (hasMember!(T, "x")) { T s; @property auto x() { return s.x; } } auto makeQ(T)(auto ref T val) { return Q!T(val); } auto s = myTypeWithFieldX(); auto q = makeQ(s); assert(q.x == s.x); = `Q` can store any type with an `x` field and gives access to it. The auxiliary function `makeQ` acts as a constructor for `Q` with template parameter deduction.
Re: Converting a Visual Studio Solution with many Projects into DUB package?
On Tuesday, 16 August 2016 at 15:46:23 UTC, WhatMeWorry wrote: I've got a large Visual Studio Solution which contains lots of Projects. Each project is a standalone D/OpenGL tutorial. I want to make it OS and IDE agnostic so it can be easily played with on Windows, Linux, and Mac OS so I thought it best to make it a dub package. I've been reading the DUB documentation but can't seem to find a way. So in short, does DUB allow something like sub-packages? Or collections of packages? No is fine. I just wanted to check before I go off and create a flat file system of dub packages. I think you are looking for this: https://code.dlang.org/package-format?lang=json#sub-packages
Re: new XML and JSON libs and replacement of std.net.curl
On Monday, 15 August 2016 at 15:01:13 UTC, Oleg B wrote: Hello. In std.xml docs I read that is deprecated, [...] For XML I found this project https://github.com/lodo1995/experimental.xml. Is this really candidate to std, or author just called it as he want? Hi! I'm the developer of that XML library. It is still under heavy development, so if you decide to use it and find any problem, feel free to contact me on GitHub. Feedback from actual usage is very important to understand what needs more work. Thank you. As a side note, the GSoC is almost over, so the iter for inclusion in Phobos should start soon.
Re: Retreive method given object, name and arguments
On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe wrote: Is there a way to implement "getSymbolOfCall" and "getDelegateOfCall" such that doit is functionally equivalent to calling the method directly? auto doit(C, string methodName, Args...)(C c, Args args) { alias methodSymbol = getSymbolOfCall!(c, methodName, Args); pragma(msg, hasUDA!(methodSymbol, "my attr")); auto dg = getDelegateOfCall!(c, methodName, Args); return dg(args); } They should deal with getting the right overload, opDispatch-ing, and deducing template arguments from the real argument list to get a concrete delegate pointer. methodSymbol should give access to compile-time introspection like full signature and UDAs. The ability to do this for non-member functions would be cool too, but is beyond my use case. Maybe I'm not understanding correctly, but I think you can use string mixins: auto doit(string methodName, C, Args...)(C c, Args args) { mixin("return c." ~ methodName ~ "(args);"); }
Re: Template parameters that don't affect template type
On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote: [...] If, in your case, it is possible to use one type as the other, then specify it. I mean, implement a templated opAssign that allows you to assign values of one instantiation to values of another. While doing so, remember that this will not change the behaviour of the assigned-to variable, but will only transfer the runtime state from one variable to the other. struct S(T1, T2) { T1 t; void opAssign(T)(auto ref S!(T1, T) other) { t = other.t; } } unittest { S!(int, float) x(1); S!(int, char) y(3); x = y; assert(x.t == 3);// the value of x is changed static assert(is(typeof(x) == S!(int, float))) // the type of x isn't changed }
Re: Unexpected foreach lowering
On Wednesday, 10 August 2016 at 21:00:01 UTC, Lodovico Giaretta wrote: On Wednesday, 10 August 2016 at 20:54:15 UTC, Steven Schveighoffer wrote: [...] Wow. Thanks. I didn't know the compiler would try opSlice. I will file it. Filed on bugzilla: https://issues.dlang.org/show_bug.cgi?id=16374
Re: Unexpected foreach lowering
On Wednesday, 10 August 2016 at 20:54:15 UTC, Steven Schveighoffer wrote: On 8/10/16 2:08 PM, Lodovico Giaretta wrote: [...] The issue is that it tries using [] on the item to see if it defines a range-like thing. Since you don't define opSlice(), it automatically goes to the subrange. This breaks for int[] as well as Array. If I add opSlice to your code (and return this) it works. This is definitely a bug, it should try range functions before opSlice. Please file. -Steve Wow. Thanks. I didn't know the compiler would try opSlice. I will file it.
Re: Unexpected foreach lowering
On Wednesday, 10 August 2016 at 19:37:39 UTC, Ali Çehreli wrote: A quick read reveals popFront() is implemented only for bool Arrays. That explains the issue. I don't know whether it's an oversight. Ali First of all, thank you for spending your time on this issue. I really appreciate that. I may be reading that code wrong but... Isn't popFront implemented for every type here? https://github.com/dlang/phobos/blob/master/std/container/array.d#L128
Re: Unexpected foreach lowering
On Wednesday, 10 August 2016 at 18:38:00 UTC, Ali Çehreli wrote: RangeWrapper does not provide the InputRange interface, so the compiler uses 'alias this' and iterates directly on the member range. I tried making RangeWrapper an InputRange but failed. It still uses 'range'. // Still fails with these: @property bool empty() { return range.empty; } void popFront() { range.popFront(); } I don't know how the decision process works there. Ali That's strange, as RangeWrapper works correctly if instantiated with any underlying range EXCEPT std.container.Array. Also, RangeWrapper does provide the InputRange interface, partially directly and partially with alias this. RangeWrapper should be "opaque", as it should not matter whether the methods needed for the InputRange interface are defined directly or inherited with alias this.
Re: Unexpected foreach lowering
On Wednesday, 10 August 2016 at 18:08:02 UTC, Lodovico Giaretta wrote: I'm probably missing something stupid but... Why on earth do the two loops in main print a different result? It looks like the foreach lowering is ignoring my definition of front... = import std.stdio, std.container.array; struct RangeWrapper(Range) { Range range; alias range this; auto front() { return range.front + 1; } } auto rangeWrapper(Range)(auto ref Range range) { return RangeWrapper!Range(range); } void main() { Array!int array; array.insertBack(3); foreach (i; rangeWrapper(array[])) writeln(i); // prints 3, which is wrong // isn't the above foreach equivalent to the following loop ? for (auto r = rangeWrapper(array[]); !r.empty; r.popFront()) writeln(r.front); // correctly prints 4 } = Thank you for your help. This actually only happens with std.container.Array. Other ranges are ok. Even stranger...
Unexpected foreach lowering
I'm probably missing something stupid but... Why on earth do the two loops in main print a different result? It looks like the foreach lowering is ignoring my definition of front... = import std.stdio, std.container.array; struct RangeWrapper(Range) { Range range; alias range this; auto front() { return range.front + 1; } } auto rangeWrapper(Range)(auto ref Range range) { return RangeWrapper!Range(range); } void main() { Array!int array; array.insertBack(3); foreach (i; rangeWrapper(array[])) writeln(i); // prints 3, which is wrong // isn't the above foreach equivalent to the following loop ? for (auto r = rangeWrapper(array[]); !r.empty; r.popFront()) writeln(r.front); // correctly prints 4 } = Thank you for your help.
Re: Template method in interfaces
On Wednesday, 10 August 2016 at 15:54:42 UTC, Adam D. Ruppe wrote: On Wednesday, 10 August 2016 at 15:48:10 UTC, Lodovico Giaretta wrote: I read the spec again, and found out that it says interfaces cannot contain templated functions... So either my interpretation is the intended one and the spec is outdated, or the spec is right and the compiler is bugged. Spec must be out of date, I remember this being a conscious decision to add them. Last line of this page: https://dlang.org/spec/template.html#limitations I'll file a bug report for this and an enhancement request for implicit final in interfaces.
Re: Template method in interfaces
On Wednesday, 10 August 2016 at 15:48:10 UTC, Lodovico Giaretta wrote: On Wednesday, 10 August 2016 at 15:39:19 UTC, Arafel wrote: Would it even make sense to "force" (deprecation warning) a "final" keyword in any implicitly-final function (I wasn't even aware of those, I have to admit)? It would make things much clearer, like with "override"... I read the spec again, and found out that it says interfaces cannot contain templated functions... So either my interpretation is the intended one and the spec is outdated, or the spec is right and the compiler is bugged. Anyway what I said about implicit final is true for classes. In classes, I don't like the idea of having to put an explicit final, but this is debatable. For interfaces, I'm ok with forcing an explicit final attribute (but as I said the spec does not allow templated functions in interfaces, even if the compiler does).
Re: Template method in interfaces
On Wednesday, 10 August 2016 at 15:39:19 UTC, Arafel wrote: On Wednesday, 10 August 2016 at 15:25:40 UTC, Lodovico Giaretta wrote: Because templated functions cannot be virtual, it follows that I.func is final. Having no body, the compiler thinks that its body will be found by the linker in another object file, but this does not happen, so the linker complains. Being I.func final, C.func just hides it, so you would not incur any problem if you called func explicitly on an object of type C. So what you found is not a bug, but some unintuitive behaviour due to templated functions being implicitly final and forward declarations. Maybe the compiler should emit a warning about implicitly-final functions in interfaces. Would it even make sense to "force" (deprecation warning) a "final" keyword in any implicitly-final function (I wasn't even aware of those, I have to admit)? It would make things much clearer, like with "override"... I read the spec again, and found out that it says interfaces cannot contain templated functions... So either my interpretation is the intended one and the spec is outdated, or the spec is right and the compiler is bugged.
Re: Template method in interfaces
On Wednesday, 10 August 2016 at 15:20:37 UTC, Arafel wrote: I'm not sure if the following is even expected to work, since I'm not sure how the vtable for the interface would look like (well, that would be applicable to any overriden templated method, though): --- public interface I { void func(T)(T t); } public class C : I { void func(T)(T t) { } } void main() { I i = new C(); i.func(1); } --- But since the error I get is in the linker, and not in the compiler, I guess that's somehow a bug? Or how should it work then? https://dpaste.dzfl.pl/7a14fa074673 /d31/f76.o: In function `_Dmain': /d31/f76.d:(.text._Dmain+0x24): undefined reference to `_D3f761I11__T4funcTiZ4funcMFiZv' collect2: error: ld returned 1 exit status --- errorlevel 1 PS: Now I see [1] that it shouldn't, so perhaps the compiler should reject templated methods in interfaces from the beginning? [1]: http://forum.dlang.org/post/jg504s$1f7t$1...@digitalmars.com Because templated functions cannot be virtual, it follows that I.func is final. Having no body, the compiler thinks that its body will be found by the linker in another object file, but this does not happen, so the linker complains. Being I.func final, C.func just hides it, so you would not incur any problem if you called func explicitly on an object of type C. So what you found is not a bug, but some unintuitive behaviour due to templated functions being implicitly final and forward declarations. Maybe the compiler should emit a warning about implicitly-final functions in interfaces.
Re: When I should to call destroy?
On Friday, 29 July 2016 at 13:18:00 UTC, Suliman wrote: Use the `destroy` function to finalize an object by calling its destructor. The memory of the object is not immediately deallocated, instead the GC will collect the memory of the object at an undetermined point after finalization: class Foo { int x; this() { x = 1; } } Foo foo = new Foo; destroy(foo); assert(foo.x == int.init); // object is still accessible But I can't understand if D have GC it should remove objects when their life is finished. When I should to call `destroy`? What would be if I will not call it? Destroy will call the destructors, but memory will not actually be deallocated before the next GC cycle. It is used because the GC cycle does not guarantee to run the destructors, so using destroy the destructor is ran immediately (guaranteed). Then, on next GC iteration, the memory will be freed. Until then, referencing it will not cause segfault, but will cause undefined behaviour, as after a destructor the state of the object is undefined (I think).
Re: Question about destructor of database and multiple use access
On Thursday, 28 July 2016 at 15:24:22 UTC, Dechcaudron wrote: On Thursday, 28 July 2016 at 15:18:24 UTC, Lodovico Giaretta wrote: 3) at program end, live objects are not scheduled for finalization; 4) at program end, pending finalizations from previous collections may not be run. I didn't know these two, can I get source on them? I don't have any specific knowledge about the D collector, but it is my understanding that most collectors out there work this way, because it would be very expensive and bug-prone to do otherwise (remember that destructors may do things like get stuck in a loop or "resurrect" themselves or other collected objects). Also, I'm assuming what I said about calling destroy(instance) is as correct as calling a cleanup method? Yes, I think so.
Re: Question about destructor of database and multiple use access
On Thursday, 28 July 2016 at 15:02:58 UTC, Dechcaudron wrote: On Thursday, 28 July 2016 at 14:43:32 UTC, Lodovico Giaretta wrote: No! Never run important finalization in a class destructor! The GC is not obliged to run the destructors, so you may end up with your objects destroyed but the connections still open. For this kind of important things, you have to do them manually. I always thought that the moment of finalization is undetermined, but that the GC does indeed run the destructor... Weird, I'll have to look into that. After all what would be the point of destructors if they are not guaranteed to be run? The collector does not immediately finalize objects. It just schedules them for finalization at a later time. So: 1) If you don't get low on memory, no collection is performed, so no object is scheduled for finalization; 2) even if a collection is performed, false pointers may prevent some unreachable object from becoming garbage and being scheduled for finalization; 3) at program end, live objects are not scheduled for finalization; 4) at program end, pending finalizations from previous collections may not be run.
Re: Question about destructor of database and multiple use access
On Thursday, 28 July 2016 at 14:33:26 UTC, Dechcaudron wrote: On Thursday, 28 July 2016 at 14:01:45 UTC, Suliman wrote: 2. Should I call destructor and how it's should like? You certainly want to close the connection to the db. Basically, the destructor is intended to free resources such as dynamic memory, closing connections... the GC will take care of dynamic memory, but closing the connection to the DB is up to you. So do that in the destructor. No! Never run important finalization in a class destructor! The GC is not obliged to run the destructors, so you may end up with your objects destroyed but the connections still open. For this kind of important things, you have to do them manually. This is true of all major programming languages: JDBC (Java DB framework, one of the most used in the world) requires calling explicit methods to close connections, statements and result sets, because the GC cannot be relied upon. The same goes for C# sql library.
Re: Autodecode in the wild and An Awful Hack to std.regex
On Thursday, 28 July 2016 at 09:10:33 UTC, Kagamin wrote: Create an RFE? Given that regex returns results as slices of the input string, using the replacement character doesn't introduce data corruption. (RFE = Request For Enhancement, right?) Yes, all algorithms that use decode internally shall provide a template parameter to useReplacementDchar. There's no reason not to expose this option, given that it allows not to brutally abort any computation in such situations, and also has the bonus point of making decode @nogc.
Re: Cannot compare object.opEquals is not nogc
On Sunday, 24 July 2016 at 15:31:28 UTC, lqjglkqjsg wrote: Almost off topic but I've recognized a typical error here, I think that many of us have already seen it too. You develop a nice class. You put attributes everywhere @safe pure nothrow @nogc. Yay the unittest pass. Later you use it for real and you realize then that the attributes must be removed because you can't do anything in the overriden methods. That's why I'm against putting @nogc on Object. You must only annotate specific sub-hierarchies that you know will never need the GC (or whatever: @system, impure, throwing). This often means that you can only annotate closed hierarchies. This is correct: you must not annotate open ended classes unless you decide that you really NEED (NEED != WANT) these limitations. And your users will probably find them restrictive, so you need a compelling reason that cannot be solved in other ways.
Re: Cannot compare object.opEquals is not nogc
On Sunday, 24 July 2016 at 15:28:53 UTC, Jonathan Marler wrote: Whoa wait a second...I didn't know you could do this. I thought everything had to inherit from the object class. Can you share the syntax to define a class that doesn't derive from object? Currently, you cannot. Everything inherits from Object. I personally think this is not the best idea. But it's not that horrible either, so probably not worth a big change. But you can just ignore it. You can put on your opCmp all the attributes you want and forget about it inheriting from Object. You can decide to never write a method that takes Object. Always take the root of your sub-hierarchy, so that you know what attributes you have. If it derives from Object or not, nobody cares as long as your sub-root overrides all opXXX with new (even abstract) declarations that have @nogc.
Re: Cannot compare object.opEquals is not nogc
On Sunday, 24 July 2016 at 14:54:11 UTC, Jonathan Marler wrote: I believe Rufus was only referring to the virtual methods defined in the object class. That would be: toHash (Note: this is already nothrow, that's intersting and quite restrictive) opCmp opEquals I think all 3 of these are good candidates for @nogc. However, AFAIK, making them @nogc would break any code that implements them because they would have to add the @nogc attribute to their implementations (unless I am mistaken? Do subclass overrides need to explicitly have @nogc if the parent class does?). If adding @nogc is not required in the implementation, then the only code that would break would be implementations that actually do allocate GC memory. Some would think that restricting GC usage inside these virtual methods is a good thing because it has the benefit of discouraging memory allocation for these types of operations. Really, you probably shouldn't be allocating memory to perform a comparison. If you really need to, you can either allocate non GC memory, or use a different mechanism then the opCmp/opEquals methods. Yes, making them @nogc would require all existing overrides to be changed (overrides cannot throw away attributes, but must specify them explicitly as in the parent class, or stricter). The real problem making these @nogc is that with the current state of things @nogc implies nothrow, thus preventing exceptions (of course we should work to change this thing, and I'm personally researching convenient ways of doing it; I'll soon write a post on General about this). Remember that comparison of complex objects may require normalization, which may change the objects themselves and allocate memory. Also, comparisons may throw exceptions that need the GC (see above). So I'm personally against making those methods @nogc. But I'm also against a singly-rooted hierarchy. Removing Object and having multiple class hierarchies would entirely solve the issue. But please note that you can already "do" that: if you never use Object, but always subclasses, the fact that Object isn't @nogc is no longer an issue. While Object (if it exists) must support any kind of descendant (and thus cannot pose arbitrary limitations like @nogc is), the roots of domain-specific hierarchies can exploit the fact that they are domain-specific to impose meaningful limitations, based on the expected usage and behaviour, and can thus be @nogc. And you can either limit your algorithm inputs to objects of a specific hierarchy or, if you want it generic, use a template (read as: you don't use Object explicitly, as if it doesn't exists).
Re: Cannot compare object.opEquals is not nogc
On Sunday, 24 July 2016 at 02:17:27 UTC, Rufus Smith wrote: This just isn't right. What your saying is that because someone screwed up, we must live with the screw up and build everyone around the screw up. This mentality is why everyone is so screwed up in the first place, do you not see that? And I think you really have a misconception about the GC vs nogc. One can rewrite GC code, such as an GC based opEquals, without limitations. They can allocate on the stack, use malloc and free when done, etc. opEquals generally doesn't have state. So you it is possible to around around. It's probably always possible to rewrite a GC opEquals to use nogc without too much difficulty. Now you are telling me to "program by trust", because there's nothing ensuring that I remember to free everything I allocated with malloc/free, while a GC would guarantee no memory leaks. Again there's nothing stopping me from returning pointers to things allocated on the stack. And now there are lots... Before you told me that programming by trust is a wrong attitude, and now you propose me to use it, risking memory leakage in a function that may be executed hundreds of times per second. BUT, it is impossible to use a GC opEquals in nogc code! This means there is no work around. What you claim is that we accept the impossiblity(which makes nogc useless) just to avoid having to rewrite some GC opEquals code. We can't rewrite the nogc side, it's set in stone. We are screwed from the start when we attempt to do nogc code because at some point we will have to do comparisons. It's the same problem with purity and any other transitive relationship. All "workarounds" are just as limited because basically we added the relationship if A is nogc and A uses B, then B must be nogc. Yet, we start with B is GC. Hence we never ever have A use B, because A's can only use nogc. To see it simpler, What if everything in D was GC based. All code was marked GC(even statements, types, etc). Do you agree that nogc would be absolutely useless? We couldn't build up anything because we couldn't include any code. This is the extreme case. Conversely, if everything was built up using nogc, we could write GC based code just fine, could we not? No. If you put a big @nogc attribute on Object.opXXX, then nobody can write GC code in his classes. So if everything is @nogc, you cannont write GC code, because it woudn't interact with Phobos. Example: if you mark an algorithm that takes a delegate @nogc, then you cannot pass GC delegates to it. So you cannot use it in GC code. Therefore, claiming that we stay with GC based code just prevents using more and more nogc code. The more GC based code D gets, the less useful nogc gets and we are back were we started. Since nogc is more critical in the foundational layers, as it affects everything built on it, all core features should be nogc. This way, the user isn't can decide when to break away from the GC code, which will only affect everything after that point. Yes. All building blocks must be as much @nogc as possible. But customization points (virtual functions, delegate arguments, ...) must not be @nogc, otherwise it is no possible to have classes that use the GC or callbacks that use the GC. This is a one way street, pretending it is two way only enriches the lawyers and eventually makes everyone unhappy. Making the D dependent on the GC was a mistake that many wasted man hours will go in to trying to unravel. Trying to carry on this mistake just wastes more hours. I understand that it is a mess, but it got that way from the mistake in the first place, not from trying to undo the mistake(which is illogical because there would be no nogc if there wasn't a gc in the first place). I also understand that there is some desire to keep things "backwards compatible". This is also a mistake, not only does it prolong the pain and suffering but is irrational. 1. A fork can be made. Those people that have based their code on the GC can continue using an older version. Their code works at that point, does it not? So just stop going down that dead end path. They have what they need, it's not like they will lose anything(virtually nothing except in most cases). Moving in the correct direction is always better, regardless of who's panties get in a wad. I still don't understand why you want Object.opXXX @nogc. As I already said, you can still make your functions @nogc, just accepting parameters of @nogc types. It's obvious. If I wrote a wonderful library that uses the GC, you will not use it. If I have a class that uses the GC in opXXX (and I am free to have it, because maybe I need it, and maybe it's the most efficient way for my use case), you will not use it. The same applies here. You'll have your algorithms work only on classes that declare opXXX as @nogc. Not all memory allocation patterns are good for malloc/free. Not all of them
Re: Cannot compare object.opEquals is not nogc
On Saturday, 23 July 2016 at 21:44:05 UTC, Rufus Smith wrote: On Saturday, 23 July 2016 at 17:27:24 UTC, Lodovico Giaretta wrote: - we trust what we are doing: e.g. we cannot mark a thing @nogc, but we know it is and the profiler confirms that no allocation happens, so we are happy; our aim is having code that doesn't freeze because of collections, and not marking code @nogc. This is bad. It only creates a faulty foundation. The whole point of nogc is to enforce nogc behavior. If you don't use it your not enforcing anything and then things slip by only to create problems later. This mentality is completely wrong and leads to decay. While you are right on this, we must be pragmatical: we currently do not enforce that pointers point to valid memory locations, that private members are not accessed outside the module with tricky arithmetics, we have tons of things that work by convention, because the compiler simply can't check them all and some are even intrinsically uncheckable. In this environment of "code by trust", @nogc is the least of the problems, also because, I insist, it can be checked with the profiler, or you can plug a custom GC to druntime that asserts every time you try to call its functions (work is being made to make the GC independent and pluggable). This is exactly why we are discussing this right now, because someone decided that it was ok to ignore other use cases which eventually turn out to be quite important. Well, I think that deciding that opXXX must always be @nogc, ignoring other use cases that may need the GC, is blatantly wrong. By asking that Object.opXXX be @nogc, you are making the error the error you said others made.
Re: Cannot compare object.opEquals is not nogc
On Saturday, 23 July 2016 at 21:44:05 UTC, Rufus Smith wrote: Templates are not the end all be all. They don't allow for run-time polymorphism, which is an important aspect of software. Ok, so you need runtime polymorphism. And you want it in @nogc code. That's not difficult. Just have the base class of your hierarchy declare its opXXX @nogc. This is possible, because non-@nogc functions can be overridden by @nogc ones (as logical). Now you can have your function accept parameters of your base class, and it will be @nogc. And without forcing every class of the D world to have opXXX @nogc. I don't see why this wouldn't be enough...
Re: Cannot compare object.opEquals is not nogc
On Saturday, 23 July 2016 at 17:04:42 UTC, Jonathan Marler wrote: On Saturday, 23 July 2016 at 16:46:20 UTC, Jonathan Marler wrote: [...] Actually Im going to disagree with myself. This technique actually wouldn't work with virtual methods:) I don't think we have the big problems with @nogc that people points out. I mean, we cannot decide that specific methods or opXXX must always be @nogc. That's too restrictive. So, what we need to do is: - use templates: with them, we can have our algorithms be @safe when applied to @safe types, @nogc when applied to @nogc types, and so on; for example, instead of taking a specific delegate type, we shall always accept a generic type, and use traits to guarantee it is some delegate; in this way, we can accept @safe delegate and propagate @safety to our algorithm, or accept @system and have our algorithm usable in @system code; same with @nogc et al. - when we use virtual methods, we are giving up all compiler-checked attributes; in this situation we have two options: - we trust what we are doing: e.g. we cannot mark a thing @nogc, but we know it is and the profiler confirms that no allocation happens, so we are happy; our aim is having code that doesn't freeze because of collections, and not marking code @nogc. - we must have @nogc (or @whatever): then we know we cannot use certain classes, because they are definitely @nogc; so we cast the objects we get to the classes/interfaces that we know are @nogc (and are marked as such), and then our code is @nogc; as you see, you don't need Object to have @nogc methods; you only need the specific classes you use have it; if you want to work on generic objects, and as such cannot do specific casts, then you should definitely be using templates. The only real problems I found till now are: - some things in Phobos that shall be @nogc are not; they shall be refactored to have that attribute (but this is not always easy and requires time) - the interface IAllocator is mostly used with @nogc allocators, but cannot have the said attribute (as I explained above, it must not restrict the possibility of allocators); it shall have a sub-interface NoGCAllocator, so that code can accept a @nogc allocator parameter without using templates (of course templates are fine, and are what we use now, but if everyone uses templates, why have IAllocator in the first place? IMHO we must have or both or none).
Re: Cannot compare object.opEquals is not nogc
On Saturday, 23 July 2016 at 14:53:49 UTC, Rufus Smith wrote: Um, this isn't right. GC code can always call non-gc code. If you mark opEquals nogc, it breaks nothing except implementations of opEquals that use the GC. GC code can still call it nogc opequals, it only enforces opEquals code to avoid the GC itself, which isn't a terrible thing. That's what I meant. Sorry for being not clear. IMHO, it is very limiting to forbid the use of the GC in opEquals. And it would definitely break a lot of code. What is terrible is that nogc code can never have any equality comparisons! It is impossible unless one manually tests them, but how? Every method would be brittle. Do a memory test? compare element by element? One can't predict what to do. @nogc code can have @nogc comparisons, as long as it does not use other objects whose comparison requires the GC. See more below. So, you are trying off laziness to break nogc. As it stands, if nogc code can't compare equality, it is broken and useless. Why put it in the language then? struct S(T) { @nogc void test(T t1, T t2) { if (t1 == t2) return true; return false; } } Broke! Even if opEquals of T does not use any GC we can't write test to be nogc, which means we can't have S be nogc or anything that depends on S that is nogc. This must be a dirty trick played by the implementors of nogc to keep everyone on the gc nipple? If opEquals of T does not use the GC, then the compiler will infer the attribute @nogc for your test function. Remember: templated functions will be inferred @nogc whenever possible. Just, don't put @nogc explicitly, so the code will be @nogc if T.opEquals is @nogc and otherwise it will be not-@nogc. Equality comparison is more fundamental than the GC in programming. There is no fundamental reason why equality comparison depends on the GC. All I can hope for now is that there is a robust way to compare that I can use that is marked nogc. Else all my nogc code is broke. I guess one has this problem with all opOp's! With templates (as you show in your code) you have no problem, just let the compiler infer the attributes, as I said. With runtime OOP it is more of a trouble, but in D runtime OOP is not used that much, and it is rarely used in critical @nogc code.
Re: Cannot compare object.opEquals is not nogc
On Saturday, 23 July 2016 at 13:18:03 UTC, Rufus Smith wrote: Trying to compare a *ptr value with a value in nogc code results in the error: Error: @nogc function '...' cannot call non-@nogc function 'object.opEquals' Shouldn't object opEquals be marked? If object.opEquals is marked @nogc, than all D classes must implement it as @nogc, because (of course) you cannot override a @nogc method with a not-@nogc one (while the opposite is possible, of course). So marking it @nogc is not only a big breaking change, but also very limiting.
Re: Building phobos GDC
On Friday, 22 July 2016 at 20:26:50 UTC, Rufus Smith wrote: On Friday, 22 July 2016 at 19:52:59 UTC, Lodovico Giaretta wrote: On Friday, 22 July 2016 at 18:30:13 UTC, Rufus Smith wrote: Trying to compile code that uses GDC, had to import phobos files from dmd in to project since they are not in the GDC's phobo lib(the core.sys.windows stuff). Almost all the errors are related to stuff like PALETTEENTRY* peNew() return { return _peNew.ptr; } Does that even make sense? I'll add that, in general, it's a bad idea to mix the libraries of the various compilers. In fact, the library has the same release cycle as the frontend, and is specific to the frontend version it comes with. GDC is several frontend versions behind DMD, so GDC cannot support the new features / characteristics of the recent DMD libraries. You should always use a Phobos version as old as the frontend of the compiler you're using. I don't agree with this. The versions are too far out of sync. It is better to test the different versions together because they are not consistent. As I yet I can neither use GDC or LDC because they don't compile the code that works with DMD. This is a problem with those compilers. If one could guarantee that the oldest compiler was always compatible, eventually(reasonably), with the newest one, it would be a different story. But bugs creep in. I'd rather work with the reference compiler, the actual one the language is based off of, rather than work with one that is not even guaranteed to be maintained properly. With dmd, I know exactly what I'm getting and I only bother with the other compilers due to performance, which is not priority when developing. Hence, I hope that the other compilers are up to speed once I am finished with developing. This is a risk, but no more than expecting those compilers to eventually be updated. Given that the maintenance of LDC and GDC are rather low compared to DMD, I'd rather stick with DMD. LDC is fairly up to date. In fact, it recently shipped an alpha version with support for the 2.071 frontend, while DMD 2.072 is still in beta. So, not that bad, just one version behind. I started a project a couple months ago with DMD 2.071. I'm still working on it, and now I can also use LDC. The real problem is GDC, which apparently is currently at 2.066.
Re: Building phobos GDC
On Friday, 22 July 2016 at 18:30:13 UTC, Rufus Smith wrote: Trying to compile code that uses GDC, had to import phobos files from dmd in to project since they are not in the GDC's phobo lib(the core.sys.windows stuff). Almost all the errors are related to stuff like PALETTEENTRY* peNew() return { return _peNew.ptr; } Does that even make sense? I'll add that, in general, it's a bad idea to mix the libraries of the various compilers. In fact, the library has the same release cycle as the frontend, and is specific to the frontend version it comes with. GDC is several frontend versions behind DMD, so GDC cannot support the new features / characteristics of the recent DMD libraries. You should always use a Phobos version as old as the frontend of the compiler you're using.
Re: Building phobos GDC
On Friday, 22 July 2016 at 18:30:13 UTC, Rufus Smith wrote: Trying to compile code that uses GDC, had to import phobos files from dmd in to project since they are not in the GDC's phobo lib(the core.sys.windows stuff). Almost all the errors are related to stuff like PALETTEENTRY* peNew() return { return _peNew.ptr; } Does that even make sense? The peculiarity of this code is that it uses DIP 25. I don't know if GDC supports it, nor if you need some compiler switch. In DMD you need the -dip25 switch. For more infos on DIP 25: https://wiki.dlang.org/DIP25
Re: Default implementations in inherited interfaces
On Thursday, 21 July 2016 at 09:46:10 UTC, Lodovico Giaretta wrote: Interesting. This is worth a bugzilla issue, IMHO. In fact, if you try the other way (i.e.: you provide an implementation of func in class C), you get the opposite error, that you are overriding a final function (B.func). Submitted as issue 16306 https://issues.dlang.org/show_bug.cgi?id=16306
Re: Default implementations in inherited interfaces
On Thursday, 21 July 2016 at 09:41:27 UTC, Saurabh Das wrote: I have an interface A which declares a certain function. A second interface B inherits from A and wishes to provide a default implementation for that function. How can I achieve this? I'm facing an error when I try this: interface A { int func(int); } interface B : A { final int func(int) { return 0; } } class C : B { } rdmd it.d: it.d(14): Error: class it.C interface function 'int func(int)' is not implemented Thanks, Saurabh Interesting. This is worth a bugzilla issue, IMHO. In fact, if you try the other way (i.e.: you provide an implementation of func in class C), you get the opposite error, that you are overriding a final function (B.func).
Re: How to search for an enum by values and why enum items aren't unique
On Wednesday, 20 July 2016 at 18:08:14 UTC, stunaep wrote: On Wednesday, 20 July 2016 at 05:45:21 UTC, Jonathan M Davis wrote: On Wednesday, July 20, 2016 04:03:23 stunaep via Digitalmars-d-learn wrote: [...] If you want the list of members in an enum, then use std.traits.EnumMembers and you'll get a compile-time list of them. It can be made into a runtime list by being put into an array literal. [...] Coming from Java I've learned to love enums that are separate objects, that can store multiple values, and that can have methods that can be in their scope. Seems to me like there's no reason to even use enums in D. What's the point when just making a constant would do the same exact thing? You can easily emulate Java enums in D. class MyEnumClass { // fields and methods, as a class private int val; public int foo() { return val * 2; } // private ctor: user cannot instantiate the class private this(int i) { val = i; } // your enumerated instances static immutable ONE; static immutable TWO; static immutable THREE; // initialize the enumerate values on program startup shared static this() { ONE = new MyEnumClass(1); TWO = new MyEnumClass(2); THREE = new MyEnumClass(3); } } It's not much longer than the equivalent Java code and is way clearer (you know exactly what's going on under the hood). In java an enum is just an extension of the singleton pattern, where there's a finite set of instantiation instead of exactly one. A D enum (or a C one, or a C++ one) is a totally different thing.
Re: Why typeof(template) is void?
On Wednesday, 20 July 2016 at 05:54:41 UTC, mogu wrote: On Wednesday, 20 July 2016 at 01:50:37 UTC, Adam D. Ruppe wrote: On Wednesday, 20 July 2016 at 01:14:05 UTC, mogu wrote: Why S's type isn't something like `S: (T) -> S`? Because S isn't a type... think of a template as being like a function that returns a type. int foo(int) { return 0; } There, you wouldn't expect typeof(foo) to be int, no, typeof(foo) is a function that returns an int. The template is the same thing - it isn't a type, it is a template that returns a type. So it's a higher kinded type aka type class in Haskell. But D's reflection cannot get enough information about template's kind. Only a `void` given. It may be inconvenient in distinction between an alias of template and void. The only solution AFAIK is by string of the type property .stringof. Note that void is a type, while S is not. So you can do: assert(is(void)) // is(type) returns true assert(!is(S)) // is(template) returns false;
Re: Allowing "fall through" of attributes
On Tuesday, 19 July 2016 at 17:05:55 UTC, Rufus Smith wrote: On Tuesday, 19 July 2016 at 16:59:48 UTC, Lodovico Giaretta wrote: On Tuesday, 19 July 2016 at 16:50:56 UTC, Rufus Smith wrote: On Tuesday, 19 July 2016 at 16:09:38 UTC, Lodovico Giaretta wrote: [...] But this doesn't create a function with all the attributes of the original? Just one that has the same return type and parameters. What if Fun is pure or extern(C) or some other attributes? I'd like to create a function that is exactly the same in all regards as the original. Sorry, I misunderstood your question. With the method I showed you, if the function is @safe, pure, @nogc or nothrow, foo will infer those attributes. But only if the operations you do in foo (apart from calling bar) are themselves @safe, pure, @nogc or nothrow. For other things, like extern(C), I don't think there's a simple solution; but I'm not an expert, so I hope someone else will give you a better answer. What is strange is I cannot even pass an extern(C) function to foo. void foo(R, A...)(R function(A) bar); extern(C) void bar(); foo() fails. Remove extern and it passes. I have not figured out how to allow for extern(C) functions to be passed. That's because an extern function must be called with a different code. So it cannot be cast to a non-extern(C) function pointer, which is what your foo accepts. If you follow my advice, and make the entire function type a parameter of foo, then foo will at least accept your extern(C) function, but it will not be extern(C) itself.
Re: Allowing "fall through" of attributes
On Tuesday, 19 July 2016 at 16:50:56 UTC, Rufus Smith wrote: On Tuesday, 19 July 2016 at 16:09:38 UTC, Lodovico Giaretta wrote: On Tuesday, 19 July 2016 at 15:55:02 UTC, Rufus Smith wrote: I have some functions that take other functions. I would like the attributes to be able to "fall" through so I get overload like behavior. I only care that I am passing a function, not if it is shared, extern(C), pure, @nogc, etc. void foo(R, A...)(R function(A) bar) { alias type = typeof(bar); pragma(msg, type); // does magic with bar } foo never uses the attributes of bar explicitly. It uses type to instantiate other functions like bar. I have to create a foo for each attribute combination, which is not worth while. The code seems to break only for extern, the best I can tell, most attributes do pass through. But type does not contain these attributes. You shall do something like this (please note that I didn't check the docs while writing this; you shall definitely have a look at std.traits and consider the following as pseudo-code and not actual D): void foo(Fun)(Fun bar) if (isSomeFunction!Fun) // your constraint that bar is a function { // how to get your R and A types, if you need them: alias R = ReturnType!bar; alias A = Parameters!bar; alias type = Fun; pragma(msg, type); // do some magic } But this doesn't create a function with all the attributes of the original? Just one that has the same return type and parameters. What if Fun is pure or extern(C) or some other attributes? I'd like to create a function that is exactly the same in all regards as the original. Sorry, I misunderstood your question. With the method I showed you, if the function is @safe, pure, @nogc or nothrow, foo will infer those attributes. But only if the operations you do in foo (apart from calling bar) are themselves @safe, pure, @nogc or nothrow. For other things, like extern(C), I don't think there's a simple solution; but I'm not an expert, so I hope someone else will give you a better answer.
Re: Allowing "fall through" of attributes
On Tuesday, 19 July 2016 at 15:55:02 UTC, Rufus Smith wrote: I have some functions that take other functions. I would like the attributes to be able to "fall" through so I get overload like behavior. I only care that I am passing a function, not if it is shared, extern(C), pure, @nogc, etc. void foo(R, A...)(R function(A) bar) { alias type = typeof(bar); pragma(msg, type); // does magic with bar } foo never uses the attributes of bar explicitly. It uses type to instantiate other functions like bar. I have to create a foo for each attribute combination, which is not worth while. The code seems to break only for extern, the best I can tell, most attributes do pass through. But type does not contain these attributes. You shall do something like this (please note that I didn't check the docs while writing this; you shall definitely have a look at std.traits and consider the following as pseudo-code and not actual D): void foo(Fun)(Fun bar) if (isSomeFunction!Fun) // your constraint that bar is a function { // how to get your R and A types, if you need them: alias R = ReturnType!bar; alias A = Parameters!bar; alias type = Fun; pragma(msg, type); // do some magic }
Re: Passing a single tuple or multiple values
On Tuesday, 19 July 2016 at 15:36:42 UTC, Lodovico Giaretta wrote: As you have to do `isTuple!(T[0])`, you also have to do `x[0].expand`. That's because T... works "as if" it was an array of types, and x, being of type T, it works "as if" it was an array of values. So you have to use an index in both cases. You can find this out from the error, which says that you can't expand an object of type `(Tuple!(int, int))`. Note the surrounding parenthesis: they tell you that what you have is not a Tuple, but an AliasSeq whose only member is a Tuple. If you do `[0]` on it, you obtain the correct type, i.e. `Tuple!(int, int)`, without the parenthesis.
Re: Passing a single tuple or multiple values
On Tuesday, 19 July 2016 at 13:33:41 UTC, jmh530 wrote: On Tuesday, 19 July 2016 at 07:23:52 UTC, John wrote: auto bar(T...)(T x) { static if (T.length == 1 && isTuple!(T[0])) return foo(x.expand); else return foo(x); } Hmm, this actually doesn't seem to be resolving my issue. I'm still getting the error about not being able to expand x. I tried it like below and got the same error. auto bar(T...)(T x) { static if (T.length > 1) { return foo(x); } else static if (T.length == 1 && isTuple!(T)) { return foo(x.expand); } } As you have to do `isTuple!(T[0])`, you also have to do `x[0].expand`. That's because T... works "as if" it was an array of types, and x, being of type T, it works "as if" it was an array of values. So you have to use an index in both cases.
Re: counting characters
On Tuesday, 19 July 2016 at 12:23:11 UTC, celavek wrote: On Tuesday, 19 July 2016 at 09:57:27 UTC, Lodovico Giaretta wrote: On Tuesday, 19 July 2016 at 09:42:40 UTC, celavek wrote: Works for me: size_t[char] counts; const string dna_chain = "AGCCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAGAGTGTCTGATAGCAGC"; counts['A'] = countchars(dna_chain, "A"); It was failing for me as I was using "countchars!". I thought that I should use the "!" in order to instantiate a template in D. I'm still confused why it is working without the "!". Anyway the compiler message was not very helpful. The declaration is: countchars(S, S1)(S str, S1 pattern) So the most verbose way to instantiate it is: countchars!(string, string)(dna_chain, "A") But as S and S1 are the types of the two arguments, the compiler can easily infer them, so you can write: countchars(dna_chain, "A") And have the compiler infer: countchars!(typeof(dna_chain), typeof("A"))(dna_chain, "A") The error message is technically correct: you cannot instantiate countchars with template parameters `dna_chain` and `"A"`, which is what you were actually doing.
Re: counting characters
On Tuesday, 19 July 2016 at 09:42:40 UTC, celavek wrote: On Tuesday, 19 July 2016 at 09:41:32 UTC, John wrote: On Tuesday, 19 July 2016 at 09:34:11 UTC, celavek wrote: Hi, I am trying to count characters in a string like: const string dna_chain = "AGCCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAGAGTGTCTGATAGCAGC"; counts['A'] = countchars!(dna_chain, 'A'); countchars(dna_chain, "A"); Not working. Same error. Works for me: size_t[char] counts; const string dna_chain = "AGCCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAGAGTGTCTGATAGCAGC"; counts['A'] = countchars(dna_chain, "A");
Re: Iterate all visible symbols, even from imported modules
On Monday, 18 July 2016 at 21:12:38 UTC, Meta wrote: On Monday, 18 July 2016 at 13:00:16 UTC, Lodovico Giaretta wrote: As per title, is it possible to iterate all visible symbols of the current module and of all imported modules and packages? My aim is to find everything in scope that has a specific UDA. module foo; import std.stdio, std.array, std.algorithm; void bar(){} struct S{} void main() { // prints ["object", "std", "bar", "S", "main"] // how do I discover that "std" is a package? writeln([__traits(allMembers, foo)]); // prints ["object", "core", "std", "KeepTerminator", "GCC_IO", ... ] // strange thing: it looks the same even if I remove all imports other than std.stdio writeln([__traits(allMembers, foo.std)]); } Thank you in advance. This answer to a similar question on StackOverflow may be useful: http://stackoverflow.com/questions/2329/d-finding-all-functions-with-certain-attribute/25560800#25560800 Wow! Looks exactly what I was looking for. I'll give this a try as soon as possible. Thank you.
Re: Iterate all visible symbols, even from imported modules
On Monday, 18 July 2016 at 18:21:41 UTC, ketmar wrote: short answer: no. there is still no way to write a reliable enumerator like this: too much things to hack around. as for module symbols, it is easy: they has no type. literally: `!is(typeof(...))`. `is(typeof(...))` is a necessary safeguard anyway if you are enumerating symbols in module, as you can't do much with module names anyway, and you *have* to filter 'em out with top-level static if. Thank you. It looks like the check `is(typeof(T)) || is(T)` is passed by every symbol `T` that is not a module nor a package, so I think I'll use its complementary as a filter.
Iterate all visible symbols, even from imported modules
As per title, is it possible to iterate all visible symbols of the current module and of all imported modules and packages? My aim is to find everything in scope that has a specific UDA. module foo; import std.stdio, std.array, std.algorithm; void bar(){} struct S{} void main() { // prints ["object", "std", "bar", "S", "main"] // how do I discover that "std" is a package? writeln([__traits(allMembers, foo)]); // prints ["object", "core", "std", "KeepTerminator", "GCC_IO", ... ] // strange thing: it looks the same even if I remove all imports other than std.stdio writeln([__traits(allMembers, foo.std)]); } Thank you in advance.
Re: Templates args
On Thursday, 14 July 2016 at 19:28:23 UTC, Andrey wrote: On Thursday, 14 July 2016 at 19:27:14 UTC, Andrey wrote: Hi guys! Help a newbie please. Playing with D and trying to understand some features. Here is my try to carry out my code from C++ project to D struct Sigmoid(T) { const T Function(T value) { ... } const T DerivateFunction(const T value) { ... } } struct Neurons_layer(T = float, size_t neurons_num = 0, F = Sigmoid!T) if(isFloatingPoint!T && is(typeof(F.Function))) { private: static if(neurons_num > 0) T[neurons_num] _neurons_arr; else T[] _neurons_arr; private: alias Function = F.Function; } unittest { Neurons_layer!(float,5,Sigmoid!float) nf; } The question is - How to make in pretty way this line: Neurons_layer!(float,5,Sigmoid!float) nf; to something like - Neurons_layer!(float,5,Sigmoid) nf; You don't need Sigmoid!float at all. This will work: Neurons_layer!(float, 5) nf; as you provided a default value for the third argument.
Re: I can has @nogc and throw Exceptions?
On Wednesday, 13 July 2016 at 22:42:36 UTC, Adam Sansier wrote: On Wednesday, 13 July 2016 at 21:27:16 UTC, Lodovico Giaretta wrote: At the end, all memory comes from one of these: GC heap, malloc, mmap, sbrk. All other allocators build on top of these (or on top of user supplied buffers, which come from these as well). What those "wrapper" allocators do is managing the given memory, either using different allocations strategies for different allocation sizes, or keeping lists of free blocks instead of returning them using "free", or other things (have a look at the docs). So at the end they do what you would manually do in C/C++ to "personalize" the allocations, with the aim of reducing waste and/or being faster. They are also arbitrarily composable on top of each other. I don't know how Phobos will handle exceptions. Maybe use reference counting (coming soon in D, maybe)? Maybe algorithms that already have to allocate will switch from using the GC to using a user-supplied custom allocator, and will use it for exceptions too. Currently I'm working on a replacement for std.xml and I'm making every component take a template parameter to specify the allocator. Initially the allocators look like a real mess, but after a couple of days playing with them, you start understanding the mechanics and at the end you really enjoy them. Changing a single parameters allows to switch between @safe gc code and @nogc code in the unittests, without changing the implementation. Ok. Is there a way to bundle allocations so that one free will work? For example, your exception handling looks good but I need to supply custom messges. If I use sformat I have to create the array for the buffer to create the message in. This means I would have to free both the exception and the string. It would be nice to be able to do this in one go. Sometimes it's nice to include runtime info in an error message such as an OS error code. As you probably saw, sformat still has some problems with @nogc, because it internally uses std.uft.encode, which may throw a GC-allocated exception, but this can be solved. Not all allocators keep track of the memory ranges they allocated (e.g.: Mallocator). The ones that do (like Region) usually provide a deallocateAll method. So the idea is that you allocate all data needed by your exception (string buffers or whatever) and the exception itself with one of these allocators, and at the end of a catch you deallocateAll. Also, could one create a struct or class for the exception so that it is automatically free'ed at the end of a catch block, if caught? Probably not without language help? I don't think it's feasible without language support for reference counted classes (which may be added sooner or later, as it has been asked and proposals have been made, and would be very useful). Also note that you don't want RAII or scope(exit) in this case but scope(success), as the exception shall not be deallocated if another one is raised in the catch block, because in D the second exception does not "overwrite" the first, but is chained to it, so that an outer catch can see both of them.
Re: I can has @nogc and throw Exceptions?
On Wednesday, 13 July 2016 at 21:12:29 UTC, Adam Sansier wrote: The advantages over a simple malloc are: 1) You can change between GC allocation, malloc, mmap and other allocators by changing a single line, instead of changing every throw; Ok, I like! 2) you can use very fast allocators, based on your needs; this example uses the Region allocator, which is way faster than a call to malloc; I like too! But I'll have to assume you are right since I have no proof. 3) the Region allocator has the added value of working even if there's no more memory available (because it preallocated it). Well, one could do this with malloc because one can pre-allocate it too. I figure this is why you stated 2 though because it is pre-allocated? So, really only point 1 stands, but that is probably not even valid since one can wrap the allocator in a template. This is probably exactly what is being done.. So, ultimately no real benefit except the implementation details have been removed. That's not a bad thing as long as it works ;) In general, the allocators library provides facilities that may seem overkill for simple tasks (and in fact they are), but prove very flexible and useful for advanced uses, or to write generic highly customizable code. Of course, being experimental, this library has still some issues... Well, I will try out the code and see. You've provided an example and if it works then it should be good enough in my case. If it doesn't limit what I need to do then I'm happy ;) How is phobo's going to deal with such things when it is trying to get off the GC? It surely has to throw exceptions. Similar method or something entirely different? Thanks. At the end, all memory comes from one of these: GC heap, malloc, mmap, sbrk. All other allocators build on top of these (or on top of user supplied buffers, which come from these as well). What those "wrapper" allocators do is managing the given memory, either using different allocations strategies for different allocation sizes, or keeping lists of free blocks instead of returning them using "free", or other things (have a look at the docs). So at the end they do what you would manually do in C/C++ to "personalize" the allocations, with the aim of reducing waste and/or being faster. They are also arbitrarily composable on top of each other. I don't know how Phobos will handle exceptions. Maybe use reference counting (coming soon in D, maybe)? Maybe algorithms that already have to allocate will switch from using the GC to using a user-supplied custom allocator, and will use it for exceptions too. Currently I'm working on a replacement for std.xml and I'm making every component take a template parameter to specify the allocator. Initially the allocators look like a real mess, but after a couple of days playing with them, you start understanding the mechanics and at the end you really enjoy them. Changing a single parameters allows to switch between @safe gc code and @nogc code in the unittests, without changing the implementation.
Re: I can has @nogc and throw Exceptions?
On Wednesday, 13 July 2016 at 20:44:52 UTC, Adam Sansier wrote: On Wednesday, 13 July 2016 at 16:28:23 UTC, Lodovico Giaretta wrote: It's actually quite easy. Here's the code (untested): import std.experimental.allocator.building_blocks.region; import std.experimental.allocator.mallocator; import std.experimental.allocator; Region(shared(Mallocator)) exception_allocator; enum EXCEPTION_MEM_SIZE = 256*1024; static this() { exception_allocator = typeof(exception_allocator)(EXCEPTION_MEM_SIZE); } And here is an usage example (untested, too): void throwingFunction() { // try to do something, but fail throw exception_allocator.make!Exception("my wonderful error message"); } void throwingThrowingFunction() { try { // try to call function, which fails throwingFunction; } catch (Exception exc) { // try to recover from failure, but generate other exception (just to show chaining) throw exception_allocator.make!Exception("I love exception chaining"); } } void main() { try { // try to call function, which fails throwingThrowingFunction; } catch (Exception exc) { // recover from failure, then deallocate the exceptions no longer needed exception_allocator.deallocateAll; } } Doesn't work. identifier expected on shared. What's the difference of simply using malloc to allocate the memory and creating the exceptions their? Seems like a long and winded way go about it or is there some benefit to using the experimental allocators? `Region(shared(Mallocator))` shall be `Region!(shared Mallocator)` (again, I'm just looking at the code, didn't test it). The advantages over a simple malloc are: 1) You can change between GC allocation, malloc, mmap and other allocators by changing a single line, instead of changing every throw; 2) you can use very fast allocators, based on your needs; this example uses the Region allocator, which is way faster than a call to malloc; 3) the Region allocator has the added value of working even if there's no more memory available (because it preallocated it). In general, the allocators library provides facilities that may seem overkill for simple tasks (and in fact they are), but prove very flexible and useful for advanced uses, or to write generic highly customizable code. Of course, being experimental, this library has still some issues...
Re: I can has @nogc and throw Exceptions?
On Wednesday, 13 July 2016 at 16:13:21 UTC, Adam Sansier wrote: On Wednesday, 13 July 2016 at 11:39:11 UTC, Lodovico Giaretta wrote: On Wednesday, 13 July 2016 at 00:57:38 UTC, Adam Sansier wrote: [...] You shall use a static per-thread Region allocator[1] backed by Mallocator[2]. Then you just make[3] exceptions inside it and throw them. So you can allocate and chain exceptions until you end the memory established on creation. Whenever you don't need the exception chain anymore (i.e.: you catched them and program is back in "normal" mode, you just reset the region allocator, so you have all of your memory again, for the next exception chain). [1] https://dlang.org/phobos/std_experimental_allocator_building_blocks_region.html [2] https://dlang.org/phobos/std_experimental_allocator_mallocator.html [3] https://dlang.org/phobos/std_experimental_allocator.html Am I going to have to do all this myself or is it already done for me somewhere? It's actually quite easy. Here's the code (untested): import std.experimental.allocator.building_blocks.region; import std.experimental.allocator.mallocator; import std.experimental.allocator; Region(shared(Mallocator)) exception_allocator; enum EXCEPTION_MEM_SIZE = 256*1024; static this() { exception_allocator = typeof(exception_allocator)(EXCEPTION_MEM_SIZE); } And here is an usage example (untested, too): void throwingFunction() { // try to do something, but fail throw exception_allocator.make!Exception("my wonderful error message"); } void throwingThrowingFunction() { try { // try to call function, which fails throwingFunction; } catch (Exception exc) { // try to recover from failure, but generate other exception (just to show chaining) throw exception_allocator.make!Exception("I love exception chaining"); } } void main() { try { // try to call function, which fails throwingThrowingFunction; } catch (Exception exc) { // recover from failure, then deallocate the exceptions no longer needed exception_allocator.deallocateAll; } }
Re: Best way to clear dynamic array for reuse
On Wednesday, 13 July 2016 at 12:37:26 UTC, Miguel L wrote: I tried Appender, but for some reason garbage collector still seems to be running every few iterations. I will try to expand a little on my code because maybe there is something i am missing: Appender!(A[]) a; void foo( out Appender!(A[]) bar) { ... bar~= lot of elements } for() { //a=[]; //discard array contents a.clear(); foo(a) appends thousand of elements to a ... use a for some calculations } Well, I think foo's parameter should be `ref Appender!(A[]) bar` instead of `out Appender!(A[]) bar`. Also, if you know you will append lots of elements, doing a.reserve(s), with s being an estimate of the number of appends you expect, might be a good idea.
Re: Best way to clear dynamic array for reuse
On Wednesday, 13 July 2016 at 12:20:07 UTC, cym13 wrote: The best option would be a.clear(). From the language specs: “Removes all remaining keys and values from an associative array. The array is not rehashed after removal, to allow for the existing storage to be reused. This will affect all references to the same instance and is not equivalent to destroy(aa) which only sets the current reference to null.” I don't think OP is using associative arrays, but dynamic arrays (if I understood correctly).
Re: Best way to clear dynamic array for reuse
On Wednesday, 13 July 2016 at 11:59:18 UTC, Miguel L wrote: I am using a temporary dynamic array inside a loop this way: A[] a; for() { a=[]; //discard array contents ... appends thousand of elements to a ... use a for some calculations } I would like to know which would be the best way to clear a contents avoiding reallocations, as there seems to be lots of garbage collection cycles taking place. The options would be: a=[]; a.length=0; a=null; ... any other? Can you help me please? Use std.array.Appender. It allows faster appends, and has a handy .clear method that zeroes the length of the managed array, without de-allocating it, so the same buffer is reused.