Re: template/mixin magic for to! auto inferring type from variable
On Friday, 2 February 2024 at 21:01:53 UTC, Paul Backus wrote: No, D only does bottom-up type inference, not top down. If you want to avoid repeating the type, use `auto` on the left side: ```d auto time = to!uint(data[1]); auto priority = to!int(data[2]); ``` Okay thanks. It finally clicked what bottom-up/top-down type interference is. The auto solution won't work for a struct however which I'm using: ```D struct procTable{ //contains all the fields inside a file I'm parsing uint time; int priority; string name; // etc } ```
template/mixin magic for to! auto inferring type from variable
Is there some way to do: ```D string[3] data; //strings from some file input, some are ints, uints, etc. auto into!(T)(T value){return to!???(value); } // ??? uint time = into!(data[1]); // We already know this is uint int priority = into!(data[2]); ``` instead of: ```D uint time = to!uint(data[1]); // specifying type twice int priority = to!int(data[2]) ```
Re: Would this be a useful construct to add to D? auto for constructor call.
On Wednesday, 24 January 2024 at 08:22:49 UTC, Walter Bright wrote: On 1/23/2024 8:01 AM, Steven Schveighoffer wrote: zero proposals that infer type from how they are used have been accepted by Walter, this one probably will be no different. Types are inferred in D from the bottom up. Mixing in special cases of it being top down leads to confusion over how the type is determined. Thanks to everyone for the feedback. And sorry I selected the wrong forum. Apologies, --Chris
Would this be a useful construct to add to D? auto for constructor call.
```D class dataGridLayerView{ int t; this(int _t){ t = _t; } } class myClass{ dataGridLayerView dataGrid; this() { dataGrid = new auto(15); // <--- new // instead of dataGrid = new dataGridLayerView(15); } } ``` Because it seems, conceptually, the compiler should know all the details required here to simply insert the right constructor name. Basically just the reverse of: ```D auto t = sqrt(15); ``` So intuitively it makes sense to me. It might even be possible to write a mixin to do this, I'm not sure. I'm no D wizard, but I don't see any obvious name or lexing conflicts/ambiguity. Cheers, --Chris
How to write an interface but with different signatures
I know that sounds stupid on the face of it. An interface shouldn't change. But consider this: A frame timer and a clock timer(seconds) that re-use functionality from a parent class/interface. ``` class timerType { void start() = 0; void stop() = 0; void restart() = 0; void set(?) = 0; // } class frameTimer : timerType { void set(int numFrames){} } class clockTimer : timerType { void set(float numSeconds){} } ``` If we put both signatures in the top we're kind of polluting the interface. If we don't put them in the interface, then you can create a timer with no set() function. None of this is super important on a practical level. There's going to probably be a total of two or three timer types. But as a learning exercise, I'm curious if there is a right/proper/best way to solve this conceptual problem. And to be clear, frames and seconds are NOT directly interchangeable or convertible. If the game runs at 2 FPS for a moment, a 5 second timer is still 5 seconds (e.g. a countdown), but a frame timer of 2 (for an animation) is still going to be 2 frames.
Re: Print debug data
On Monday, 17 July 2023 at 03:43:04 UTC, Alain De Vos wrote: Is it possible to print runtime memory usage of: -The stack -The heap -The garbage collector ? there's gc.stats for part of it: https://dlang.org/library/core/memory/gc.stats.html
Re: Advice on debugging possible exception or crash
On Thursday, 6 July 2023 at 06:00:04 UTC, Cecil Ward wrote: My program is instrumented with a load of writeflns. At one point it looks as though it suddenly quits prematurely because the expected writeflns are not seen in the output. It could be that I am just reading the flow of control wrong as it goes ret, ret etc. I’m wondering if it is throwing an exception, or has a fault initiating a crash, perhaps even due to the fetching of arguments of one of the writeflns. In my limited experience, exceptions produce an error message though, and I’m not seeing anything. Any advice on how to debug this, silent termination ? I don’t have a debugger on this machine, but on an x86-64 box I could use gdb if I first take the time to work out how. one thing I do is have gdb/lldb break on d assert, before it destroys the stack. That helped me catch a class of bugs. ```sh # in the gdb interface before running break _d_assertp break _d_assert break _d_assert_msg # or to combine it into the commandline: gdb -ex "break _d_assert" -ex "break _d_assert_msg" -ex "run $1" ./main # can also add it to your .gdbinit startup code. ```
Re: Options for Cross-Platform 3D Game Development
On Wednesday, 5 July 2023 at 22:27:46 UTC, Andrew wrote: So, I've gotten the itch to have a go at game development in D, after doing a bit of it in Java last year. I've previously used LWJGL, which is a java wrapper for OpenGL, OpenAL, GLFW, and some other useful libs. The problem is, apparently OpenGL is deprecated for apple devices, so I don't really want to use that unless there are no decent alternatives. So far, the most promising I've seen is [bindbc-bgfx](https://code.dlang.org/packages/bindbc-bgfx), but it's been a pain to set up due to having to build the bgfx codebase, which requires a specific version of glibc that my distro (Linux Mint) doesn't offer yet. Are there any other recommendations for cross-platform rendering libraries? Of course I could use a pre-made game engine like Unity or Godot, but for me, most of the fun is in making the engine. Are you trying to make a PC game, or a mobile game? Because in 99% of cases I would pick a different toolchain for mobile than PC. OpenGL being depreciated on a single, walled-garden platform, does not rule it out for the entire rest of installed systems. Only if I absolutely needed, cross-platform out-of-the-box with mobiles and PC, would I pick a package like, Xamarin. Which now forces me to use C#, and the size bloat of including a mono framework with all my apps. I would not pick Xamarin just because I wanted to keep my options open, I would d pick it because I have a planned application that needed to be 1:1 synced across iPhone, Android (and possibly PC). There's also other options. Such as using a OpenGL -> Metal conversion layer, like MetalAngle: https://github.com/kakashidinho/metalangle https://chromium.googlesource.com/angle/angle So be sure exactly what you want as the best tools for the job will depend greatly on the requirements of the project.
official activate script is super confusing
https://dlang.org/install.html#activate I ran the two curl liners for grabbing DMD and LDC newest. So now I have ~/dlang/ldc-1.32.2 and ~/dlang/dmd-2.104.0 How am I supposed to have both "activated"? Why does LDC have to override DMD, and DMD have to override LDC in the PATH? I have both installed on another system without using this script and they run fine side-by-side. I can call dmd, or ldc, without any special "activate" calls. But this script seems to be the easiest/fastest way to download DMD and LDC. I normally have separate scripts for dmd and ldc. (godmd, and goldc) But it seems I'll have to hardcode calls to the right activate script before my normal script code. ```sh #godmd ~/dlang/dmd-2.104.0/activate dmd -I... ``` But the activate scripts may have different version numbers in path! ~/dlang/dmd-2.104.0/activate will one day become ~/dlang/dmd-2.105.0/activate and so on.
Re: Debugging by old fashioned trace log printfs / writefln
On Thursday, 29 June 2023 at 18:27:22 UTC, Cecil Ward wrote: I’m trying to debug my D program with old-fashioned printfs stuck in various strategic places, actually using writefln(). My problem is that the addition of printf fights with the existing declarations for pure nothrow @nogc @safe and I have to adjust them, then put them back correctly when the writefln() trace statements are later removed. Is there something else I could be using, something that is allowed to violate the checking rules for purity, nothrow, @nogc? Would pragma( msg, "…" ) do the trick? Is that what I should be using? pragma(msg, "") is only for compile time. It for debugging functions/templates if they're actually used (which static path is used), instantiated, and you can also get type values from template inputs to confirm they're what you expect. "Oh this is a char[][] not a char[]!" pragmas are the D equivalent of C/C++ pragmas. In this case, C/C++: ```C #pragma message( message-string ) ```
Re: pragma msg field name?
On Tuesday, 27 June 2023 at 22:34:17 UTC, Adam D Ruppe wrote: On Tuesday, 27 June 2023 at 22:20:22 UTC, Chris Katko wrote: pragma(msg, t.stringof); // does not see any new fields! D's declarations are all order-independent, in theory those foreaches are done simultaneously, so it is kinda a race condition. Thank you, that's what I thought, but then I started adding them and there was no warning and I was like "wait... is this top-down???" In practice, the compiler does them in two passes but both based on the same initial state. Adding stuff and then reflecting over the stuff you add must be done as explicit steps on the outside, like you can make a `struct step1 {}` then `alias step2 = transform!step1;` then `alias step3 = transform_again!step2;` or something. Okay again makes more sense. The amount of stuff that was "kinda" working, plus learning through tiny 3 liner code snippets in docs, was making my brain explode a bit. A constructor/factory pattern for this makes way more sense. Sometimes it's hard to tell where things are symbolic / functional, verses procedural/linear.
Re: pragma msg field name?
Does anyone know why the new variables don't show up after the static foreach? I have a struct, it has some marked fields. I want to note those fields at compile time and make some similarly named fields like myField becomes myField__replicated. The code doesn't _have_ to be inside the struct/class itself. It could be: ``` auto replicatedObject = makeReplicated!(myObject); ``` for example. I'm not sure the high-level best way right now, as I'm currently having issues with the nitty-gritty implementation of templates. snippetcode (drop right into run.dlang.io): ```D import std; struct multiplayerObject2 { ushort type; ushort type2; float x, y; static foreach(t; typeof(this).tupleof) { pragma(msg, t.stringof); mixin("bool " ~ t.stringof ~ "25;"); // copy the fieldname with a suffix } pragma(msg, "-separator-"); static foreach(t; typeof (this).tupleof) // again { pragma(msg, t.stringof); // does not see any new fields! } } void main() { } ``` ```D // Output type type2 x y -separator- type type2 x y ```
Re: pragma msg field name?
On Tuesday, 27 June 2023 at 04:56:19 UTC, Ali Çehreli wrote: On 6/26/23 21:25, Chris Katko wrote: > How do I get just the field name? I know .tupleof, which you can typeof() as well: class myObject{ int field1, field2, field3; static foreach(field; typeof(this).tupleof) { pragma(msg, field.stringof); } static foreach(MemberType; typeof(typeof(this).tupleof)) { pragma(msg, MemberType); } } The output: field1 field2 field3 int int int I had to consult what I wrote years ago: http://ddili.org/ders/d.en/tuples.html#ix_tuples..tupleof Ali That seems to do the trick, I was really not expecting so much text just to get something so simple! At the moment I'm trying to take variables with an attribute (rep) and then make a duplicate of them inside the struct. It seems to work. If I had duplicate names, it fails. However, the new fields don't appear to be showing up on a second enumeration: enum rep; struct multiplayerObject2 { @rep ushort type; @("rep2") ushort type2; float x, y; static foreach(t; typeof(this).tupleof) { // no if rep/rep2 here, i'm just testing: pragma(msg, t.stringof); // does not see any new fields! mixin("bool " ~ t.stringof ~ "25;"); // copy the fieldname with a suffix } pragma(msg, "-separator-"); static foreach(t; typeof (this).tupleof) // again { pragma(msg, t.stringof); // does not see any new fields! } } output ``` type type2 x y -separator- type type2 x y ``` However, if I do try to force the names to duplicate (say "type2") I get an error involving some sort of __anonymous subobject. ``` source/app.d-mixin-123(123,6): Error: variable `app.multiplayerObject2.__anonymous.type2` conflicts with variable `app.multiplayerObject2.type2` at source/app.d(116,19) ``` I also never realized you could put a static/static foreach inside the body of a struct (and not a function) so I'm still having trouble wrapping my head around that. Is it processing top-down? Jonathan M Davis: Yeah, it does what I listed if you add the UDA to it.
pragma msg field name?
inside a static foreach I can do ``` enum rep; class myObject{ int field1, field2, field3; static foreach(field; getSymbolsByUDA!(typeof(this), rep)) { pragma(msg, field); // fails pragma(msg, fullyQualifiedName!field); // works } } ``` error for pragma(msg, field) ``` source/app.d(33,16): Error: value of `this` is not known at compile time source/app.d(33,4):while evaluating `pragma(msg, field)` [repeating for every variable in the class] ``` How do I get just the field name? And why does it think this is a run-time value? I need to wrap it in some sort of template? All I see in std.traits docs are: fullyQualifiedName mangledName moduleName packageName
Re: Beerconf June 2023
On Saturday, 24 June 2023 at 22:43:50 UTC, Steven Schveighoffer wrote: On 6/24/23 9:01 AM, Richard (Rikki) Andrew Cattermole wrote: Linkity link link https://meet.jit.si/Dlang2023JuneBeerConf Unfortunately, we were getting some spam joiners. So if you want to join, the password is now `DlangRox` -Steve Will there be a YouTube/whatever mirror of the conference afterward?
Returning a reference to be manipulated
I'm trying to figure out how to return a reference to something that may not be a reference type. ```D struct stats { float[string] data=0; float ref opIndex(string key) { return data[key]; // want a ref to a specific element } } void test() { stats foo; auto x = foo.bar(); // returns some sort of reference // data["tacos"] = 0 x++; // data["tacos"] = 1 } ``` Right now, I'm using pointers which resolves to: ```D // float* opIndex(string key){...} using pointer (*s["tacos"])++; // works with pointer, but is strange looking s["tacos"]++; // preferred syntax or something similar ```
Assocative array lookup for object
```D class bitmapHandler { bitmap*[string] bmps; void get(string name){return bmps[name]; /* plus other code */} } void usage() { bitmapHandler bh; bitmap foo = bh.get("bar"); // works bitmap foo2 = bh["bar"]; // desired } ``` Should I be using opEquals? Or something different? The problem with 'alias this' here is I want to wrap access to the insides with getter functions that do various things like logging and error checking. I mean, if I ruined some encapsulation, I could make a function called "bh" and have the usage: ```D bh("bar"); ``` and have it access a singleton object.
Virtual method call from constructor
dscanner reports this as a warning: ```D struct foo{ this() { /* some initial setup */ refresh(); } void refresh() { /* setup some more stuff */} // [warn] a virtual call inside a constructor may lead to unexpected results in the derived classes } ``` Firstly, are all calls virtual in a struct/class in D? Is this any different from C++? IIRC, in C++, a struct cannot have virtual calls, and virtual methods are explicit keywords in classes. Second, could you give me some case examples where this problem occurs? Is the issue if I override refresh in a derived class, and the base class will accidentally use child.refresh()? Third, is there the expectation that you should _never_ call any internal, private, methods inside a constructor? Or do I just call/structure it a different way? For a concrete example: I have a particle struct. It makes sense to me, to have initial setup code (placed in the refresh() function) called by this(), that later I can then call again; to reset the struct to an initial state in-memory without re-allocations. I imagine in D that there's probably something like: ```D particles[235] = foo.init; ``` but that blows up in a scenario where I'm only _partially_ resetting the struct data. For example, if I had a bunch of pointers to system modules, those values don't need to be nulled and re-set every time in this(), whereas the physical data like position, velocity, angle, need reset in refresh(). You could architect around that, but I'm trying to learn the language mechanics.
Re: templates and traits
On Saturday, 18 March 2023 at 20:42:50 UTC, Nick Treleaven wrote: On Saturday, 18 March 2023 at 19:22:07 UTC, Chris Katko wrote: ... So there's multiple sub-problems to solve. I asked this years ago, and got 90% of the way done and then lost the code and cannot find the original forum post. Maybe it was this?: https://forum.dlang.org/post/dqzxnctucwvyhstfz...@forum.dlang.org YES! I tried google search, forum search, even going through all my accounts posts, even my e-mail. I think I accidentally made that post without logging in so it's not attached to my account posts.
templates and traits
Given: ```D struct pos {float x, y;} draw(myBitmap, pos(320, 240), centered); draw(pos(320, 240), myBitmap); draw("text", myFont, pos(320, 240)); ``` I'm writing a general "draw" template function that through compile-time, calls an associated DAllegro/Allegro 5 function: ``` draw(myBitmap, pos(320, 240), centered); // al_draw_bitmap(myBitmap, pos.x - myBitmap.w/2, pos.y - myBitmap.h, 0); draw(pos(320, 240), myBitmap); // order doesn't matter draw("text", myFont, pos(320, 240)); // different function al_draw_text(...) ``` So there's multiple sub-problems to solve. I asked this years ago, and got 90% of the way done and then lost the code and cannot find the original forum post. The pos(320,240) part works fine already. I need: - At compile-time, for a variadic template that can take any number of arguments, if specific arguments are available, I branch and use them to call a specific applicable C function. I remember I need to write some sort of enum function that checks "IsAny" if an argument is passed at all, as well as one to find where that argument is. Passing duplicates probably don't matter (at least not right now), first valid argument is fine. I can't seem to write code (or find example code online) that does this. But it's something like ```D enum isAny() = ...; void draw(T...)(T) { if(isAny(bitmap)) { // it's a sprite, now find out if we need it rotated, stretched, etc. } is(isAny(string)) { // its text [...] } } ``` A separate problem I've run into is, the 'centered' construct. If I have rotate(25) (rotate 25 degrees), that works. But I cannot just pass a type named "centered" with no variable attached to it, nor can I--I think--pass an enum. I could do centered(false) or centered(0), but that's clunkier than just saying "if 'centered' is an argument, we center it. If not, we don't." I could have a variable named centered, I guess. or an enum with {isCentered=1, notCentered=0} and detect if the enum is passed. Lot's of ways to skin this cat. The idea here, is I've got a lot of optional arguments (centered, tinted, rotated, scaled, sheared, etc) that I can pick from and I don't want to have to sort through a list of 80 different permutations of function signatures, or, one gigantic megafunction with a ton of zeros/nulls for all the unused arguments. This is a bit of a confusing problem to explain, so I've probably left something necessary out.
Convert array of simple structs, to C array of values
```D struct pair { float x; float y; } pair[10] values; import std.conv; auto valuesInCStyle = to!(const float*)(values); ``` Now that's not going to work because (I would imagine) to! doesn't understand x, and y, can be placed in order to give an array of: valuesInCStyle = [values[0].x, values[0].y, values[1].x ,values[1].y, ...] I know there's gotta be some simple one liner function in D, but I can't think of it.
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
On Friday, 1 July 2022 at 13:28:26 UTC, Chris Katko wrote: ...wait, does "world" not 'exist' until after the constructor finishes? Is that's what's going on? But then why does it 'exist' when I send it directly? Is it only "registered" with the module once this() finishes or something like that? Yep, that's it. moving all code in world.this() to world.initialize() and immediately calling initialize, works fine. D g.world = new g.world_t; // code would crash here g.world.initialize(); // doesn't crash if moved here class world { this(){} void initialize(){/*...*/} } class elf : unit { this(pair _pos, atlasHandler atlas/*not used*/) { super(0, _pos, pair(0, 0), g.dude_bmp); anim = new animation(1, elf_coords, g.world.atlas); //not crashing now } } It appears module access to a class is broken until the constructor finishes.
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
On Friday, 1 July 2022 at 13:12:05 UTC, Adam D Ruppe wrote: On Friday, 1 July 2022 at 12:57:01 UTC, Chris Katko wrote: Cannot access memory at address 0x10 Looks like an ordinary null pointer. How did you create the variable? D bool initialize() //called from main { g.world = new world_t; } class atlasHandler{} class animation { this(int _numFrames, ipair[] coordinates, atlasHandler atlas) { } } class world_t { atlasHandler atlas; this() { viewTest(); atlas = new atlasHandler(); units ~= new elf(pair(200, 200), atlas); //crashes } logic() { // doesn't crash units ~= new elf(pair(200, 200), atlas); } } class elf : unit { this(pair _pos, atlasHandler atlas) { super(0, _pos, pair(0, 0), g.dude_bmp); // anim = new animation(1, elf_coords, atlas); //doesn't crash anim = new animation(1, elf_coords, g.world.atlas); //CRASH here isTreeWalker = true; } } also important. it seems to only occur in the constructor. If I create an elf after the world constructor, it's fine. ...wait, does "world" not 'exist' until after the constructor finishes? Is that's what's going on? But then why does it 'exist' when I send it directly? Is it only "registered" with the module once this() finishes or something like that?
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
Forgot the last line. That's important because world MUST exist by time elf is called... because world... created and called elf. So it's not a memory issue, but some sort of linkage issue.
Re: dlang bug - accessing module variable from method segfaults only when using module reference directly
To add, I cannot even access g.world from inside elf's constructor. ... which is the function that called it. D Thread 1 "main" received signal SIGSEGV, Segmentation fault. objects.elf.this(g.pair, objects.atlasHandler) (this=, atlas=, _pos=...) at ./src/objects.d:320 (gdb) bt #0 objects.elf.this(g.pair, objects.atlasHandler) (this=, atlas=, _pos=...) at ./src/objects.d:320 #1 worldmod.world_t.this() (this=) at ./src/worldmod.d:60 #2 main.initialize() () at ./src/main.d:110 #3 main.main(immutable(char)[][]).__lambda6() (__capture=) at ./src/main.d:462 #4 allegro5.system.al_run_allegro(scope int() delegate).main_runner(int, char**) () #5 allegro5.system.al_run_allegro(scope int() delegate) () #6 D main (args=...) at ./src/main.d:461 (gdb) x g.world 0x0:Cannot access memory at address 0x0
dlang bug - accessing module variable from method segfaults only when using module reference directly
dmd (but I think LDC also is affected) this bug has bit me multiple times now, to the point I can recognize it. Accessing module variables, from inside a method, causes a segfault. Even if the variable should be available by then through the call order. Proving that its a bug, you can directly send the exact same variable through an argument, and it works fine. (not sure if this code will do it, last time I tried to replicate it with solely this kind of code, the bug disappeared.) D /// module g.d class world { atlasHandler atlas; void do() { atlas = new AtlasHanlder(); elf e = new elf(atlas); } } /// module 'objects.d' class atlasHandler{} class elf { this(atlasHandler atlas) { assert(atlas !is null); //works fine assert(g.world.atlas !is null); //crashes writefln("atlas [%p] vs g.world.atlas [%s]", atlas, g.world.atlas); // crashes trying to read g.world.atlas } } gdb output (not the exact same module names but you get the point): Thread 1 "main" received signal SIGSEGV, Segmentation fault. (gdb) p atlas $1 = (objects.atlasHandler *) (gdb) p g.world $2 = (worldmod.world_t *) (gdb) p g.world.atlas Cannot access memory at address 0x10 (gdb) p this $3 = (objects.elf *) (gdb) x atlas 0x7fffec1cf380: 0x55826580 (gdb) x g.world.atlas Cannot access memory at address 0x10 It appears that whatever value its sending, is in a protected memory segment and automatically segfaulting even upon reading. Worst case I can public my repo and you can see it for yourself.
Re: nested function overloading
On Wednesday, 22 June 2022 at 12:42:48 UTC, Steven Schveighoffer wrote: On 6/22/22 2:05 AM, monkyyy wrote: On Monday, 20 June 2022 at 13:20:51 UTC, Steven Schveighoffer wrote: And you can also use an inner struct to define overloaded functions. I believe templates make a better bandaid ```d void main(){ template bar(){ void bar_(int){} void bar_(float){} alias bar=bar_; } bar(1); bar(3.14); } ``` Wow, I never thought of that, it's a great idea! You don't even need to use the alias. ```d void main(){ template bar(){ void bar(int){} void bar(float){} } bar(1); bar(3.14); } ``` -Steve Wow! That's great! Another trick to add to my toolbox.
Re: can you initialize a array of POD structs?
On Saturday, 18 June 2022 at 17:52:16 UTC, Adam D Ruppe wrote: On Saturday, 18 June 2022 at 17:37:44 UTC, Chris Katko wrote: D struct pair { float x, y;} pair p[] = [[0, 0], [255, 255], [25,-25]]; //nope An array of pair is `pair[]`, keep the brackets with the type. Then a struct literal is either: pair(0, 0) // using constructor syntax or in some select contexts (including this one): {0, 0} // using named literal syntax Therefore: pair[] p = [{0, 0}, {255, 255}, {25,-25}]; compiles here. Thanks!! One extra caveat for anyone who googles this. You can't use {0, 0} notation if the struct has constructors. Which make sense since you don't want people accidentally bypassing a constructor if it exists.
can you initialize a array of POD structs?
D struct pair { float x, y;} pair p[] = [[0, 0], [255, 255], [25,-25]]; //nope
multidim array with enum
I'm having difficulty figuring out exactly what signature D is expecting. D enum DIR { UP = 0, DOWN, LEFT, RIGHT, UPLEFT, UPRIGHT, DOWNRIGHT, DOWNLEFT, } BITMAP*[2][DIR] bmps; // ... bmps[DIR.UP][0] = nope. bmps[DIR.UP][0] = new BITMAP *; // nope bmps[DIR.UP][0] = new BITMAP; // nope bmps[DIR.UP] = new BITMAP*[2]; // compiles. runtime range violation. I swear this all worked fine when it was just: D bmps[DIR] bmps;
Re: nested function overloading
On Friday, 17 June 2022 at 12:19:33 UTC, bauss wrote: On Friday, 17 June 2022 at 12:09:33 UTC, Chris Katko wrote: I don't need this functionality, but I wanted to be sure. Does function overloading not work with nested functions? I got a compiler error (something like "function already defined") when I tried it. According to the spec then nested functions cannot be overloaded: "Nested functions cannot be overloaded." See: 19.17.1.3 https://dlang.org/spec/function.html#nested Thanks! re: documentation. That is one-line tiny footnote in a page that's over 85 pages long on my browser. :) I could easily see many people missing it until they encounter it.
nested function overloading
I don't need this functionality, but I wanted to be sure. Does function overloading not work with nested functions? I got a compiler error (something like "function already defined") when I tried it.
Re: a struct as an multidimensional array index
On Friday, 10 June 2022 at 17:26:48 UTC, Ali Çehreli wrote: On 6/10/22 08:13, z wrote: > arrays of arrays has different order for declaration and addressing, > and declaring array of arrays has different order depending on how you > declare it and wether it's static or dynamic array, *oof*) > > To give you an idea of the situation : > ```D > int[3][1] a;//one array of 3 int > writeln(a[0][2]);//first "column", third "row" > ``` I've written about this multiple times in the past but D's way is consistent for me. That must be because I always found C's syntax to be very illogical on this. To me, C's problem starts with putting the variable name in the middle: // C code: int a[1][3]; // Why? So, first, D moves the variable to its consistent place: after the type: int i; int[N] arr; Both of those are in the form of "type and then name". Good... And then, here is the consistency with arrays: "type and then square brackets". int[] dynamicArray; int[N] staticArray; So, here is where you and I differ: int[3][1] arr; // Ali likes int[1][3] arr; // z wants I like it because it is consistently "type and then square brackets". (It so happens that the type of each element is int[N] in this case.) If it were the other way, than array syntax would be inconsistent with itself. :) Or, we would have to accept that it is inside-out like in C. But of course I understand how it is seen as consistent from C's point of view. :) And this is consistent with static vs dynamic as well because again it's "type and then square brackets": int[1][] a; // A dynamic array of int[1] int[][3] b; // A static array of 3 int[]s Ali This is an interesting discussion. I had noticed multi-dim arrays seemed backwards but I assumed I was doing something wrong and had other thing to worry about. I had no idea it was DIFFERENT for static vs dynamic arrays? That's horrifying! Also you reminded me of a possible D bug that I ran into. I had classes that had circular dependencies. One had to know about the other, and vice-versa. And I had derived classes. But somehow, they would explode. I would send one reference to the others constructor to 'link' them together, but the reference would be NULL. But if I accessed the exact same variable through a global reference, it worked fine. I tried ripping the affected code into a new file but the bug wasn't replicated. Even if I matched the compiler/linker options. It was super frustrating.
Re: Run a command-line process with data sent, and retrieve the data.
On Friday, 10 June 2022 at 17:37:30 UTC, Chris Katko wrote: I want to pipe in string data to a shell/commandline program, then retrieve the output. But the documentation I read appears to only show usage for 'Files' for stdin/stdout/stderr. ala something like this: D string input = "hello\nworld"; string output; runProcess("grep hello", input, output); assert(output = "hello"); Okay that's probably incorrect grep, but you get the point.
Run a command-line process with data sent, and retrieve the data.
I want to pipe in string data to a shell/commandline program, then retrieve the output. But the documentation I read appears to only show usage for 'Files' for stdin/stdout/stderr. ala something like this: D string input = "hello\nworld"; string output; runProcess("grep hello", input, output); assert(output = "hello");
a struct as an multidimensional array index
Is it somehow possible to use a struct as a [multidimensional] array index: D struct indexedPair { size_t x, y; } bool isMapPassable[100][100]; auto p = indexedPair(50, 50); if(isMapPassable[p]) return true; Probably not, but I'm curious.
Odd construct idea. Splitting arguments inside a parameter list.
D struct pair { float x,y; } myFunction(float taco, float x, float y, float burrito) { // stuff } myfunction(_taco, _x, _y, _burrito); // call function // But can we do this? pair p; myfunction(_taco, p; _burrito); // p becomes (x,y) and satisfies the two floats in the signature I don't know if I need this but I'm curious if it's a template possibility. Though under-the-hood it could violate some necessary assumption about function signature matching. I'm curious if you can pass a struct of values (a 'tuple'?) with the right subfields, as if those fields occupied a function signature. (As I write this and try to explain it, it probably sounds impossible.) I have an existing API that uses X/Y coordinates, but I like using packed/named tuples (right term?) for related arguments. pos(x,y) vs velocity(x,y) for example make it super easy to tell which x belongs to which construct. Worst case I could just write wrapper functions for like 60+ functions. But it's still an interesting "can D do this" idea that popped into my head tonight. I'm always curious about what's possible. - Note that it doesn't necessarily have the struct fields match the called function argument names. I'm talking about calling with a struct with two floats (of any name), fulfilling two float requirement of a function signature. Is there a way for a tuple/array/some-sort-of-combined object to fulfill two separate function arguments? Of course we could always just do: D pair p; myFunction(taco, p.x, p.y, burrito);
Re: template? mixin? template mixins? for modifying a struct setup
On Thursday, 19 May 2022 at 10:35:30 UTC, ag0aep6g wrote: On 19.05.22 12:15, Chris Katko wrote: given ```D struct COLOR { float r, g, b, a; // a is alpha (opposite of transparency) } auto red = COLOR(1,0,0,1); auto green = COLOR(0,1,0,1); auto blue = COLOR(0,0,1,1); auto white = COLOR(1,1,1,1); //etc ``` is there a way to do: ```D auto myColor = GREY!(0.5); // where GREY!(0.5) becomes COLOR(0.5, 0.5, 0.5, 1.0); ``` What's wrong with a simple plain function? COLOR grey(float rgb) { return COLOR(rgb, rgb, rgb, 1); } auto myColor = grey(0.5); Yeah that occurred to me as I was falling asleep. Though, do I have to a specify ```D static auto myColor = grey(0.5); ``` to ensure it's done at compile time? It's not the end of the world, but ideally, these are static / hardcoded values that can be used thousands of times a second.
template? mixin? template mixins? for modifying a struct setup
given ```D struct COLOR { float r, g, b, a; // a is alpha (opposite of transparency) } auto red = COLOR(1,0,0,1); auto green = COLOR(0,1,0,1); auto blue = COLOR(0,0,1,1); auto white = COLOR(1,1,1,1); //etc ``` is there a way to do: ```D auto myColor = GREY!(0.5); // where GREY!(0.5) becomes COLOR(0.5, 0.5, 0.5, 1.0); ```
Re: Template shenannigans with multiple datatypes
On Friday, 13 May 2022 at 07:05:36 UTC, vit wrote: On Friday, 13 May 2022 at 06:43:39 UTC, Chris Katko wrote: I have an intrinsicGraph(T) class that is given a pointer to a T dataSource and automatically polls that variable every frame to add it to the graph, whether it's a float, double, integer, and maybe bool. [...] I dont understand first qestion but second question has a solution: ```d intrinsic_graph!T make_graph(T, Args...)(auto ref T val, auto ref Args args){ return new intrinsic_graph!T(val, args); } instrinsicGraph!float testGraph; instrinsicGraph!ulong testGraph2; // later testGraph = make_graph(units[0].x, 100, 300, COLOR(1,0,0,1)); testGraph2 = make_graph(g.stats.fps, 100, 500, COLOR(1,0,0,1)); ``` Okay, to clarify just in case I'm very confusing because I'm up late. If I wanted a "multipleGraph". A graph that takes multiple values and plots them on the same graph. I need to store a buffer for each dataSource. Luckily, because I'm painting them to the screen, the buffers only really need to be float even if they started as a boolean, int, or double. However, if I'm keeping a list of pointers to things I want to snoop when I call onTick(), I can't think of a way to support multiple types: ```D class intrinsicGraph(T) { T* dataSource; float[] buffer; void onTick() { //grab datasource data and do something. buffer ~= to!float(*datasource); } } auto g = intrinsicGraph!float(); ``` But what if there's multiple types? ```D class multiGraph(???) { ???[] dataSources; float[] buffers; void onTick() { //grab datasource data and do something. foreach(d, i; dataSources) buffers[i] ~= to!float(*d); //or whatever } } auto g = multiGraph!???(, , ); ``` This is a kinda "dynamic language" feature but it feels like this information is theoretically, knowable at static, compile-time. I know what the variable types will be at compile-time, but I don't know how to put them all in one class and reference them automatically.
Template shenannigans with multiple datatypes
I have an intrinsicGraph(T) class that is given a pointer to a T dataSource and automatically polls that variable every frame to add it to the graph, whether it's a float, double, integer, and maybe bool. This all works fine if you have a single template type. But what if I want ... multiple graphs? I cannot do D class intrinsicGraph(T???) { (void*) dataSources[]; } and have it become whatever datatype I want. Even if I'm always storing the values in a float buffer, the dataSources themselves cannot be multiple types. Basically I'm wondering if there's a way to have D int FPS; float frameTime; // graph myGraph; myGraph.add(); myGraph.add(); and it enumerates through its dataSources array and adds to the relevant buffers. There is a key that might help, they're all types that can resolve to integer or float. I'm not trying to add support for adding myRandomClass or networkPacket. Only things that can resolve down to float in some form. Is there some kind of clue in having an array of Object (the fundamental superclass?)? I don't think this is necessarily a "run time" reflection problem. Because I could make a graph at compile time, and know its of type, say, (T V U). Say, float, double, uint. Some sort of vardiac template. But then how would you store that, unless you use some sort of mixins to write separate variables. (float\* dataSource0 and double\* dataSource1) Or, wrap each pointer in some sort of fat pointer class that stores the type and a void*, and have an array of those fat pointers and and use some compile time voodoo to cast back cast(float)dataSource[0] (zero is always float), cast(uint)dataSource[2] (index 2 has cast(uint) put in). Additional questions: This may sound strange but is there a way to avoid having to specify the template type twice? ```D instrinsicGraph!float testGraph; instrinsicGraph!ulong testGraph2; // later testGraph = new intrinsic_graph!float(units[0].x, 100, 300, COLOR(1,0,0,1)); testGraph2 = new intrinsic_graph!ulong(g.stats.fps, 100, 500, COLOR(1,0,0,1)); ``` It'd be nice if I only had to specify the type once. It'd also be kinda nice if I could hide the fact I need to specify the type at all and have it automatically become whatever type the passed in value is: D instrinsicGraph testGraph(g.stats.fps) //automatically stores an integer buffer.
Re: What are (were) the most difficult parts of D?
On Thursday, 12 May 2022 at 16:04:09 UTC, Ali Çehreli wrote: My view on private has changed over the years. I need to be convinced that there is usage that needs to be protected. :) I don't see people using types freely especially the ones that are in the same module. The only argument for private is to allow changing the implementation of published libraries in the future. I use private as part of my rapid dev process. You write code, you get things working with no real worry for correctness or careful interfaces. You cannot make an interface until you actually know what you're making. So you make things, with "bad" connections. Then you remove those connections. 1. Get system working with lots of direct access to class variables. 2. Make those variables forbidden (through private in C++). 3. The compiler now shows you every instance of your new interface encapsulation violations. No human decision to opt-in. No remembering to search. You have an automatically generated list of violations to fix. I do the same thing with a module called "g" (for globals). I write new code into g, get it working. I can see how "dirty" a file is by simply searching for how many references to the module g there are. Then if I move the code into a proper new module, all references to g magically fail. It is impossible for me to leave dangling old code touching naughty internals, and I get a nice error view of all areas that need attention. If the uses are all over the place and not in only a few areas (instead of just in logic() and draw(), but all over the place) then I know I need to rewrite and introduce a system so everything is mostly in one place. In D, I can do the module based method, but nothing short of renaming variables gives me a list of violations and, that also makes all the correct internal accesses wrong. Because private doesn't work. Call it whatever keyword you want, I really want a 'private' specifier for classes. It's incredibly useful.
A template construct like using()
I swear I asked something like this before years ago but it doesn't show up in my previous forum posts. I'm looking for a construct that mimics using(var)/with(var) D bitmap* b; draw_with(b) { draw_pixel(red, 16, 16); //draw red pixel to bitmap b (b is implied above) } But the code ends up being: D bitmap* b; set_target_bitmap(b); //entry code draw_pixel(red, 16, 16); // body set_target_bitmap(original_target); // exit code The essence is wrapping something the code up in a kind of RAII-like entry and exit code that references a given target variable. Perhaps a mixin is what I'm looking for?
Re: std.typecons Typedef initializers?
On Monday, 25 April 2022 at 12:53:14 UTC, Mike Parker wrote: On Monday, 25 April 2022 at 08:54:52 UTC, Chris Katko wrote: D struct pair { float x,y; } alias sPair = Typedef!pair; // pair of xy in screen space coordinates alias vPair = Typedef!pair; // pair of xy in viewport space coordinates //etc How do you initialize a typedef'd struct? ``d vPair v1 = vPair(pair(1f, 2f)); ``` So to use a typedef'd struct... I have to basically add the original type on top of the typedef'd type every time? Surely it's not this clunky? I mean, why even use a typedef then. Why not use just pair, sPair, vPair, etc as separate types with identical members and cast as necessary? I'm not sure what the benefit typedef is adding here. Thanks
std.typecons Typedef initializers?
D struct pair { float x,y; } alias sPair = Typedef!pair; // pair of xy in screen space coordinates alias vPair = Typedef!pair; // pair of xy in viewport space coordinates //etc void test() { pair v0 = pair(1f, 2f); // works fine, but what about the typedefs? vPair v1 = vPair(1f, 2f); //nope vPair v2 = Typedef!vPair(1f, 2f); //nope } How do you initialize a typedef'd struct?
save and load a 2d array to a file
D struct map_t{ int data[50][50]; } map; //save std.file.write("save.map", map.data); // compiles //load map.data = std.file.read("save.map", map.data.sizeof); // error main.d(536): Error: cannot implicitly convert expression `read("save.map", 2500LU)` of type `void[]` to `ubyte[50][]` I'm guessing here, that internally we've got an array of arrays (which means array of pointers), and D doesn't know how to split by one of the axis. So how do I do that? If I know it's exactly packed as it was before, can I smash it somehow by direct writing a bunch of ubytes? What is the 'smash' way to do it, and if better, what's the elegant way to do it? (In case I need either going forward). Thanks, --Chris
Nested function requires forward declaration?
Using DMD. v2.098-beta-2 Not sure if right terminology. But I just wrote a nested function that uses a variable outside its body. The capture (right term?) is obvious where the invocation is. However, I have to move the declaration of the variable to above the nested function for it to compile. Here is the code that wont compile: D void execute() { bool isKey(ALLEGRO_KEY key) { return (event.keyboard.keycode == key); } ALLEGRO_EVENT event; // later isKey(ALLEGRO_KEY_W); // main.d(491): Error: undefined identifier `event` This however, will compile: D void execute() { ALLEGRO_EVENT event; // <--Only change bool isKey(ALLEGRO_KEY key) { return (event.keyboard.keycode == key); } // later isKey(ALLEGRO_KEY_W); It appears the nested function's variable capture depends on forward declaration (the right term?). Whereas, I was under the impression most/all of D worked on a multiple pass compilation so the order of declarations shouldn't matter. Is this a D spec, or a compiler parsing error/oversight? I guess if I had two different variables called event, this could become confusing code to read except that, mentally these should still link up, right? Hypothetical: D void execute() { bool isKey(ALLEGRO_KEY key) { return (event.keyboard.keycode == key); } { ALLEGRO_EVENT event; isKey(ALLEGRO_KEY_W); } //lets say this does some memory housekeeping/deleting so that's why we use scope { ALLEGRO_EVENT event; //new 'event', same name, new memory isKey(ALLEGRO_KEY_W); } } in this case, 'event' under-the-hood could be renamed, say, "event2" and have the same expected compile time symbol linking occur. The second isKey call is obviously connected to the second 'event' variable. I imagine this is a really odd edge case but it's piqued my interest.
unit test broken [DUB bug?]
Running 64-bit Linux ``` dmd --version DMD64 D Compiler v2.098.0-beta.2 dub --version DUB version 1.27.0-beta.2, built on Sep 7 2021 ``` the following code 'compiles' in one project. ```d unittest { gasdindgaslkdgansklnasgdlknaglkgansklsdg; } void main(){} // compiles, links, and 'runs unit tests' ``` dub [shows compiling, linking, then runs] dub test ``` Running dfile-test-library All unit tests have been run successfully. ``` Which made no sense whatsoever until I placed it into a second, different DUB project and catches it immediately using the same commands and test. In a separate dub project I get the error message: ``` widescreen ~main: building configuration "application"... source/app.d(4,1): Error: undefined identifier `gasdindgaslkdgansklnasgdlknaglkgansklsdg` /usr/bin/dmd failed with exit code 1. ``` I'm not doing anything special with DUB and made both projects within a couple weeks of each other. I tried dub clean, dub, dub test. Still broken. dub.json for broken project ```json { "authors": [ "chris" ], "copyright": "Copyright © 2021, chris", "dependencies": { "crypto": "~>0.2.16" }, "description": "A minimal D application.", "license": "proprietary", "name": "dfile" } ``` dub.json for working project ```json { "authors": [ "chris" ], "copyright": "Copyright © 2021, chris", "description": "A minimal D application.", "license": "proprietary", "name": "widescreen" } ``` dub.json.selections (for broken project only) ```json { "fileVersion": 1, "versions": { "crypto": "0.2.16", "intel-intrinsics": "1.6.1" } } ``` Other than unit testing being broken, everything seems to work fine. I even deleted 99.9% of my code and left only the bad unittest code and a main, and it still compiles. Could it be a bug where the previous unit test (at some point) was valid, and it's caching and still running that one? I have a /.dub/code/ d file I found: ```d module dub_test_root; import std.typetuple; static import notes; alias allModules = TypeTuple!(notes); import std.stdio; import core.runtime; void main() { writeln("All unit tests have been run successfully."); } shared static this() { version (Have_tested) { import tested; import core.runtime; import std.exception; Runtime.moduleUnitTester = () => true; enforce(runUnitTests!allModules(new ConsoleTestResultWriter), "Unit tests failed."); } } ``` Which doesn't appear in the "correct, not compiling" project directory which appears just empty. Possibly because it never successfully compiled a unit test suite.
Re: d strings are the bane of my existance
On Sunday, 5 December 2021 at 16:32:16 UTC, rikki cattermole wrote: The string is not the problem. ```d string ip_address = "192.168.1.1"; auto x = new InternetAddress(ip_address, 8008); ``` That works. A string in D is an alias for immutable(char)[]. This is defined in druntime (object.d). Immutable does cast to const implicitly, so a string argument to the constructor works fine as it has the same meaning. The port however, that needs to be a ubyte/ushort to pass in and not be a string like you had it. Yes! Thank you! I just realized the latter part was broken when I switched to using a uint for the addr. But I didn't know string is an alias for immutable(char)[]! Thank you!
d strings are the bane of my existance
All I want: ```d string ip_address = "192.168.1.1"; auto x = new InternetAddress( ip_string, "8008"); ``` ```d source/app.d(161,16): Error: none of the overloads of `this` are callable using argument types `(string, int)` /usr/include/dmd/phobos/std/socket.d(1472,5):Candidates are: `std.socket.InternetAddress.this()` /usr/include/dmd/phobos/std/socket.d(1519,5): `std.socket.InternetAddress.this(scope const(char)[] addr, ushort port)` /usr/include/dmd/phobos/std/socket.d(1542,5): `std.socket.InternetAddress.this(uint addr, ushort port)` /usr/include/dmd/phobos/std/socket.d(1550,5): `std.socket.InternetAddress.this(ushort port)` /usr/include/dmd/phobos/std/socket.d(1562,5): `std.socket.InternetAddress.this(sockaddr_in addr)` ``` So InternetAddress cannot be constructed with a string. Only a const(char)[]. But toStringz gives me a immutable(char)*, which sounds like the same thing but isn't. and .dup on that just explodes. cast doesn't seem to work. to! doesn't seem to work. I know there "is" a solution, it's just so odd to have this much difficulty using a string.
sleeping vs sched_yield
there's: ```d import core.thread; Thread.sleep( dur!("msecs")(10) ); ``` but what if you want to simply yield all remaining time back to the time scheduler? Is there a D std.library accessible version of POSIX sched_yield: https://man7.org/linux/man-pages/man2/sched_yield.2.html It seems I can (thanks to the amazing work of D community) simply do: ```d extern(C) int sched_yield(void); // #include ``` however, how does the linker know I need and not some local library, or SDL library, or SDL2.0 library, etc. Shouldn't I be specifying the library somewhere? Side side question: The above line fails to compile as-is because it has (void) instead of (). ``` source/app.d(226,16): Error: cannot have parameter of type `void` ``` Should that be corrected in the compiler? Shouldn't () and (void) be interchangeable as long as you're not doing void*?
automatic NaN propogation detection?
Is there any automatic compiler-based or library methods for detecting NaNs? I mean, if the compiler is outputting code that it knows is going to be set in memory to NaN, why isn't it giving me at least a compiler warning? Is that some sort of "NP complete" can't-fix issue or something? I mean, I can pass NaN to std.math.round() and it doesn't fire off an exception or anything. It compiles fine even though it's impossible-as-compiled to be correct. (Unless my absurd intention was to find the rounded value of NaN.) Instead, I'm stuck finding out where the NaN started, from a trail of destruction of values destroyed by NaN propogation. Why not stop it at its source? Even dscanner won't flag this code! ```d import std.stdio; import std.math; int main() { float x; writeln(x); writeln(round(x)); return 0; } ```
Re: Is this a compiler aliasing bug?
On Friday, 17 September 2021 at 10:29:12 UTC, bauss wrote: On Friday, 17 September 2021 at 09:44:53 UTC, Chris Katko wrote: [...] It's not a bug because "obj.x" referes to the same symbol that is "this.x" Alias will create an alias for a symbol, not an expression or the like. So obj.x is the same as this.x and in that case the alias will refer to the same thing. The problem here is that the function is local to the class, so the alias will always refer to the class members directly and not the passed instance. You really shouldn't use alias like this anyway and should just use auto, if it's because you want to save typing. It shouldn't have any impact at all tbh. Thanks everyone! Okay, so yeah, back in 2017 I definitely was still learning D. And, after a year or two, I was re-learning it... using this bad learner codebase! There's been plenty of other things I had to fix that are "no-nos" in my modern codebases.
Is this a compiler aliasing bug?
I'm debugging some code I wrote back in 2017 and a bounding box collision detection kept giving spurious answers till I resorted to assuming nothing and dumped every variable and alias. I kept getting results like it was checking against itself, and of course, that would result in finding a collision. So I threw an assert in to check if it was identical objects (as in an error outside this function), and it didn't fire off. It appears (unless my eyes are deceiving me?) that variable aliases themselves are broken. $ dmd --version DMD64 D Compiler v2.098.0-beta.2 code: ```d class drawable_object_t obj; bool is_colliding_with(drawable_object_t obj) //was a class member { assert(this != obj); //does not fire off alias x1 = x; alias y1 = y; alias w1 = w; alias h1 = h; alias x2 = obj.x; alias y2 = obj.y; alias w2 = obj.w; alias h2 = obj.h; writeln("x1: ", x1, " y1: ", y1, " w1: ", w1, " h1: ", h1); writeln("x2: ", x2, " y2: ", y2, " w2: ", w2, " h2: ", h2); writeln("x1: ", x, " y1: ", y, " w1: ", w, " h1: ", h); writeln("x2: ", obj.x, " y2: ", obj.y, " w2: ", obj.w, " h2: ", obj.h); } /* output: x1: 50 y1: 81 w1: 5 h1: 6 x2: 50 y2: 81 w2: 5 h2: 6 < x1: 50 y1: 81 w1: 5 h1: 6 x2: 200 y2: 86.54 w2: 26 h2: 16 < */ ``` The arrows point to the dependency. The top two sets of numbers should _not_ be identical.
Re: sort a string
On Friday, 1 May 2020 at 08:17:33 UTC, norm wrote: On Friday, 1 May 2020 at 07:38:53 UTC, Chris Katko wrote: [...] You need to convert the sort output to dchar[], e.g. --- dchar[] line3 = sort(line2.to!(dchar[])).to!(dchar[]); --- Cheers, Norm That works, thanks!
sort a string
I'm making anagrams. According to the nextPermutation() docs, I need to 'sort by less' to get all permutations. ... Except the doc page doesn't mention how to do that, nor does std.algorithm.sort show how to sort a string. ... and the google results on the dlang forums from 2017 don't work. I've tried .byCodeUnit. , .representation. I've tried sorting on the dchar. I've tried sorting the on string. The closest I've gotten: string word = "bar"; string line2 = toLower!(string)(word); dchar[] line3 = sort(line2.to!(dchar[])); "Error: cannot implicitly convert expression sort(to(line2)) of type SortedRange!(dchar[], "a < b") to dchar[]"
Re: Get memory used by current process at specific point in time
On Sunday, 12 January 2020 at 13:58:18 UTC, Per Nordlöw wrote: Is there a druntime/phobos function for getting the amount of memory (both, stack, malloc, and GC) being used by the current process? Valgrind will tell you the exact usage (except no delineation for GC) per here: https://stackoverflow.com/questions/131303/how-to-measure-actual-memory-usage-of-an-application-or-process Valgrind is an overall extremely useful tool for Linux devs. Still, some internal instrumentation would be nice. But I'm not aware of any.
Re: Practical parallelization of D compilation
On Wednesday, 8 January 2020 at 06:51:57 UTC, H. S. Teoh wrote: On Wed, Jan 08, 2020 at 04:40:02AM +, Guillaume Lathoud via Digitalmars-d-learn wrote: [...] [...] Generally, the recommendation is to separately compile each package. E.g., if you have a source tree of the form: src/ src/main.d src/pkg1/mod1.d src/pkg1/mod2.d src/pkg2/mod3.d src/pkg2/mod4.d then you'd have 3 separate compilations: dmd -ofpkg1.o src/pkg1/mod1.d src/pkg1/mod2.d dmd -ofpkg2.o src/pkg2/mod3.d src/pkg2/mod4.d dmd -ofmyprogram src/main.d pkg1.o pkg2.o The first two can be done in parallel, since they are independent of each other. The reason per-package granularity is suggested is because the accumulated overhead of separately compiling every file makes it generally not worth the effort. D compiles fast enough that per-package compilation is still reasonably fast, but you no longer incur as much overhead from separately compiling every file, yet you still retain the advantage of not recompiling the entire program after every change. (Of course, the above example is greatly simplified; generally you'd have about 10 or more files per package, and many more packages, so the savings can be quite significant.) T What's the downsides / difficulties / "hoops to jump through" penalty for putting code into modules instead of one massive project? Is it just a little extra handwriting/boilerplate, or is there a performance impact talking to other modules vs keeping it all in one?
Re: Using tasks without GC?
Thanks everyone, looks like i'll have to benchmark myself (which is fine) but I'm always afraid because I know "proper benchmarking is hard. (TM)" Feel free to throw any other side advice in. I'm looking to get a broad perspective on this. Straight up shutting off the garbage collector in exchange for memory is an interesting concept. But I wonder how quickly it will get eaten up. ALSO, if I do shut it off, when i turn it on is it going to take much longer? Does the GC take linear / quadratically more time based on the N of "items need to be freed"? The thing is, I'm looking to parallelize a dedicated server for running MASSIVE numbers of objects (1's or 10's) at high tick rate. Worse, for my particular "game mode", the "rounds" can last hours. So while a slow crawl of RAM is okay, it won't be okay if it hits 30 GB in an hour. So that's going to be another "it works IF it works [in our particular game/application]" as opposed to "this definitely will/won't work". That's more "benchmarking and see" scenarios, which I'm trying to avoid as much as possible. You normally don't want to willfully START a project with a design where the only way to know if it works... is to bench. There's also an option of periodically firing off (without ending the game) say, once every hour and tell everyone to just "live with it" because it's (I HOPE!) not going to be a 15/30/60 second delay. In my particular application, that still wouldn't be that disruptive. (Unless turning GC off hits max ram every couple minutes. Then again nobody is going to be okay with that.) On Saturday, 4 January 2020 at 11:30:53 UTC, dwdv wrote: Creates a Task on the GC heap that calls an alias. If possible, there's also scopedTask, which allocates on the stack: https://dlang.org/phobos/std_parallelism.html#.scopedTask So my question is: Has anyone done any analysis over how "dangerous" it is to use GC'd tasks for _small_ tasks (in terms of milliseconds)? Nothing major, but https://github.com/mratsim/weave/tree/master/benchmarks/fibonacci puts quite a bit of pressure on various implementations. You might want to profile ./pfib 40: import std; ulong fib(uint n) { if (n < 2) return n; auto x = scopedTask!fib(n-1); // vs. Task!fib(n-1); taskPool.put(x); auto y = fib(n-2); return x.yieldForce + y; // {yield,spin,work}Force } void main(string[] args) { enforce(args.length == 2, "Usage: fib number requested>"); auto n = args[1].to!uint; // defaultPoolThreads(totalCPUs); writefln!"fib(%d) = %d"(n, fib(n)); } At least D isn't locking up beyond 12 tasks; looking at you, stdlib-nim. :)
Using tasks without GC?
When I program, it's usually videogame ideas. That implies a soft, real-time requirement. In general, that requires the mantra "allocations are evil, use object pools whenever possible." [storing data in static arrays and 'deleting' is usually just marking an entry as is_deleted=true and re-using "dead" ones.] I'm looking through D's parallelism module and the docs state, up-front: >Creates a Task on the GC heap that calls an alias. The modern, scalable way to make a parallel game engine uses tasks. (as opposed to functional decomposition where 1 thread is networking 1 thread is physics, etc.) That requires making LOTS of tasks (_per frame_!) and dispatching them. And a 60 FPS frametime is... 16 ms or less. So my question is: Has anyone done any analysis over how "dangerous" it is to use GC'd tasks for _small_ tasks (in terms of milliseconds)? Is the GC going to fire off all the time and send jitter off the charts? Because while freeze-the-world for 20 milliseconds would probably be unnoticable for many business apps, it would completely break a videogame. I wonder how difficult it would be to either modify the existing parallel task codebase (or, write my own?) to use static pools instead. Allocate once an array of "MAX_NUM_TASKS" tasks (eating the minor memory hit) to prevent touching any allocation. [Even if it wasn't GC, allocating every frame in say, C++, is dangerous. malloc/new is slow and subject to fragmentation and permissions checks.] Any advice, thoughts? Thanks, --Chris Katko
Why is this allowed? Inheritance variable shadowing
You can drop this straight into run.dlang.io: import std.stdio; class base{ float x=1;} class child : base {float x=2;} //shadows base variable! void main() { base []array; child c = new child; array ~= c; writeln(c.x); //=2 writeln(array[0].x); //=1 //uses BASE's interface, yes, //but why does the CHILD instance one exist at all? } It appears to be legal C++ as well but I can't imagine a situation where you'd want to allow the HUGE risk of shadowing/aliasing variables in an child class. Why is inheritance shadowing allowed? Especially when in D you have to explicitly "override" existing _methods_ but not fields/variables? To quote a Stack Overflow comment on C++ having this "It's not a compile error, but it's certainly a design one." Is this allowed just because "C++ does it" or because it has some sort of real world use that justifies the risk? Personally, I'd love a compile-time warning that I could turn on that flags this situation. Thanks for your help, --Chris
Easiest way to use Linux system C files / tiny C libraries
What's the easiest way to use POSIX and Linux-specific C include files? I know you can write a wrapper but it seems like half the time these files include 20 files which include 20 files which use strange enums, arrays, etc that don't clearly have answers on how to wrap them. Is there something I'm missing? For example, right now, the most recent problem I've had related to this is wanting to use the libprocps-dev library. All it does is expose the /proc/ process data in an easy-to-use format. I "could" write my own in D but then once again, I've not solved my re-occurring problem of "what if I DO need a C library." Do I need to implement every piece of a C header / library, or can I get away with a tiny subset that I'm actually using? I don't know. I know this is all vague. But I've run into this problem multiple times and every time, after hours of googling, never gotten anywhere. Thanks.
Re: D is supposed to compile fast.
On Saturday, 24 November 2018 at 20:44:57 UTC, welkam wrote: On Friday, 23 November 2018 at 08:57:57 UTC, Chris Katko wrote: D is supposed to compile fast. You didnt read the fine print. It compiles simple code fast. Also compilation is separate step from linking and your program might spend half of "compilation" time in link phase. Wait wait wait wait wait. So 1) I have to compile manually, then link. Except that also runs the files every time even if they're up-to-date. Is that normal behavior for C/C++? Two questions/topics/issues: --- #1 How to I only build files that are dirty? Do I actually need a build program like DUB, MAKE, or CMAKE to do that? (Can make, cmake be used?) How do they recognize files are out-dated if DMD can't? Is that just an industry-standard specialization/separation-of-responsibilities to not have the compiler auto-detect up-to-date builds? I have the simplest project ever. Less than 10 files and my non-VStudio build-scripts have always been simple. A few lines or one long line running GCC/Clang/etc. I don't want to learn a make program's huge syntax just to compile a program if I can avoid it! (I've still got so many D and networking topics to learn on the back-burner!) I've heard "just use dub" but I've also heard that dub have flaws/gotchas that I can't remember when it comes to say, dynamic linking DLLs/SOs. So I've been hesitant to learn it. #2 I ran individual file times. They're pretty shocking. --- std.regex is still, the Devil (TM), clocking in at almost FOUR SECONDS for a very simple set of code that simply matches lines for a poor-man's INI file parser (with a custom feature that allows tab indents to be nested sections). I was considering ripping it out and replacing it with JSON and this has REALLY motivated me to rip out the regex. Here's the file times: novous@saturn:~/Desktop/bitbucket/ss14$ time dmd -c molto.d Class 4 - Scaled Rotated hello hello -- it matches! real0m0.377s user0m0.344s sys 0m0.028s novous@saturn:~/Desktop/bitbucket/ss14$ time dmd -c helper.d real0m0.118s user0m0.096s sys 0m0.020s novous@saturn:~/Desktop/bitbucket/ss14$ time dmd -c editor.d real0m0.626s user0m0.536s sys 0m0.072s novous@saturn:~/Desktop/bitbucket/ss14$ time dmd -c common.d real0m0.755s user0m0.636s sys 0m0.092s novous@saturn:~/Desktop/bitbucket/ss14$ time dmd -c map.d real0m1.045s user0m0.904s sys 0m0.112s novous@saturn:~/Desktop/bitbucket/ss14$ time dmd -c object_t.d real0m0.359s user0m0.336s sys 0m0.024s novous@saturn:~/Desktop/bitbucket/ss14$ time dmd -c animation.d real0m0.365s user0m0.280s sys 0m0.068s novous@saturn:~/Desktop/bitbucket/ss14$ time dmd -c ini.d real0m3.672s <--- WOWZA user0m3.292s sys 0m0.332s I have to tell you that, as an outsider (who is VERY interested in D), this is very frustrating. "Compile times are fast" != "build times" is a huge misconception that borders on being a clever lie or twisting of words. When people hear "compile times", they think "time to compile the whole project" not "time to compile a simple test case that doesn't use any typical D features--also, it's not linking." Second, as shown here, it's not fast even for compiling! Because the second you touch std.regex (which has NO WARNINGS in the documentation), you're greeted with another clever lie-by-omission: a 10x explosion of build time over some modules. Now let's stop for a moment. I'm not accusing anyone, and "lie" is a strong word with heavy guilt implications--like people are intentionally being very sneaky to deceive new-comers. I'm not saying any of that, so you can relax and put down the pitchfork. I'm not attacking you or your group personally. However, I can't think of any better word. So my point is, I keep running into either misconceptions that conveniently make D look good, and other gotchas with NO DOCUMENTATION that make the language much slower to work with than expected. And if I'm experiencing this, there are dozens (hundreds?) who hit the same roadblocks and gotchas and many people are much less forgiving/understanding than I am and simply just "give up" without ever telling you. So I'm trying to say this with the best of intentions. You can't have standard modules with no warning documentation that explode your RAM usage and compile times orders-of-a-magnitude more than other ones. You can have an "alpha" or "beta" or "Addon" or "external" module. But putting it in your standard framework implies that it works well with the other modules (::cough::std.variant and threads::cough::), and that it's not incredibly slower or more resource intensive. Having it in your standard library implies it meets a certain _STANDARD_. I mean, can you think of any module in the
Re: D is supposed to compile fast.
On Friday, 23 November 2018 at 10:00:17 UTC, Nicholas Wilson wrote: If you pass all the files on the command line then they all get (re)compiled. How are you supposed include files if not passing them to the compiler? I'm only using std.regex in one file, IIRC, so whatever the "proper" way to only compile changed files should improve it drastically. Almost all of my templates are incredibly simple like using generic arguments for taking float and doubles, instead of hardcoded float. I am using both Allegro and DAllegro (a D binding for Allegro5). But until recently, the compile times have been very fast. So it's definitely been D features cutting things down. And as for "compile-time doesn't matter" arguments, that's plain silly. I'm not a junior programmer. I've had builds that took over 30 minutes to compile and as we all (should!) know, the longer the build time (especially over 10 seconds), the quicker the mind loses its train-of-thought and the more difficulty the brain has with establishing cause-and-effect relationships between code and bugs. When our builds hit 30 minutes, we ended up so disconnected from the project we'd end up playing a short game of Duke Nukem 3-D inbetween builds. (Ha! Builds. Build engine = the Duke Nukem 3D engine. A super-niche pun.) We were incredibly unproductive until I re-wrote the entire thing in a different language. It ran in less than 10 seconds and suddenly we were powering through new problem after new problem. (A huge data conversion project between a discontinued, no-documentation product and a new product by a different company.) Anyhow, if you REALLY want to look at some very WIP code with poor documentation and possibly lots of random swearing (hobby project for trying out D in a game), I'll make the repo public for now: https://bitbucket.org/katasticvoyage/ss14/src/master/ extra.d is a main code unit for this application. ini.d has regex. (and no, it's not a proper lexer. I'm probably swapping it out with JSON.)
D is supposed to compile fast.
Any time I see people mention the benefits of D, I see "compile times" "compile times" "compile times" over and over. I'm using very modest amounts of templates, for a fairly small sized program (very early work toward a game), and I'm hitting ~15 seconds compile time in LDC and ~7 seconds in DMD. And I'm not even compiling with optimizations! ldc2 -w -ofextra extra.d molto.d helper.d editor.d common.d map.d object_t.d animation.d ini.d -L-L. $@-gc -d-debug=3 -de -fdmd-trace-functions dmd -w -ofextra extra.d molto.d helper.d editor.d common.d map.d object_t.d animation.d ini.d -profile=gc -profile -g -debug -color -L-L. I keep putting stuff into new files, but it feels like it's compiling everything from scratch / not getting faster the way C++ does. And I'm not even bringing up the 800MB of RAM required because I dared to import std.regex. (On a laptop with 2 GB of RAM. RIP. If I dare to have tabs open, the compile time goes into the minutes thanks to swapping.)
Re: Why does nobody seem to think that `null` is a serious problem in D?
Try to learn D. Put writeln in deconstructor to prove it works as expected Make random changes, program never runs again. Takes 30+ minutes to realize that writeln("my string") is fine, but writeln("my string " ~ value) is an allocation / garbage collection which crashes the program without a stack. My favorite D'ism so far:
Re: Why is stdio ... stdio?
On Saturday, 10 November 2018 at 13:53:14 UTC, Kagamin wrote: On Friday, 9 November 2018 at 09:11:37 UTC, Jonathan M Davis wrote: No, I didn't. I just used underscores, which has been used with plain text for emphasis for decades. Supporting markdown, would involve stuff like backticks for code highlighting Backticks are from ddoc. What's the other way to indicate a code fragment? markup for urls - stuff that doesn't actually provide information to someone who's reading plain text but just gets in the way If the url is messy, it's already a mess. If it isn't, it's easier to leave url as is than bother to markup it. whereas the underscores _do_ provide information to someone reading plain text. I think what's really missing is code highlighting. Emphasis isn't very useful, in your example the verb "do" is already emphasis, so markup doesn't provide any additional information, just gets in the way. There is another possibility. Have the website run (fallible) heuristics to detect a snippet of code and automatically generate it. That would leave the mailing list people completely unchanged. However, HOW fallible becomes a huge issue. It may be so well implemented that nobody ever complains. Or, it could be so bad that it often breaks up the author's post in ways the author never planned--almost taking away the poster as the controller of what they present. That's a bit of an extreme, and unlikely, but I feel that examining extremes can be helpful to define the potential domain of the problem. We can also easily have a checkmark next to each post that disables highlighting for that post (as well as disable them in your account settings), and even a button people could press that says "this post is highlighted wrong." and the developer would get a log with the code. How many implementation "fixes" are needed depends on how fallible the detection code really is. -- But, really, I don't personally see it being "that" bad for people to put code tags / code markers around code. It's not like they're going to be peppered everywhere. If you can ignore a comment in code, you can ignore two tags (start and end) in a single post. It's an interesting argument to extend bold and italics... because people ARE already using them! But I never suggested we should support "full markdown". There's no need to support an entire standard if your forum only needs part of it. It seems like a reasonable compromise favoring maximum utility, to support code tags, as well as tags people already use like italics and bold. Automatic URL linking is a feature of 99% of forums and that would also have zero impact on the mailing list people. There may be others. Even if the goal is "minimum changes for mailing list people" it can still be done.
Re: Why is stdio ... stdio?
On Friday, 9 November 2018 at 09:11:37 UTC, Jonathan M Davis wrote: On Friday, November 9, 2018 1:27:44 AM MST Kagamin via Digitalmars-d-learn wrote: On Friday, 9 November 2018 at 06:42:37 UTC, Jonathan M Davis wrote: > [...] You used markdown three times in your message. No, I didn't. I just used underscores, which has been used with plain text for emphasis for decades. Supporting markdown, would involve stuff like backticks for code highlighting, and special markup for urls - stuff that doesn't actually provide information to someone who's reading plain text but just gets in the way, whereas the underscores _do_ provide information to someone reading plain text. - Jonathan M Davis FYI, Allegro.CC just uses int main() { return 0; } as well as for pre-formatted "monospace" text. Neither of those would pollute a mailing list in plain-text mode because they'd exist only at the start and end of code. I'm sure you had no problem reading my above code.
Why is stdio ... stdio?
Simple curious question. Why isn't : import std.stdio; instead: import std.io; (Also, while we're at it. Why doesn't this form have code highlighting? It would much improve readibility. Doesn't that seem almost essential for a programming forum?) I mean, I get it. stdio is the c header from a thousand years ago. But this isn't C. So it's kind of odd to ask for the "Standard standard" io library.
Re: lazy variables
On Wednesday, 17 October 2018 at 07:32:37 UTC, aliak wrote: Hi, Is there any notion of lazy vars in D (i see that there're parameters)? i.e: struct S { //... int y; //... } lazy S x = () { // do some heavy stuff }(); if (condition) { func(x.y); // heavy stuff evaluated here } Cheers, - Ali This might be helpful: https://dlang.org/articles/lazy-evaluation.html
Why doesn't foreach support iterating?
int [50]data; foreach(i, datum; data){} // works File file("gasdgasd"); foreach(i, line; file.byLine){} //NOPE. foreach(line; file.byLine){} //works. I finally noticed in the docs it says "for arrays only." The question is, why? Every language that I used previously (as far as I can remember) implemented foreach in a way that's consistent / orthogonal. Is there a way around this? Because currently I have to liter my foreach's with ugly manual index variables that hold scope even after it's gone. int i = 0; foreach(line; file.byLine){ //do stuff i++; } i = 2; // still exists!
Re: std.regex is fat
On Sunday, 14 October 2018 at 03:26:33 UTC, Adam D. Ruppe wrote: On Sunday, 14 October 2018 at 03:07:59 UTC, Chris Katko wrote: For comparison, I just tested and grep uses about 4 MB of RAM to run. Running and compiling are two entirely different things. Running the D regex code should be comparable, but compiling it is slow, in great part because of internal templates... There was an effort to speed up the template code, but it is still not complete. I know that. I figured people would miss my point on it though so I should have clarified. That's why I said it's likely the templates/DMD that's exploding--not the actual regex action. From a simple program, it takes ~100-150MB of RAM to compile. Adding a single regex (not compiled regex) balloons to 550MB at 5 seconds of compile time. --- Anyhow, I wrote my own simple "dgrep" and compared the results with grep, it's very competitive: (NOT to be confused with the above RAM stats for COMPILING) Command being timed: "sh -c cat dgrep.d | ./dgrep 'write' " User time (seconds): 0.00 System time (seconds): 0.00 Percent of CPU this job got: 0% Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00 Average shared text size (kbytes): 0 Average unshared data size (kbytes): 0 Average stack size (kbytes): 0 Average total size (kbytes): 0 Maximum resident set size (kbytes): 3192 Average resident set size (kbytes): 0 Major (requiring I/O) page faults: 0 Minor (reclaiming a frame) page faults: 301 Voluntary context switches: 5 Involuntary context switches: 124 Swaps: 0 File system inputs: 8 File system outputs: 8 Socket messages sent: 0 Socket messages received: 0 Signals delivered: 0 Page size (bytes): 4096 Exit status: 0 Command being timed: "sh -c cat dgrep.d | grep 'write'" User time (seconds): 0.00 System time (seconds): 0.00 Percent of CPU this job got: 0% Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00 Average shared text size (kbytes): 0 Average unshared data size (kbytes): 0 Average stack size (kbytes): 0 Average total size (kbytes): 0 Maximum resident set size (kbytes): 2224 Average resident set size (kbytes): 0 Major (requiring I/O) page faults: 2 Minor (reclaiming a frame) page faults: 282 Voluntary context switches: 10 Involuntary context switches: 0 Swaps: 0 File system inputs: 760 File system outputs: 0 Socket messages sent: 0 Socket messages received: 0 Signals delivered: 0 Page size (bytes): 4096 Exit status: 0 So I have to say I'm impressed with the actual performance of the regular expressions engine--especially considering "grep" is, IIRC, considered a fine-tuned beast.
Re: std.regex is fat
On Sunday, 14 October 2018 at 02:44:55 UTC, Chris Katko wrote: On Friday, 12 October 2018 at 13:42:34 UTC, Alex wrote: [...] So wait, if their solution was to simply REMOVE std.regex from isEmail. That doesn't solve the regex problem at all. And from what I read in that thread, this penalty is paid per template INSTANTIATION which could explode. [...] For comparison, I just tested and grep uses about 4 MB of RAM to run. So it's not the regex. It's the dmd / templates / CTFE, right?
Re: std.regex is fat
On Friday, 12 October 2018 at 13:42:34 UTC, Alex wrote: On Friday, 12 October 2018 at 13:25:33 UTC, Chris Katko wrote: Like, insanely fat. All I wanted was a simple regex. The second include a regex function, my program would no longer compile "out of memory for fork". /usr/bin/time -v reports it went from 150MB of RAM for D, DAllegro, and Allegro5. To over 650MB of RAM, and from 1.5 seconds to >5.5 seconds to compile. Now I have to close all my Chrome tabs just to compile. Just for one line of regex. And I get it, it's the overhead of the library import, not the single line. But good gosh, more than 3X the RAM of the entire project for a single library import? Something doesn't add up! Hm... maybe, you run into this: https://forum.dlang.org/post/mailman.3091.1517866806.9493.digitalmar...@puremagic.com So wait, if their solution was to simply REMOVE std.regex from isEmail. That doesn't solve the regex problem at all. And from what I read in that thread, this penalty is paid per template INSTANTIATION which could explode. 1 - Does anyone know WHY it's so incredibly fat? 2 - If this isn't going to be fixed anytime soon, shouldn't there be a DISCLAIMER on the documentation? (+potential workarounds like keeping regex queries in their own file.) I mean, this kind of thing shouldn't require looking through forums. It's a clear bug, and if it's a WONTFIX (even temporarily), it should be documented clearly as such. If I'm running into this issue, how many other people already did, and possibly even gave up on using D?
std.regex is fat
Like, insanely fat. All I wanted was a simple regex. The second include a regex function, my program would no longer compile "out of memory for fork". /usr/bin/time -v reports it went from 150MB of RAM for D, DAllegro, and Allegro5. To over 650MB of RAM, and from 1.5 seconds to >5.5 seconds to compile. Now I have to close all my Chrome tabs just to compile. Just for one line of regex. And I get it, it's the overhead of the library import, not the single line. But good gosh, more than 3X the RAM of the entire project for a single library import? Something doesn't add up!
Re: Why are 2-D arrays reversed?
On Wednesday, 10 October 2018 at 16:00:42 UTC, Steven Schveighoffer wrote: On 10/10/18 9:22 AM, Chris Katko wrote: int[][] data = [ [1, 0, 1, 0, 0], [1, 0, 1, 0, 0], [1, 0, 1, 1, 1], [1, 0, 0, 1, 0], [5, 1, 1, 1, 0] ]; when drawn with data[i][j], prints the transpose of "data": [1, 1, 1, 1, 5] [0, 0, 0, 0, 1] [1, 1, 1, 0, 1] [0, 0, 1, 1, 1] [0, 0, 1, 0, 0] So, if I flip [i][j] and print a row of "j's", it'll be correct. It's very confusing and counter-intuitive to have to remember to swap i and j every time I use an array. I guess when I load data from files, the i/j are already swapped and stay consistent, but when using an array in source code, they have to be flipped. I'm not sure what code you are using, but it prints out just fine for me: https://run.dlang.io/is/hrA0tj -Steve Ah, here's a simple example: int[][] data3 = [ [1, 0, 1, 0, 0], [1, 0, 1, 0, 0], [1, 0, 1, 1, 1], [1, 0, 0, 1, 0], [5, 1, 1, 1, 0] ]; for(int i = 0; i < 5; i++) { for(int j = 0; j < 5; j++) { write(data4[i][j]," "); } writeln(); } 1 0 1 0 0 1 0 1 0 0 1 0 1 1 1 1 0 0 1 0 5 1 1 1 0 I have to draw j's first. I have to iterate through the "y"/columns/j to get the the "x's" first. I mean, I guess it makes sense if the outer-most array indexer refers to the inner-most "element". Wait, this IS the same as C, isn't it? So maybe this is just a "new" problem for me since I rarely-if-ever use hardcoded arrays... Maybe my brain is just melting.
Why are 2-D arrays reversed?
int[][] data = [ [1, 0, 1, 0, 0], [1, 0, 1, 0, 0], [1, 0, 1, 1, 1], [1, 0, 0, 1, 0], [5, 1, 1, 1, 0] ]; when drawn with data[i][j], prints the transpose of "data": [1, 1, 1, 1, 5] [0, 0, 0, 0, 1] [1, 1, 1, 0, 1] [0, 0, 1, 1, 1] [0, 0, 1, 0, 0] So, if I flip [i][j] and print a row of "j's", it'll be correct. It's very confusing and counter-intuitive to have to remember to swap i and j every time I use an array. I guess when I load data from files, the i/j are already swapped and stay consistent, but when using an array in source code, they have to be flipped.
Re: How do you iterate "vertically" over a 2-D array?
On Tuesday, 9 October 2018 at 10:52:47 UTC, Chris Katko wrote: I have a 2-D array: int[5][5] data = [ [1, 0, 1, 0, 0], [1, 0, 1, 0, 0], [1, 0, 1, 1, 1], [1, 0, 0, 1, 0], [1, 1, 1, 1, 0] ]; 1 - Is there a way to foreach vertically through that? (that is, rotated 90 degrees from the usual iteration.) 2 - Is there a way to send that "vertical slice" to a function? int count_numbers(){/*...*/} count_numbers(data[0]); //horizontal sum of array[0][0..$-1] WORKS. count_numbers(data[][0]); //vertical sum of array[0..$-1][0] HYPOTHETICAL I'm working on an RLE encoding function and I need both vertical and horizontal strips. It just occurred to me that the problem is essentially the same, if you can "transpose" the matrix. Oh geez, did I just realize what I need? some sort of matrix transpose function? I found this post; https://forum.dlang.org/post/na8ikk$2ojo$1...@digitalmars.com The problem is though, even if I use [][], instead of [5][5] (or try using his conversion function), I can call transposed... but I can't call my function with it! void run_rle3(int [] a){/*...*/} run_rle3(data[0]); //works run_rle3(data.transposed[0]); //nope [see error below] run_rle3(data[0].transposed); //nope (didn't expect this to) run_rle3((data.transposed)[0]); //nope [see error below] Error: function dmap.run_rle3 (int[] a) is not callable using argument types (Transversal!(int[][], cast(TransverseOptions)0)) So according to this: https://dlang.org/library/std/range/transposed.html It's trying to take my [0] as an argument for the TransverseOptions variable? But even if I wrap it in parenthesis, it still takes it! (See the last line of code.) auto taco = (data.transposed); run_rle3(taco); //same error, but < HERE?
How do you iterate "vertically" over a 2-D array?
I have a 2-D array: int[5][5] data = [ [1, 0, 1, 0, 0], [1, 0, 1, 0, 0], [1, 0, 1, 1, 1], [1, 0, 0, 1, 0], [1, 1, 1, 1, 0] ]; 1 - Is there a way to foreach vertically through that? (that is, rotated 90 degrees from the usual iteration.) 2 - Is there a way to send that "vertical slice" to a function? int count_numbers(){/*...*/} count_numbers(data[0]); //horizontal sum of array[0][0..$-1] WORKS. count_numbers(data[][0]); //vertical sum of array[0..$-1][0] HYPOTHETICAL I'm working on an RLE encoding function and I need both vertical and horizontal strips. It just occurred to me that the problem is essentially the same, if you can "transpose" the matrix. Oh geez, did I just realize what I need? some sort of matrix transpose function? I found this post; https://forum.dlang.org/post/na8ikk$2ojo$1...@digitalmars.com The problem is though, even if I use [][], instead of [5][5] (or try using his conversion function), I can call transposed... but I can't call my function with it! void run_rle3(int [] a){/*...*/} run_rle3(data[0]); //works run_rle3(data.transposed[0]); //nope [see error below] run_rle3(data[0].transposed); //nope (didn't expect this to) run_rle3((data.transposed)[0]); //nope [see error below] Error: function dmap.run_rle3 (int[] a) is not callable using argument types (Transversal!(int[][], cast(TransverseOptions)0))
Re: std.socket tutorials? examples?
On Thursday, 4 October 2018 at 08:52:28 UTC, Andrea Fontana wrote: On Thursday, 4 October 2018 at 08:32:13 UTC, Chris Katko wrote: I've been Google'ing and there's like... nothing out there. One of the top results for "std.socket dlang examples"... is for TANGO. That's how old it is. Socket paradigm is quite standard across languages. Anyway you can find a couple of example here: https://github.com/dlang/dmd/blob/master/samples/listener.d https://github.com/dlang/dmd/blob/master/samples/htmlget.d Andrea I was hoping someone would have a walk-through or something. Those examples are 110 lines each! Usually, with D, there's plenty of useful paradigms/templates/Phobos magic. So if I just port a C/C++/C# socket example over, how am I supposed to know if I'm doing it "the right/proper/best way" in D? That kind of thing.
std.socket tutorials? examples?
I've been Google'ing and there's like... nothing out there. One of the top results for "std.socket dlang examples"... is for TANGO. That's how old it is.
Re: Template/mixin ideas?
On Wednesday, 3 October 2018 at 11:51:01 UTC, Sebastiaan Koppe wrote: On Wednesday, 3 October 2018 at 11:01:53 UTC, Chris Katko wrote: [...] A combination of static introspection with string mixins does the trick: --- enum colors { reset = "\033[0m", red = "\033[31m" } auto GenerateColorFuncs() { string result; static foreach(c; __traits(allMembers, colors)) result ~= "auto "~c~"(string str) { return colors."~c~" ~ str ~ colors.reset; }"; return result; } mixin(GenerateColorFuncs()); void main() { import std.stdio; writeln("bla".red); } --- Although you might want to replace the string concatenation with something more performant if used a lot. The mixin part wouldn't be slowed by strings, right? So the "slowness" is the invokation part which changes strings and forces GC allocations, I guess? What's the alternative to using strings... for strings?
Template/mixin ideas?
I've got this simple task but I'm trying to perfect it as best I can to learn something in the process. I have Linux terminal ASCII codes for coloring terminal output. string red(string) { /* ... */ } "Hello world".red => "\033[31mHello World\033[0m" which translates to "[red]Hello World[reset to normal text]". I have to do some slight trickery so I can chain them. But it all works fine. __The function is the same__ no matter what kind of color, bold, etc attribute I want. The only difference is the tag/prefix string. So I have a table (or enum): enum colors{ reset = "\033[0m", red = "\033[31m", bold = "\033[1m" //... } Absolute perfection would be some way to add a single line to that enum (or table) and magically get a new function. I add "blue" with its prefix code to the enum and immediately I can do: "hello world".blue Add yellow = "\033..." and I can do: "hello world".bold.yellow It's an interesting problem. Right now, I made a generic version that accepts the prefix code string directly called "color()" and red() translates to a call to color with the red string. blue() does the same. And so on. But it's still plenty of boiler plate. I do that so I don't have 80+ functions all a half-page long--which would be a nightmare to verify. It's surely nothing mission critical. But I wonder if I can distill this simple problem down further, I may be able to learn some tricks for later problems. Thanks.
Re: Dynamic Minimum width with Format / writefln
On Wednesday, 3 October 2018 at 00:34:33 UTC, Adam D. Ruppe wrote: On Wednesday, 3 October 2018 at 00:14:03 UTC, Chris Katko wrote: Except it doesn't work and tries to decode col.width-1 into a hexadecimal number and only prints that. ("4D6EF6") That number certainly isn't col.width (unless you have a width of like millions)... It looks more like a pointer. What is the type of col.name? If it is string, this code should work fine. I'm guessing it is a char*... I'm not sure how I made this mistake. But it seems to only show up now if I leave .toStringz() with the writefln. writefln("%-*s<", col.width-1, col.name.toStringz() /* here */); So maybe I've been staring at code too long tonight and simply missed it?
Dynamic Minimum width with Format / writefln
- First, I'm confused. The docs say 's' is "whatever it needs to be". ("he corresponding argument is formatted in a manner consistent with its type:") But what if I specifically want a STRING. Because I only see floats, ints, etc. No forced string types. - Second, This works fine in D: printf("%-*s|", col.width-1, col.name.toStringz()); It's a left-aligned, string with a minimum width from the first argument, col.width. (-1 because I'm throwing a pipe symbol on the end.) Now with writefln: writefln("%-*s|", col.width-1, col.name); Same format specifier, except I don't need a toStringz which is nice. Except it doesn't work and tries to decode col.width-1 into a hexadecimal number and only prints that. ("4D6EF6") I looked through the docs: https://dlang.org/phobos/std_format.html '%' Position Flags Width Separator Precision FormatChar Width: empty Integer '*' But there are then zero examples or explanations of how to use that option. What's going on here?
Re: Sending Tid in a struct
On Wednesday, 23 November 2016 at 08:47:56 UTC, Christian Köstlin wrote: On 03/03/2012 18:35, Timon Gehr wrote: On 03/03/2012 12:09 PM, Nicolas Silva wrote: [...] Yes, this seems to be a bug. Workaround: struct Foo{ string s; Tid id; } void foo(){ Foo foo; receive((Tuple!(string,"s",Tid,"id") bar){foo=Foo(bar.s,bar.id);}); } void main(){ auto id = spawn(); id.send("string",id); ... } I had a similar problem with this an it seems this is still a bug with dmd 2.072. best regards, christian So this appears to still be a bug in 2.078.0-beta.1. Sigh... So the only way to actually use concurrency in D... is to use this hack? Or has it been fixed since January? Is there an official bug report?
Re: Simple parallel foreach and summation/reduction
On Monday, 24 September 2018 at 07:13:24 UTC, Chris Katko wrote: On Monday, 24 September 2018 at 05:59:20 UTC, Chris Katko wrote: [...] Actually, I just realized/remembered that the error occurs inside parallelism itself, and MANY times at that: [...] This JUST occurred to me. When I use an outer taskPool.[a]map, am I NOT supposed to use the taskPool version of reduce?! But instead, the std.algorithm one? Because this is running with both/all cores, and only using 2.7MB of RAM: sum = taskPool.reduce!(test)( map!(monte)(range) //map, not taskPool.map ); If that's the correct case, the docs did NOT make that obvious! FYI, I went from ~5200 samples / mSec, to 7490 samples / mSec. 36% difference for second "real" core. Better than nothing, I guess. I'll have to try it on my main machine with a proper CPU.
Re: Simple parallel foreach and summation/reduction
On Monday, 24 September 2018 at 05:59:20 UTC, Chris Katko wrote: On Saturday, 22 September 2018 at 02:26:41 UTC, Chris Katko wrote: On Saturday, 22 September 2018 at 02:13:58 UTC, Chris Katko wrote: On Friday, 21 September 2018 at 12:15:59 UTC, Ali Çehreli wrote: On 09/21/2018 12:25 AM, Chris Katko wrote: [...] You can use a free-standing function as a workaround, which is included in the following chapter that explains most of std.parallelism: http://ddili.org/ders/d.en/parallelism.html That chapter is missing e.g. the newly-added fold(): https://dlang.org/phobos/std_parallelism.html#.TaskPool.fold Ali Okay... so I've got it running. The problem is, it uses tons of RAM. In fact, proportional to the working set. T test(T)(T x, T y) { return x + y; } double monte(T)(T x) { double v = uniform(-1F, 1F); double u = uniform(-1F, 1F); if(sqrt(v*v + u*u) < 1.0) { return 1; }else{ return 0; } } auto taskpool = new TaskPool(); sum = taskpool.reduce!(test)( taskpool.amap!monte( iota(num) ) ); taskpool.finish(true); 100 becomes ~8MB 1000 becomes 80MB 1, I can't even run because it says "Exception: Memory Allocation failed" Also, when I don't call .finish(true) at the end, it just sits there forever (after running) like one of the threads won't terminate. Requiring a control-C. But the docs and examples don't seem to indicate I should need that... So I looked into it. It's amap that explodes in RAM. Per the docs, amap has "less overhead but more memory usage." While map has more overhead but less memory usage and "avoids the need to keep all results in memory." But, if I make a call to map... it doesn't compile! I get: Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map Simply changing amap to map here: sum = taskPool.reduce!(test) ( taskPool.map!(monte)(range) ); Actually, I just realized/remembered that the error occurs inside parallelism itself, and MANY times at that: /usr/include/dmd/phobos/std/parallelism.d(2590): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2596): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2616): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2616): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2616): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2616): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2616): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2616): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2626): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2626): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2626): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2626): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2626): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2626): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map /usr/include/dmd/phobos/std/parallelism.d(2634): Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map monte.d(64): Error: template instance std.parallelism.TaskPool.reduce!(test).reduce!(Map) error instantiating Though I tried looking up the git version of prallelism.d and the lines don't quite line up: https://github.com/dlang/phobos/blob/master/std/parallelism.d
Re: Simple parallel foreach and summation/reduction
On Saturday, 22 September 2018 at 02:26:41 UTC, Chris Katko wrote: On Saturday, 22 September 2018 at 02:13:58 UTC, Chris Katko wrote: On Friday, 21 September 2018 at 12:15:59 UTC, Ali Çehreli wrote: On 09/21/2018 12:25 AM, Chris Katko wrote: [...] You can use a free-standing function as a workaround, which is included in the following chapter that explains most of std.parallelism: http://ddili.org/ders/d.en/parallelism.html That chapter is missing e.g. the newly-added fold(): https://dlang.org/phobos/std_parallelism.html#.TaskPool.fold Ali Okay... so I've got it running. The problem is, it uses tons of RAM. In fact, proportional to the working set. T test(T)(T x, T y) { return x + y; } double monte(T)(T x) { double v = uniform(-1F, 1F); double u = uniform(-1F, 1F); if(sqrt(v*v + u*u) < 1.0) { return 1; }else{ return 0; } } auto taskpool = new TaskPool(); sum = taskpool.reduce!(test)( taskpool.amap!monte( iota(num) ) ); taskpool.finish(true); 100 becomes ~8MB 1000 becomes 80MB 1, I can't even run because it says "Exception: Memory Allocation failed" Also, when I don't call .finish(true) at the end, it just sits there forever (after running) like one of the threads won't terminate. Requiring a control-C. But the docs and examples don't seem to indicate I should need that... So I looked into it. It's amap that explodes in RAM. Per the docs, amap has "less overhead but more memory usage." While map has more overhead but less memory usage and "avoids the need to keep all results in memory." But, if I make a call to map... it doesn't compile! I get: Error: no [] operator overload for type std.parallelism.TaskPool.map!(monte).map!(Result).map.Map Simply changing amap to map here: sum = taskPool.reduce!(test) ( taskPool.map!(monte)(range) );
Re: Simple parallel foreach and summation/reduction
On Saturday, 22 September 2018 at 02:13:58 UTC, Chris Katko wrote: On Friday, 21 September 2018 at 12:15:59 UTC, Ali Çehreli wrote: On 09/21/2018 12:25 AM, Chris Katko wrote: [...] You can use a free-standing function as a workaround, which is included in the following chapter that explains most of std.parallelism: http://ddili.org/ders/d.en/parallelism.html That chapter is missing e.g. the newly-added fold(): https://dlang.org/phobos/std_parallelism.html#.TaskPool.fold Ali Okay... so I've got it running. The problem is, it uses tons of RAM. In fact, proportional to the working set. T test(T)(T x, T y) { return x + y; } double monte(T)(T x) { double v = uniform(-1F, 1F); double u = uniform(-1F, 1F); if(sqrt(v*v + u*u) < 1.0) { return 1; }else{ return 0; } } auto taskpool = new TaskPool(); sum = taskpool.reduce!(test)( taskpool.amap!monte( iota(num) ) ); taskpool.finish(true); 100 becomes ~8MB 1000 becomes 80MB 1, I can't even run because it says "Exception: Memory Allocation failed" Also, when I don't call .finish(true) at the end, it just sits there forever (after running) like one of the threads won't terminate. Requiring a control-C. But the docs and examples don't seem to indicate I should need that...
Re: Simple parallel foreach and summation/reduction
On Friday, 21 September 2018 at 12:15:59 UTC, Ali Çehreli wrote: On 09/21/2018 12:25 AM, Chris Katko wrote: On Thursday, 20 September 2018 at 05:51:17 UTC, Neia Neutuladh wrote: On Thursday, 20 September 2018 at 05:34:42 UTC, Chris Katko wrote: All I want to do is loop from 0 to [constant] with a for or foreach, and have it split up across however many cores I have. You're looking at std.parallelism.TaskPool, especially the amap and reduce functions. Should do pretty much exactly what you're asking. auto taskpool = new TaskPool(); taskpool.reduce!((a, b) => a + b)(iota(1_000_000_000_000L)); I get "Error: template instance `reduce!((a, b) => a + b)` cannot use local __lambda1 as parameter to non-global template reduce(functions...)" when trying to compile that using the online D editor with DMD and LDC. Any ideas? You can use a free-standing function as a workaround, which is included in the following chapter that explains most of std.parallelism: http://ddili.org/ders/d.en/parallelism.html That chapter is missing e.g. the newly-added fold(): https://dlang.org/phobos/std_parallelism.html#.TaskPool.fold Ali Okay... so I've got it running. The problem is, it uses tons of RAM. In fact, proportional to the working set. T test(T)(T x, T y) { return x + y; } double monte(T)(T x) { double v = uniform(-1F, 1F); double u = uniform(-1F, 1F); if(sqrt(v*v + u*u) < 1.0) { return 1; }else{ return 0; } } auto taskpool = new TaskPool(); sum = taskpool.reduce!(test)( taskpool.amap!monte( iota(num) ) ); taskpool.finish(true); 100 becomes ~8MB 1000 becomes 80MB 1, I can't even run because it says "Exception: Memory Allocation failed"
Re: Simple parallel foreach and summation/reduction
On Thursday, 20 September 2018 at 05:51:17 UTC, Neia Neutuladh wrote: On Thursday, 20 September 2018 at 05:34:42 UTC, Chris Katko wrote: All I want to do is loop from 0 to [constant] with a for or foreach, and have it split up across however many cores I have. You're looking at std.parallelism.TaskPool, especially the amap and reduce functions. Should do pretty much exactly what you're asking. auto taskpool = new TaskPool(); taskpool.reduce!((a, b) => a + b)(iota(1_000_000_000_000L)); I get "Error: template instance `reduce!((a, b) => a + b)` cannot use local __lambda1 as parameter to non-global template reduce(functions...)" when trying to compile that using the online D editor with DMD and LDC. Any ideas?
Simple parallel foreach and summation/reduction
All I want to do is loop from 0 to [constant] with a for or foreach, and have it split up across however many cores I have. ulong sum; foreach(i; [0 to 1 trillion]) { //flip some dice using float die_value = uniform(0F,12F); if(die_value > [constant]) sum++; } writeln("The sum is %d", sum); However, there are two caveats.: - One: I can't throw a range of values into an array and foreach on that like many examples use. Because 1 trillion (counting from zero) might be a little big for an array. (I'm using 1 trillion to illustrate a specific bottleneck / problem form.) - I want to merge the results at the end. Which means I either need to use mutexes (BAD. NO. BOO. HISS.) or each "thread" would need to know if it's separate, and then store their sums in, say, a thread[#].sum variable and then once all were completed, add those sums together. I know this is an incredibly simple conceptual problem to solve. So I feel like I'm missing some huge, obvious, answer for doing it elegantly in D. And this just occurred to me, if I had a trillion foreach, will that make 1 trillion threads? What I want is, IIRC, what OpenMP does. It divides up your range (blocks of sequential numbers) by the number of threads. So domain of [1 to 1000] with ten threads would become workloads on the indexes of [1-100], [101-200], [201-300], and so on. for each CPU. They each get a 100 element chunk. So I guess foreach won't work here for that, will it? Hmmm... > But again, conceptually this is simple: I have, say, 1 trillion sequential numbers. I want to assign a "block" (or "range") to each CPU core. And since their math does not actually interfer with each other, I can simply sum each core's results at the end. Thanks, --Chris
Re: Load entire file, as a char array.
On Monday, 3 September 2018 at 07:38:51 UTC, Chris Katko wrote: On Monday, 3 September 2018 at 06:28:38 UTC, bauss wrote: On Monday, 3 September 2018 at 06:25:23 UTC, bauss wrote: On Monday, 3 September 2018 at 03:19:39 UTC, Neia Neutuladh wrote: On Monday, 3 September 2018 at 03:04:57 UTC, Chris Katko wrote: This should be simple? All I want to do is load an entire file, and access individual bytes. The entire thing. I don't want to have know the file size before hand, or "guess" and have a "maximum size" buffer. So far, all google searches for "dlang binary file read" end up not working for me. Thank you. http://dpldocs.info/experimental-docs/std.file.read.1.html import std.file : read; auto bytes = read("filename"); This gives you a void[], which you can cast to ubyte[] or char[] or whatever you need. Or he could do readText() which returns a string, which in turn will give a proper char array when casted. Actually ignore the casting thing, looking at readText it takes a template parameter. So: char[] a = readText!(char[])("filename"); Thanks, that works! But... I'm so confused by D's fifty different string types. I can run .strip() on a char[]. But I can't run .replace('\n','?') ? So then I convert char[] to a temporary string and run replace on that. but then writefln("%s") doesn't accept strings! Only char[]. char []t = cast(char[])(c[i-15 .. i+1]).strip(); string s = text(t); //s.replace('\n','?') writefln(" - [%s]", s); // fail main.d(89): Error: template std.array.replace cannot deduce function from argument types !()(char[], char, char), candidates are: /usr/include/dmd/phobos/std/array.d(2122): std.array.replace(E, R1, R2)(E[] subject, R1 from, R2 to) if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2 && (hasLength!R2 || isSomeString!R2)) /usr/include/dmd/phobos/std/array.d(2255): std.array.replace(T, Range)(T[] subject, size_t from, size_t to, Range stuff) if (isInputRange!Range && (is(ElementType!Range : T) || isSomeString!(T[]) && is(ElementType!Range : dchar))) What's going on here? WAIT! This is my fault (not that I was saying it was "D's" fault, just that I was confused). it's not replace '' ''. It's replace "" "". For some reason, I must have been thinking it was per-character (which is what I'm doing) so I should be using single quotes. So I CAN run .replace("","") on a char[], just as I can a string. And THANK GOODNESS because I thought one of the major advantages of D was being relatively orthogonal/type agnostic and if I was going to have to remember "X() runs only on Y" for 3+ different string types that would be a nightmare!
Re: Load entire file, as a char array.
On Monday, 3 September 2018 at 06:28:38 UTC, bauss wrote: On Monday, 3 September 2018 at 06:25:23 UTC, bauss wrote: On Monday, 3 September 2018 at 03:19:39 UTC, Neia Neutuladh wrote: On Monday, 3 September 2018 at 03:04:57 UTC, Chris Katko wrote: This should be simple? All I want to do is load an entire file, and access individual bytes. The entire thing. I don't want to have know the file size before hand, or "guess" and have a "maximum size" buffer. So far, all google searches for "dlang binary file read" end up not working for me. Thank you. http://dpldocs.info/experimental-docs/std.file.read.1.html import std.file : read; auto bytes = read("filename"); This gives you a void[], which you can cast to ubyte[] or char[] or whatever you need. Or he could do readText() which returns a string, which in turn will give a proper char array when casted. Actually ignore the casting thing, looking at readText it takes a template parameter. So: char[] a = readText!(char[])("filename"); Thanks, that works! But... I'm so confused by D's fifty different string types. I can run .strip() on a char[]. But I can't run .replace('\n','?') ? So then I convert char[] to a temporary string and run replace on that. but then writefln("%s") doesn't accept strings! Only char[]. char []t = cast(char[])(c[i-15 .. i+1]).strip(); string s = text(t); //s.replace('\n','?') writefln(" - [%s]", s); // fail main.d(89): Error: template std.array.replace cannot deduce function from argument types !()(char[], char, char), candidates are: /usr/include/dmd/phobos/std/array.d(2122): std.array.replace(E, R1, R2)(E[] subject, R1 from, R2 to) if (isDynamicArray!(E[]) && isForwardRange!R1 && isForwardRange!R2 && (hasLength!R2 || isSomeString!R2)) /usr/include/dmd/phobos/std/array.d(2255): std.array.replace(T, Range)(T[] subject, size_t from, size_t to, Range stuff) if (isInputRange!Range && (is(ElementType!Range : T) || isSomeString!(T[]) && is(ElementType!Range : dchar))) What's going on here?
Re: Load entire file, as a char array.
On Monday, 3 September 2018 at 03:19:39 UTC, Neia Neutuladh wrote: On Monday, 3 September 2018 at 03:04:57 UTC, Chris Katko wrote: This should be simple? All I want to do is load an entire file, and access individual bytes. The entire thing. I don't want to have know the file size before hand, or "guess" and have a "maximum size" buffer. So far, all google searches for "dlang binary file read" end up not working for me. Thank you. http://dpldocs.info/experimental-docs/std.file.read.1.html import std.file : read; auto bytes = read("filename"); This gives you a void[], which you can cast to ubyte[] or char[] or whatever you need. That works great! I thought all file i/o had to through the File class.
Load entire file, as a char array.
This should be simple? All I want to do is load an entire file, and access individual bytes. The entire thing. I don't want to have know the file size before hand, or "guess" and have a "maximum size" buffer. So far, all google searches for "dlang binary file read" end up not working for me. Thank you.
Re: Doxygen newbie
Oh goodness. I thought D was using Doxygen! Thanks.
Doxygen newbie
I'm a complete doxygen newbie. But my first thought when writing comments is... why not use Markdown? (Which has become almost universal online these days.) So I google it and Moxygen comes up. Which seems pretty good. https://sourcey.com/generating-beautiful-markdown-documentation-with-moxygen/ So my question is, can you use Markdown with normal Doxygen? Is Moxygen needed? And if so, would I run into any complications using D instead of C/C++ with Doxygen and Moxygen? Would there be any strange demangling issues or anything like that? Thanks
Re: Rotate array in writefln?
On Wednesday, 18 April 2018 at 07:15:47 UTC, Simen Kjærås wrote: On Wednesday, 18 April 2018 at 06:54:29 UTC, Chris Katko wrote: I need to rotate an array by 90 degrees, or have writefln figure that out. I need, say: 0 4 5 6 0 0 0 0 0 0 0 0 0 0 0 0 But it's outputting: 0 0 0 0 4 0 0 0 5 0 0 0 6 0 0 0 int [4][4] data; file.writeln(format("%(%-(%d %)\n%)", data)); Generally, the solution would be std.range.transposed. However, since you're using a int[4][4], that's not a range-of-ranges, and transposed don't work out of the box. This helper function should help: T[][] ror(T, size_t N1, size_t N2)(ref T[N1][N2] arr) { T[][] result = new T[][N2]; foreach (i, e; arr) { result[i] = e.dup; } return result; } unittest { import std.stdio; import std.range; int [4][4] data; data[2][3] = 4; writefln("%(%-(%d %)\n%)", data); writefln("%(%-(%d %)\n%)", data.ror.transposed); } -- Simen That makes sense why transpose wouldn't work for my arrays! So you're saying if I used [][] (dynamic array) that's a range of ranges, and it would work? Why is it you have to rework your templates for static vs dynamic ranges? Thanks!