Re: Is there any generic iteration function that stops at first match?
On Friday, 5 March 2021 at 05:32:27 UTC, Jack wrote: On Friday, 5 March 2021 at 02:43:36 UTC, H. S. Teoh wrote: On Fri, Mar 05, 2021 at 02:13:39AM +, Jack via Digitalmars-d-learn wrote: something like filter[1] but that stops at first match? are there any native functions for this in D or I have to write one? just making sure to not reinvent the wheel [...] Why not just .front? E.g.: int[] data = [ 1,2,3,4,5 ]; auto r = data.filter!(v => v % 2 == 0); assert(r.front == 2); T it loops over the entire array then returns, I'd like to stop as soon as the predicate return true void main() { import std.stdio, std.algorithm, std.range; int[] data = iota(5).map!"a+1".array; auto r = data.filter!(function (v) { writeln(v); return v % 2 == 0; }); assert(r.front == 2); } output: 1 2 'r' is an iterator. To force it to loop over the entire array that would need a .array like I'm using for 'data'.
Re: vibe.d / experience / feedback
On Thursday, 1 October 2020 at 06:32:23 UTC, Robert M. Münch wrote: 5. One can't access the raw HTTP request body, things must be go through Vibe's JSON parser. To get access to the raw body, a lot of workarounds are necessary. given an HTTPServerRequest req, req.bodyReader.readAll for binary data and .readAllUTF8 for text.
Re: preset counter variable in a for loop
On Friday, 28 February 2020 at 12:44:52 UTC, Namal wrote: Hello, I don't understand why this simple code causes a compiler error.. import std.stdio; void main(){ int b = 0; for (b; b<3; b++){ writeln(b); } } $Error: b has no effect Well, that's the error. b has no effect, so there's no need for it, and it's likely written in error. It has no effect in C++ either, and you may get a warning: example.cc: In function 'int main()': example.cc:7:8: warning: statement has no effect [-Wunused-value] for (b; b<3; b++){
Re: Call method if declared only
On Friday, 28 February 2020 at 08:08:59 UTC, Виталий Фадеев wrote: Searching for beauty readable code... The pattern throughout Phobos is static tests, like isInputRange!R So something like this: import std.stdio; import std.traits; template canOnKey(T) { static if (__traits(hasMember, T, "onKey")) enum canOnKey = isCallable!(__traits(getMember, T, "onKey")); else enum canOnKey = false; } struct A { void onKey() { writeln("called A"); } } struct B { } struct C { bool onKey = false; } void maybeKey(T)(T o) if (canOnKey!T) { o.onKey(); } void maybeKey(T)(T o) if (!canOnKey!T) { } void main() { auto a = A(), b = B(), c = C(); maybeKey(a); maybeKey(b); maybeKey(c); } output: called A (and no other output) Of course in this exact instance it would be simpler to write void maybeKey(T)(T o) { static if (canOnKey!T) o.onKey(); } And rather than lots of specific hasThisExactMethod!T tests, it might be nice if in your actual program there's a 'class' of grouped properties that you can test for all at once, again like isInputRange!T and friends.
Re: Question about the $ sign in arrays and strings
On Wednesday, 19 February 2020 at 07:49:36 UTC, Namal wrote: oooh... I used str = std.readln(); to get my string and there must have been some other sign, line break or whitespace or something at the end :( Now I understand it, thx That makes sense. readln includes the newline: $ echo hello | rdmd --eval 'readln.map!(std.uni.isWhite).writeln' [false, false, false, false, false, true] You can use std.string.chomp to drop it: $ echo hello | rdmd --eval 'readln.chomp.map!(std.uni.isWhite).writeln' [false, false, false, false, false]
Re: Question about the $ sign in arrays and strings
On Wednesday, 19 February 2020 at 07:04:48 UTC, Namal wrote: Hello, I wanted to remove the lastchar in a string and figured that you can do that wit str = str[0..$-2]; but why is str = str[0..$] and str=str[0..$-1] the same ? Why do you think that they are the same? $ rdmd --eval 'auto str = "hello"; writeln(str = str[0..$]); writeln(str = str[0..$-1])' hello hell
Re: How to iterate over range two items at a time
On Monday, 17 February 2020 at 05:04:02 UTC, Adnan wrote: What is the equivalent of Rust's chunks_exact()[1] method in D? I want to iterate over a spitted string two chunks at a time. [1] https://doc.rust-lang.org/beta/std/primitive.slice.html#method.chunks_exact And, after actually reading the Rust doc, I see that you want to iterate over a string two chars at a time while discarding any remaining 1-length chunk. There isn't an equivalent of that. A quick one is auto chunks_exact(R)(R r, size_t n) { return r.take(r.length - r.length%n).chunks(n); } but to get the exact same behavior you'll want to return a range type that stores the final chunk.
Re: How to iterate over range two items at a time
On Monday, 17 February 2020 at 05:04:02 UTC, Adnan wrote: What is the equivalent of Rust's chunks_exact()[1] method in D? I want to iterate over a spitted string two chunks at a time. [1] https://doc.rust-lang.org/beta/std/primitive.slice.html#method.chunks_exact $ rdmd --eval '"hello world".chunks(2).each!writeln' he ll o wo rl d $ rdmd --eval '"hello world".chunks(2).map!"a.array.length".each!writeln' 2 2 2 2 2 1 Note the .array; each chunk is a range type. $ rdmd --eval 'typeid("hello world".chunks(2).take(1)).writeln' std.range.Take!(Chunks!string).Take
Re: How the hell to split multiple delims?
On Saturday, 15 February 2020 at 11:32:42 UTC, AlphaPurned wrote: I've tried 10 different ways with split and splitter, I've used all the stuff that people have said online but nothing works. I always get a template mismatch error. Why is something so easy to do so hard in D? auto toks = std.regex.split(l, Regex("s")); auto toks = std.regex.splitter(l, Regex("s")); auto toks = std.regex.splitter(l, ctRegex!r"\."); Why do you think this doesn't work? I'm not just asking this to be rude. Your problem is likely in the rest of your code. $ rdmd --eval 'split("the quick,brown:fox",regex("[ ,:]")).writeln' ["the", "quick", "brown", "fox"] $ rdmd --eval 'typeid(split("the quick,brown:fox",regex("[ ,:]"))).writeln' immutable(char)[][] $ rdmd --eval 'splitter("the quick,brown:fox",regex("[ ,:]")).writeln' ["the", "quick", "brown", "fox"] $ rdmd --eval 'typeid(splitter("the quick,brown:fox",regex("[ ,:]"))).writeln' std.regex.Splitter!(cast(Flag)false, string, Regex!char).Splitter That final value is a range type. Consider the guides at the top of https://dlang.org/phobos/std_range.html Ranges take a while to get comfortable with.
Re: Filling an associated array of associated arrays
On Tuesday, 14 January 2020 at 23:23:51 UTC, Jamie wrote: I'm trying to initialise an associated array of associated arrays with values, taking the same approach I would for an associated array: This works: import std.stdio; void main() { string[string][string] table = ([ "info" : [ "equation" : "H2 + I2 <=> 2HI", "type" : "elementary", ], "frc" : [ "A" : "1.2e9", "n" : "1.2e9", "C" : "1.2e9", ], ]); writeln(table); } c.f. https://issues.dlang.org/show_bug.cgi?id=17607 I found that by searching the forums for your error.
Re: Reading a file of words line by line
On Tuesday, 14 January 2020 at 16:39:16 UTC, mark wrote: I can't help feeling that the foreach loop's block is rather more verbose than it could be? WordSet words; auto rx = ctRegex!(r"^[a-z]+", "i"); auto file = File(filename); foreach (line; file.byLine) { auto match = matchFirst(line, rx); if (!match.empty()) { auto word = match.hit().to!string; // I hope this assumes UTF-8? if (word.length == wordsize) { words[word.toUpper] = 0; } } } return words; } One thing I picked up during Advent of Code last year was std.file.slurp, which was great for reading 90% of the input files from that contest. With that, I'd do this more like int[string] words; slurp!string("input.txt", "%s").each!(w => words[w] = 0); Where "%s" is what slurp() expects to find on each line, and 'string' is the type it returns from that. With just a list of words this isn't very interesting. Some of my uses from the contest are: auto input = slurp!(int, int, int)(args[1], "z=%d>") .map!(p => Moon([p[0], p[1], p[2]])).array; Tuple!(string, string)[] input = slurp!(string, string)("input.txt", "%s)%s"); Of course if you want to validate the input as you're reading it, you still have to do extra work, but it could be in a .filter!
Re: Finding position of a value in an array
On Monday, 30 December 2019 at 19:46:50 UTC, Ron Tarrant wrote: Thanks, mipri. Got it sorted. Here's a working proof... ``` import std.stdio; import std.algorithm; import std.conv; void main(string[] args) { MyObject[] objectArray; MyObject newObject; MyObject findPointer; long index; int lastObjectID = 7; int foundObjectIndex; for(int i; i < 12; i++) { lastObjectID++; newObject = new MyObject(lastObjectID); objectArray ~= newObject; if(i is 5) { findPointer = newObject; } } for(int i; i < objectArray.length; i++) { writeln("object: ", cast(MyObject*)objectArray[i], ", ID: ", objectArray[i].objectID); } index = objectArray.countUntil(findPointer); writeln("findPointer: ", findPointer, ", at address: ", cast(MyObject*)findPointer, " is a MyObject pointer in the objectArray with an index of ", index, ", address: ", cast(MyObject*)objectArray[index], ", ID: ", objectArray[index].objectID); } // main() class MyObject { int objectID; this(int ordinal) { objectID = ordinal; } // this() } // class MyObject ``` Compare: import std.stdio; import std.algorithm; import std.conv; void main(string[] args) { MyObject[] objectArray; MyObject newObject; MyObject findPointer; long index; int foundObjectIndex; for(int i; i < 12; i++) { newObject = new MyObject(); objectArray ~= newObject; if(i is 5) { findPointer = newObject; } } for(int i; i < objectArray.length; i++) { writeln("object: ", cast(MyObject*)objectArray[i]); } index = objectArray.countUntil(findPointer); writeln("findPointer: ", findPointer, ", at address: ", cast(MyObject*)findPointer, " is a MyObject pointer in the objectArray with an index of ", index, ", address: ", cast(MyObject*)objectArray[index]); } // main() class MyObject {} With output: object: 7F2DC37C3000 object: 7F2DC37C3020 object: 7F2DC37C3030 object: 7F2DC37C3040 object: 7F2DC37C3050 object: 7F2DC37C3060 object: 7F2DC37C3070 object: 7F2DC37C3080 object: 7F2DC37C3090 object: 7F2DC37C30A0 object: 7F2DC37C30B0 object: 7F2DC37C30C0 findPointer: x297.MyObject, at address: 7F2DC37C3060 is a MyObject pointer in the objectArray with an index of 5, address: 7F2DC37C3060
Re: Finding position of a value in an array
On Monday, 30 December 2019 at 19:08:27 UTC, Ron Tarrant wrote: On Monday, 30 December 2019 at 17:12:26 UTC, MoonlightSentinel wrote: D disallows implicit conversion from integers to pointers and hence they cannot be compared. You would need to explicitly cast your ulong to an appropriate pointer type I'm not trying to convert, just wade through an array of pointers to find a specific pointer using searchUntil(). I mean, it's not a big deal if I can't do it. You can definitely do it: $ rdmd --eval 'int a, b, c; [, , ].countUntil().writeln' 2 But you need to have an array of pointers.
Re: Concatenation/joining strings together in a more readable way
On Monday, 30 December 2019 at 10:23:14 UTC, Marcone wrote: On Monday, 30 December 2019 at 09:41:55 UTC, mipri wrote: This leaks too much. writeln("Helo {} {}".format("xx", "name")); // Helo xx name writeln("Helo {} {}".format("{}", "name")); // Helo name {} This function replace {} for arguments received. You just need don't send {} as arguments. I tested native function format() in Python: print("Helo {} {}".format("{}", "name")) # Helo {} name Nothing wrong, working same way. It doesn't work the same way. These are not the same: Helo name {} Helo {} name Python's implementation doesn't get confused if your format() arguments include a {}.
Re: Finding position of a value in an array
On Monday, 30 December 2019 at 14:30:12 UTC, Ron Tarrant wrote: On Sunday, 29 December 2019 at 09:44:18 UTC, MoonlightSentinel wrote: int i = a.countUntil(55); I was trying to do this with an array of pointers, but I get an error (which suggests to me that I don't know what data type a pointer is): find_in_array_object.d(25): Error: cannot cast expression newObject of type find_in_array_object.MyObject to ulong What's your code? 'find_in_array_object.MyObject' doesn't look like a pointer.
Re: Concatenation/joining strings together in a more readable way
On Monday, 30 December 2019 at 06:47:37 UTC, Marcone wrote: Use Python format() style: import std; import std: Format = format; // format() string format(T...)(T text){ string texto = text[0]; foreach(count, i; text[1..$]){ texto = texto.replaceFirst("{}", to!string(i)); texto = texto.replace("{%s}".Format(to!string(count)), to!string(i)); } return texto; } This leaks too much. writeln("Helo {} {}".format("xx", "name")); // Helo xx name writeln("Helo {} {}".format("{}", "name")); // Helo name {}
Re: Finding position of a value in an array
On Sunday, 29 December 2019 at 08:26:58 UTC, Daren Scot Wilson wrote: Reading documentation... Array, Algorithms, ... maybe I've been up too late... how does one obtain the index of, say, 55 in an array like this int[] a = [77,66,55,44]; I want to do something like: int i = a.find_value_returning_its_index(55); assert(i==2) I'm sure it's obvious but I'm not seeing it right now. int i = a.countUntil!(v => v == 55); assert(i == 2); It might not be an obvious application of countUntil, but it's listed at https://dlang.org/phobos/std_algorithm_searching.html
Re: How create a function that receive a function and run it in another threading?
On Friday, 27 December 2019 at 06:08:16 UTC, Marcone wrote: import std; import core.thread; auto threading(lazy void fun){ return task!fun().executeInNewThread(); } void main(){ threading(writeln("Hello World!")); } I want to create a function threading() to run some function in other threading, but I get this error bellow. How can I get success? Error: static function Programa.threading.Task!(fun).Task.impl cannot access frame of function Programa.threading Error: template instance `Programa.threading.Task!(fun)` error instantiating This works: import std; import core.thread; auto threading(void function() fun){ return task(fun).executeInNewThread(); } void main(){ writeln("Main: ", thisTid); threading({ writeln("Hello, ", thisTid); }); }
Re: Concatenation/joining strings together in a more readable way
On Wednesday, 25 December 2019 at 12:39:08 UTC, BoQsc wrote: Are there any other ways to join two strings without Tilde ~ character? I can't seems to find anything about Tilde character concatenation easily, nor the alternatives to it. Can someone share some knowledge on this or at least point out useful links/resources? Huh? For clarity I'm going to respond to some potential rewrites of your question. I don't think "foo" ~ "bar" is very readable. Can I use a different syntax? No. That's the syntax. Even if you customize it in your own code, by overloading addition or the like, you'll still come across it in other people's code. So I can only recommend that you find some way to make it readable for you. Maybe use a different or larger font? Maybe just get more familiar with it? I don't think the syntax is likely to change. Where can I find documentation for the ~ operator? It's under 'expressions' in the spec: https://dlang.org/spec/expression.html#cat_expressions Is ~ the best way to join strings together? Can I use something else? You can use it to join arrays in general, including strings. Depending on your use case you might prefer joiner() https://dlang.org/phobos/std_algorithm_iteration.html#.joiner in usage like assert(["many", "strings"].joiner("").array == "manystrings"); Or Appender, for many mutating appends to the same array: https://dlang.org/phobos/std_array.html#Appender
Re: What would it take to bring preinstalled D language compiler in the major Linux Distributions?
On Monday, 23 December 2019 at 13:34:55 UTC, BoQsc wrote: I would love to see D language available out of box in major Linux distributions and use without much care of installation. Anyone have a though about it? Was there any serious efforts to bring D language to Major distributions? What do you consider to be a major distribution? Fedora has all three compilers in default repositories. The install script at https://dlang.org/download.html has a dated version of gdc but is otherwise fairly painless.
Re: range code doesn't work for multi-array
On Tuesday, 17 December 2019 at 07:40:28 UTC, AlphaPurned wrote: if arr is a single array the follow code works(removing [i]) but if it is a double array it fails. arr as type double[A][B]. arr[i] has type double[A]. v ~= arr[i].map!(a=>to!string(a)~",").join; with `Range = double[21]` must satisfy the following constraint: ` isInputRange!(Unqual!Range)` The problem isn't that it's a multi-array but that it's a fixed-size array. As the error suggests: it complains about a double[21], and not about a double[][] Fixed size arrays you need to slice to make them valid input ranges. (std.container.array is the same.) At a terminal: $ rdmd --eval 'int[3] x; x.map!"a+1".writeln' ... with Range = int[3] whose parameters have the following constraints: > isInputRange!(Unqual!Range) Tip: not satisfied constraints are marked with > $ rdmd --eval 'int[3] x; x[].map!"a+1".writeln' [1, 1, 1] Note the [] in x[].map
Re: D's equivalent List Comprehension
On Friday, 13 December 2019 at 15:20:02 UTC, Jesse Phillips wrote: I had mentioned my take on list comprehension here: https://forum.dlang.org/post/qslt0q$2dnb$1...@digitalmars.com#post-ycbohbqaygrgmidyhjma:40forum.dlang.org However someone put together a more comprehensive tutorial of its power. So I took the opportunity to demonstrate the parallel in D. https://dev.to/jessekphillips/list-comprehension-in-d-4hpi D is like writing English. Wait I thought that was supposed to be Python, maybe I am thinking ruby. It might help your blog posts to use drepl in your examples: https://code.dlang.org/packages/drepl A session: $ dub -q run drepl Welcome to D REPL. D> import std; std D> iota(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] D> [2,45,21,45] [2, 45, 21, 45] D> [2,45,21,45].enumerate.assocArray [0:2, 3:45, 2:21, 1:45] D> iota(10).filter!(i => i % 2 == 0) [0, 2, 4, 6, 8] D> Lines without a semicolon are expressions, whose values are printed automatically. Lines with semicolons can import stuff, declare variables, define new functions, etc. Serious current limitations are: it's not aware of dub and can't import dub packages, and it can't parse dstyle braces.
Re: How add "version.txt" Version File by Command Line or by resources.res using dmd.exe
On Sunday, 8 December 2019 at 20:50:05 UTC, Marcone wrote: I want to add version to my program. I have configurated my version file "version.txt", but I dont know how link this file to my program. If Need spec file, please send the exemple code of spec. Or is is possible add version file by dmd command line or resources. Thank you. I'm not sure I know what you're asking, but maybe this is the answer. In version.txt: 0.1.0 - a version example In version.d: import std.string : chomp; immutable Version = import("version.txt").chomp; void main() { import std.stdio : writeln; writeln("Version: ", Version); } To compile and run with both files in the current directory: dmd -J. -run version With output: Version: 0.1.0 - a version example The corresponding dub setting is probably stringImportPaths
Re: Are there any DUB packages for displaying an ascii table?
On Sunday, 8 December 2019 at 08:01:32 UTC, Soulsbane wrote: Been playing with Golang lately and it has quite a few modules for terminal tables. For example this one: github.com/brettski/go-termtables. Is there a D equivalent package? Can't seem to find any via search(which by the ways seems to give bad results or I just can't find the right word to search with). Thanks! This exists and was updated as recently as the first of December: https://code.dlang.org/packages/asciitable I don't see any other dub packages that look related.
Re: Populating nested AAs; "This wouldn't be so verbose in Ada 2020"
On Sunday, 8 December 2019 at 06:42:22 UTC, Paul Backus wrote: You can use the `require` function [1] for this: with (userHistory.require(host).require(user)) { if (isOk) ++ok; // renamed to avoid shadowing else ++evil; } Many "methods" for built-in AAs are located in the `object` module. It makes them a bit tricky to find in the documentation, if you don't already know they're there. https://dlang.org/phobos/object.html#.require Thanks! I wasn't aware of the 'object' doc. Looks like the language documentation does mention require() in "Inserting if not present", but combining it with 'with' is a neat trick.
Populating nested AAs; "This wouldn't be so verbose in Ada 2020"
Hello, I've got this code: struct UserStats { int ok, evil; } // module-level variable UserStats[string][string] userHistory; and this code that populates it: // loop over DB query if (host !in userHistory) userHistory[host] = typeof(userHistory[host]).init; if (user !in userHistory[host]) userHistory[host][user] = typeof(userHistory[host][user]).init; if (ok) ++userHistory[host][user].ok; else ++userHistory[host][user].evil; The joke of the thread title is that in pseudo-Ada2020, those assignments would look like User_History (host) = typeof (@).init; User_History (host) (user) = typeof (@).init; as @ is a shortcut for the left hand side of an assignment. It's what Ada has instead of += and friends. Of course, I don't propose that @ be added to D; I just want to know if there's a good idiom for new assignments to nested AAs like this. A nice alternative for my specific use is struct UserStats { static int[Tuple!(string, string)] ok, evil; } and // loop over DB query if (ok) ++UserStats.ok[tuple(host, user)]; else ++UserStats.evil[tuple(host, user)]; But of course this would be less convenient if f.e. I wanted to pattern my data structures after a JSON production result.
Re: Using map result type
On Sunday, 8 December 2019 at 01:10:21 UTC, AA wrote: I'd like to accept the return type of map. From some previous questions that I should accept a template? In general this is what you want to do with any kind of range code, because you're not working with definite types, but with types that have certain properties. And an advantage of this is that you can decide to do more or less efficient things at compile time based on additional properties of the types you're working with. Just open up phobos and look for 'static if': https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L3858 So if you you give minPos an array, it'll just foreach() over the array and return a slice. In which case minPos is exactly as efficient as the code you would've written by hand instead of using minPos, because it expands to that same code. And if you give minPos something else, it'll still work. So for something like: ``` void mapAccepter(Range)(Range r) { import std.array : array; import std.stdio : writeln; auto collected = r.array; writeln(collected); } void main() { import std.algorithm.iteration : map; int[] nums = [1, 2, 3]; auto evenness = map!(n => n % 2 == 0)(nums); mapAccepter(evenness); } ``` 1) Is there any way I can make `mapAccepter` not a templated function? Not really. Even if you try to use typeof() to get the (internal) type that std.alogorithm.map returns, you'll run into errors like Error: function x253.mapAccepter(MapResult!(__lambda5, int[]) r) is not callable using argument types (MapResult!(__lambda1, int[])) when you try to use it. 2) Is there any way if I need to make `mapAccepter` templated to constrain Range to be a range of booleans. Certainly. Static reflection's what this kind of generic code is all about. See all the constraints in the std.algorithm pages in the library documentation? Just look at this one, randomly picked: https://dlang.org/phobos/std_algorithm_searching.html#.endsWith if (isBidirectionalRange!Range && (Needles.length > 1) && is(typeof(.endsWith!pred(doesThisEnd, withOneOfThese[0])) : bool) && is(typeof(.endsWith!pred(doesThisEnd, withOneOfThese[1..$])) : uint)); So for your code: void mapAccepter(Range)(Range r) if (is(ElementType!Range == bool)) { import std.array : array; import std.stdio : writeln; auto collected = r.array; writeln(collected); } Or if you do this often, maybe something like this would do: enum RangeOfBools(T) = is(ElementType!T == bool) && isInputRange!T; void mapAccepter(Range)(Range r) if (RangeOfBools!Range) { import std.array : array; import std.stdio : writeln; auto collected = r.array; writeln(collected); }
Re: How to invert bool false/true in alias compose?
On Saturday, 7 December 2019 at 04:00:53 UTC, Marcone wrote: import std; alias cmd = compose!(to!bool, wait, spawnShell, to!string); void main(){ writeln(cmd("where notepad.exe")); } Result: C:\Windows\System32\notepad.exe C:\Windows\notepad.exe false The result show "false" because good spawnshell command return 0 and 0 to bool is false. But I want to invert false to true to get true or false if command success. These all work: alias cmd = compose!(unaryFun!"!a", to!bool, wait, spawnShell, to!string); alias cmd = compose!("!a", to!bool, wait, spawnShell, to!string); alias cmd = compose!(b => !b, to!bool, wait, spawnShell, to!string);
Re: Unexpectedly nice case of auto return type
On Friday, 6 December 2019 at 23:25:30 UTC, Johannes Loher wrote: On Tuesday, 3 December 2019 at 10:06:22 UTC, Mike Parker wrote: On Tuesday, 3 December 2019 at 10:03:22 UTC, Basile B. wrote: That's interesting details of D developement. Since you reply to the first message I think you have not followed but in the last reply I told that maybe we should be able to name the type of null. I think this relates to TBottom too a bit. https://github.com/dlang/DIPs/blob/40352337053998885fbd0fe2718c300a322d3996/DIPs/DIP1NNN-DK.md This is everything I wished for. It basically exactly resembles the results of the lengthy discussion H. S. Theo and I had in the review thread for Walter‘s original bottom type suggestion. And it even covers a few additional details we had not thought about. I can’t wait for this DIP to go into review. Thanks a lot to the DIP author. You have my biggest respect for writing a fleshed out proposal of this! nice. Kotlin has this as well, with Unit as void and Nothing as noreturn. So for example this compiles without complaint: fun infinite(f: () -> Unit) { while (true) { f() } } fun main() { infinite { println(".") } println("goodbye") } Where 'infinite' has an implcit Unit return type, but this warns that the "goodbye" will never happen: fun infinite(f: () -> Unit): Nothing { while (true) { f() } } fun main() { infinite { println(".") } println("goodbye") } This might be more important for resources that never get closed, or secrets are never scrubbed from memory, due to someone putting those tasks after a function like 'infinite' without noticing. ... noreturn local variables are pretty gross, though.
Re: Unexpectedly nice case of auto return type
On Tuesday, 3 December 2019 at 10:13:30 UTC, mipri wrote: Speaking of nice stuff and aliases, suppose you want to return a nice tuple with named elements? Option 1: auto auto option1() { return tuple!(int, "apples", int, "oranges")(1, 2); } Option 2: redundancy Tuple!(int, "apples", int, "oranges") option2() { return tuple!(int, "apples", int, "oranges")(1, 2); } Option 3: an alias alias BadMath = Tuple!(int, "apples", int, "oranges"); BadMath option3() { return BadMath(1, 2); } Option 4: typeof(return) Tuple!(int, "apples", int, "oranges") option4() { return typeof(return)(1, 2); }
Re: Intersection of two sets
On Tuesday, 3 December 2019 at 18:45:18 UTC, Jan Hönig wrote: On Tuesday, 3 December 2019 at 13:55:51 UTC, Alex wrote: This depends on the available accesses on your sets. In terms of ranges: Are your sets InputRanges, ForwardRange, ... ? 2) Are there some build-in function for handling such sets? This is maybe what you are looking for: https://dlang.org/phobos/std_algorithm_setops.html In terms of ranges, i need to understand ranges properly first. The top of https://dlang.org/phobos/std_range.html has some talks and tutorials to consider. The std.algorithm.setops have definitely the functionality i need. I guess my current implementation would be a simple array. I just need to make sure delete, or not create double entries. A problem with the unittest examples is that they assume the reader is very familiar with the language :) Here are some things to keep in mind with setIntersection: 1. setIntersection expects its inputs to be sorted. If they aren't, it doesn't notice; you just don't get the behavior you want. int[] a = [4, 2, 3, 1], b = [8, 4, 2, 6]; assert(setIntersection(a, b).array == []); // ! assert(setIntersection(a.sort, b.sort).array == [2, 4]); 2. setIntersection returns a range, not an array. This probably lets you return the infinite intersections of two infinite ranges, for example. If you're looking at this for Advent of Code you'll probably want to pass the intersections through some other operators that will accept a range. (Also, sort mutates *and* returns the array. if you're depending on the positions of 2 and 4 in the original arrays, you should get the intersection of a sorted copy of them.) In general, pay attention to the static constraints: if (Rs.length >= 2 && allSatisfy!(isInputRange, Rs) && !is(CommonType!(staticMap!(ElementType, Rs)) == void)); In English: 1. if you're getting an intersection of ranges, you need to provide at least two ranges. 2. all of the ranges need to be input ranges 3. the ranges' element types need to have a common type that isn't 'void'. You can use these same constraints in your code if you're not sure if they apply static assert (isInputRange!(typeof(a))); assert(setIntersection(a, b).array == []); or you can test them interactively: $ rdmd --eval 'isInputRange!(typeof([1, 2, 3])).writeln' true And you can also check on their documentation and see if it's what you expect: https://dlang.org/phobos/std_range_primitives.html D doesn't have 500+ line errors for the simplest template misuse like C does, but its much shorter template error messages still could be friendlier. Usually they're in terms of these constraints, or you've a more basic error like having a range type (like the SetIntersection struct that setIntersection actually returns) where some other code expects a simple array, or vice versa.
Re: Unexpectedly nice case of auto return type
On Tuesday, 3 December 2019 at 10:02:47 UTC, Andrea Fontana wrote: On Tuesday, 3 December 2019 at 09:48:39 UTC, Basile B. wrote: You see what surprises me here is that we cannot express the special type that is `TypeNull` and that can only have one value (`null`) so instead we have to use `auto` or `typeof(null)`. You can still create an alias anyway :) alias TypeNull = typeof(null); Speaking of nice stuff and aliases, suppose you want to return a nice tuple with named elements? Option 1: auto auto option1() { return tuple!(int, "apples", int, "oranges")(1, 2); } Option 2: redundancy Tuple!(int, "apples", int, "oranges") option2() { return tuple!(int, "apples", int, "oranges")(1, 2); } Option 3: an alias alias BadMath = Tuple!(int, "apples", int, "oranges"); BadMath option3() { return BadMath(1, 2); } It wasn't obvious to me that BadMath(...) would work. It *should* be obvious since this also works: ... return Tuple!(int, "apples", int, "oranges")(1, 2); But the convenience of tuple() helped to mask that. I was going with silly stuff like ... return cast(BadMath) tuple(1, 2);
Re: Floating-Point arithmetic in dlang - Difference to other languages
On Tuesday, 3 December 2019 at 09:22:49 UTC, Jan Hönig wrote: Today i have stumbled on Hacker News into: https://0.30004.com/ I am learning D, that's why i have to ask. Why does writefln("%.17f", .1+.2); not evaluate into: 0.30004, like C++ but rather to: 0.2 Many other languages evaluate to 0.30004 as well. You can get this result in D as well: $ rdmd --eval 'double a = .1, b = .2; writefln("%.17f", a+b)' 0.30004 https://dlang.org/spec/float.html explains it: real (80bit, 'long double' in C) floats are used in your first calculation, and doubles are used in my revised example. Most other languages give you the double result for very reasonable historical reasons, described here: https://retrocomputing.stackexchange.com/questions/9751/did-any-compiler-fully-use-intel-x87-80-bit-floating-point/9760#9760 D's behavior is a minor 'miss': https://nwcpp.org/Oct-2019.html ... I wanted to include a C example that gives the D result, but it seems to be trickier to force 80 bit intermediates.
Re: how to implement a function in a different D source file
On Tuesday, 26 November 2019 at 03:06:52 UTC, Omar wrote: the page here https://dlang.org/spec/function.html suggests you can implement a function in a different file ... mentioned the endeavour of no-bodied-functions as a way of presenting a black-box type of interface. oh, that's what you were asking. Consider: $ cat interface/references.d module references; string greeting(); $ cat implementation/references.d module references; string greeting() { return "Hello, Dave"; } $ cat main.d import references; void main() { import std.stdio: writeln; writeln(greeting); } And trying to build it: $ dmd -c implementation/references.d $ dmd -Iinterface -c main.d $ dmd main.o references.o $ ./main Hello, Dave
Re: how to implement a function in a different D source file
On Tuesday, 26 November 2019 at 03:06:52 UTC, Omar wrote: Hey, I'm very interested in this programming language, I already prefer it to C++ and if only i had adopted it years ago, but that's beside the point. I read a bunch of tuts today and the only thing I'm really stuck on at the moment is how to actually implement a function in a different file. the page here https://dlang.org/spec/function.html suggests you can implement a function in a different file, and a different tutorial somewhere else (or maybe the same site or even same page idr) mentioned the endeavour of no-bodied-functions as a way of presenting a black-box type of interface. But with the whole module namespace thing I'm a bit at a loss how to do this. Say I have main.d ex.d and ex2.d and I want to import ex, and call a function it declares, and implement the function in ex2.d and link the objects at the end so the linker is happy. I don't know how to do this and I can't find a straigh answer anywhere or any examples. so ? First, here's exactly what you're asking for: $ cat ex1.d enum string admin = "Dave"; $ cat ex2.d import ex1; string greeting() { return "Hello, " ~ admin; } $ cat main.d import ex2; void main() { import std.stdio: writeln; writeln(greeting); } Three files that all import what they need, and can be compiled separately and then linked. $ dmd -c ex1 $ dmd -c ex2 $ dmd -c main $ dmd -ofmain main.o ex2.o ex1.o $ ./main Hello, Dave And dmd isn't cheating, as you can see by skipping the first two compiles: $ rm *.o $ dmd -c main $ dmd -ofmain main.o /usr/bin/ld: main.o: in function `_Dmain': main.d:(.text._Dmain[_Dmain]+0x5): undefined reference to `_D3ex28greetingFZAya' collect2: error: ld returned 1 exit status Error: linker exited with status 1 But you could also just compile everything together: $ rm *.o $ dmd -ofmain *.d $ ./main Hello, Dave If all of your code is in D, my received understanding is that this is a completely reasonable option. You could also use dub as your build system: Package recipe format (sdl/json) [json]: Name [main]: Description [A minimal D application.]: Author name [mipri]: License [proprietary]: MIT Copyright string [Copyright © 2019, mipri]: Add dependency (leave empty to skip) []: This'll create a new directory named 'main', and you can build and run a 'hello world' by running 'dub'. After moving some files around... $ cat source/movie/references/names.d module movie.references.names; enum string admin = "Dave"; $ cat source/movie/references/lines.d module movie.references.lines; string cantDoThat() { import movie.references.names: admin; return "I'm afraid I can't do that, " ~ admin; } $ cat source/app.d void main() { import movie.references.lines: cantDoThat; import std.stdio: writeln; writeln(cantDoThat); } Building and running it: $ dub Performing "debug" build using dmd for x86_64. main ~master: building configuration "application"... Linking... Running ./main I'm afraid I can't do that, Dave
Re: Leak-detection of references to scoped class instances
On Monday, 25 November 2019 at 12:08:54 UTC, Per Nordlöw wrote: On Monday, 25 November 2019 at 08:22:02 UTC, Jacob Carlborg wrote: On Sunday, 24 November 2019 at 21:49:19 UTC, Per Nordlöw wrote: I guess we need a builtin language qualifier for scoped classes for that to work, right? We have that: scope a = new Object; — /Jacob Carlborg Ahh, nice. Does/Will DMD/GDC/LDC (in release builds) make the allocation of `Object` happen on the stack? class C { int x; this(int n) { x = n; } } int heap() { auto x = new C(2); // vgc: `new` causes a GC allocation return x.x; } /+ int example.heap(): sub rsp, 8 mov edi, OFFSET FLAT:example.C.__Class call_d_newclass mov DWORD PTR [rax+16], 2 mov eax, 2 add rsp, 8 ret +/ int stack() { scope x = new C(2); // (no vgc output) return x.x; } /+ int example.stack(): sub rsp, 40 mov rdi, rsp mov QWORD PTR [rsp], OFFSET FLAT:example.C.__vtbl mov QWORD PTR [rsp+8], 0 mov DWORD PTR [rsp+16], 2 call_d_callfinalizer mov eax, 2 add rsp, 40 ret +/ gdc assembly. ldc eliminates the object entirely.
Re: How to wait for a shell process to finish on ctrl+c before exiting?
On Sunday, 24 November 2019 at 15:44:00 UTC, aliak wrote: I'm writing some command line tooling stuff, and one of the command spins up a docker compose file (which in short, spins up some services and aggregates the output of each service to stdout). When a user presses ctrl+c, i would like to pass on the ctrl+c to the spawned process and wait till it handles ctrl+c and then let go of the current process. This might be useful: --- #! /usr/bin/env rdmd import std; import core.stdc.signal; int spawnedPid; extern(C) int kill(int pid, int sig) nothrow @nogc @system; extern (C) int waitpid(int pid, int* status, int options) nothrow @nogc @system; extern(C) void interruptHandler(int sig) nothrow @nogc @system { kill(spawnedPid, SIGTERM); waitpid(spawnedPid, null, 0); } int spawnProcessAndWait(string[] cmd) { auto pid = spawnProcess(cmd, stdin, stdout, stderr); spawnedPid = pid.processID; signal(SIGINT, ); int result = wait(pid); return result; } void main() { spawnProcessAndWait(["perl", "-le", "$SIG{INT} = sub { print 'Ignoring interrupt' }; $SIG{TERM} = sub { print 'Got'; sleep 2; print 'Term' }; print 'Go'; sleep 10"]); } --- I don't just using this code, but running this and seeing how it behaves. For example, you might be surprised by the output if you hit control-C as soon as you see the "Go": --- Go ^CIgnoring interrupt Got Term --- with a 2s delay after 'Got'. Or this output if you remove the Perl $SIG{INT} assignment: --- Go ^C --- with you dropped right back to the shell. It's also possible to cause this code to exit with an exception from the wait(), because there's no process for it wait for.
Re: What is the best way to program over "abstract" types in D?
On Saturday, 23 November 2019 at 21:52:40 UTC, Adam D. Ruppe wrote: On Saturday, 23 November 2019 at 20:22:44 UTC, Ola Fosheim Grøstad wrote: I guess it is possible to use introspection somehow? Yeah, you have to write a function that checks it with introspection and then static assert on it somewhere. This is a little bit better. What it's still missing is a "there's a function with the same signature as this other function, s/type1/type2/" kinda check. abstract class Named { string name(); } template isNamed(alias T) { import std.traits: hasUDA; enum isNamed = hasUDA!(T, Named); static if (isNamed) { static foreach (f; __traits(getVirtualFunctions, Named, "name")) { static assert(__traits(compiles, name(T(; //static assert(__traits(compiles, f(T(; } } } string greet(T)(T x) if (isNamed!T) { return "Hello " ~ x.name; } string greet(T)(T x) if (!isNamed!T) { return "Hello?"; } @Named struct World {}; struct Alice {}; @Named struct Bob {}; string name(World x) { return "World"; } string name(Alice x) { return "Alice"; } string name(Bob x) { return "Bob"; } void main() { import std.stdio: writeln; writeln(greet(World())); writeln(greet(Alice())); writeln(greet(Bob())); }
Re: What is the best way to program over "abstract" types in D?
On Saturday, 23 November 2019 at 11:21:32 UTC, Ola Fosheim Grøstad wrote: ... I read your question as "can I have typeclasses in D?" I'll refer to typeclasses in a language other than Rust. You don't need to know the language. I think you knowing Rust at all might be clouding your vision, actually. First, you have some definition of the typeclass: :- typeclass named(T) where [ func name(T) = string ]. In English: a type T is a named(T) if there's a function 'name' that accepts a T and returns a string. This definition might appear in a module with a bunch of functions that operate on named(T), like :- func greeting(T) <= (named(T)). greeting(W) = "Hello, " ++ name(W). This is a function that accepts a value of a type T (provided that T is named) and then returns the concatenated string. This looks an awful lot like OOP, but there's no runtime dispatch, and there are no objects -- indeed, the type could be a primitive type like int, or float. The exact 'name()' function that gets called is statically determined. Finally, there are declarations that some types are, in fact, instances of the typeclass. :- type world ---> world. :- instance named(world) where [ name(world) = "World" ]. :- instance named(int) where [ name(X) = "Anonymous Integer". ]. % (yes, all ints have the same name) These might appear in completely different modules with their own unrelated code, written by other people, at a later time, and with this instance declaration, when the whole program is compiled together, some integers or the 'world' abstract type might be handled by a lot of code that only knows that it can call some name() function to get a string. This code did not need to be edited to add a 'world' case to a switch to provide this functionality. If you're thirsty when by a river you might drink from the river. If you're thirsty when by a soda machine you might buy a Coke. But rivers are not made of soda. People using FP languages reach for typeclasses and people using OOP languages reach for class hierarchies in the same kinds of situations, even if there are enormous differences in the exact outcome. One difference as you noted is that none of the name() calls is virtual in the typeclass case. So, what would you need for typeclasses in D? You need all the same parts: a static declaration of some kind of typeclass, a static restriction of functions to apply to the typeclass, and static registration of types to the typeclass. At least, you need all these parts if you want the same kind of nice user interface, where invalid registrations are rejected in a timely manner. Here's a hack, instead: Typeclass declaration? There isn't one. Maybe there's documentation: /+ Named(T) string name(T x); // define me +/ Typeclass restriction? It looks for a magic member. You let people into the building because they each came in with their own badge and the badge looks right; you didn't consult a filing cabinet containing descriptions of all the people allowed in the building. You still accomplished the goal. With some caveats: the filing cabinet might've said "cats can come in too", but cats cannot show a badge. Likewise primitive types like ints and floats can't be given static members. template isNamed(alias T) { enum isNamed = hasStaticMember!(T, "secretlyIsNamed"); } As used: string greet(T)(T x) if (isNamed!T) { return "Hello " ~ x.name; } Typeclass registration? Add the member to your types. These types have no other information to them: struct World { static char[0] secretlyIsNamed; } struct Bob { static char[0] secretlyIsNamed; } And then of course, define the required functions: string name(Bob x) { return "Bob"; } string name(World x) { return "World"; } And then you can call them with static dispatch: void main() { writeln(greet(World())); writeln(greet(Bob())); } This all really works. You get your static polymorphism. The compiler doesn't let you forget a name() function (if you try to use it). You have generic code in a library that can be reused with different types provided by users of the library. But because it's a hack, there are some unwanted outcomes. First, other parts of the language can see these secretlyIsNamed members, and that might cause problems. They're not really secret. Second, negative typeclasses are not possible in FP langs, but we have them here: string greet(T)(T x) if (!isNamed!T) { return "Hello???"; } Third, not only can't we register primitive types into typeclasses like this, we also can't register any type that already exists or that's provided by third party code. In an FP lang you could import a serialization module, import some kind of special container from another module, and then in your own code say, "special containers are serializeable too and this is how they should be serialized", even though neither of the module authors were aware of the
Re: Spawning a process, then killing it on SIGINT
On Saturday, 23 November 2019 at 09:54:48 UTC, aliak wrote: Is there a way to go about killing a process after spawning it on a SIGINT? I can't do this for e.g. because kill is not @nogc. Well, this works: import std; import core.stdc.signal; extern(C) int kill(int pid, int sig) nothrow @nogc @system; int currentSpawnedPid; extern(C) void killCurrentPidHandler(int sig) nothrow @nogc @system { if (currentSpawnedPid > 1) kill(currentSpawnedPid, sig); } int main() { auto pid = spawnProcess(["sleep", "50s"], stdin, stdout, stderr); currentSpawnedPid = pid.processID; signal(SIGINT, ); return wait(pid); }
Re: How to simulate Window's "Press any key to continue..."
On Friday, 22 November 2019 at 04:41:30 UTC, mipri wrote: ~this() { reset(); } Oh, if you don't ever call raw() this will break your terminal. I just copied some code from a toy program and adapted it, and didn't notice that until I posted.
Re: How to simulate Window's "Press any key to continue..."
On Friday, 22 November 2019 at 04:22:07 UTC, FireController#1847 wrote: Right, but readln will only wait until the user presses the delimiter (by default Enter/Return). I want it to wait until ANY key is pressed, not a specific key If curses is available you can use it, at the cost of completely changing how you do I/O (in a good way if you need lots of updates): #! /usr/bin/env dub /+ dub.sdl: dependency "nice-curses" version="~>0.2.5" +/ import std.stdio; import nice.curses: Curses; void main() { auto curses = new Curses; auto scr = curses.stdscr; curses.setCursor(0); scr.addstr("Press any key to continue..."); scr.refresh; curses.update; scr.getch; } If you really just briefly want getch-style input in a normal terminal program, and still have a posix system, you can do that with tcsetattr. https://stackoverflow.com/questions/7469139/what-is-the-equivalent-to-getch-getche-in-linux struct Terminal { import core.stdc.stdio: getchar; import core.sys.posix.termios: tcgetattr, tcsetattr, termios, ECHO, ICANON, TCSANOW, TCSAFLUSH; private termios last; int getch() { return getchar(); } int getch_once() { raw; auto r = getchar; reset; return r; } void raw() { termios term; tcgetattr(0, ); term = last; term.c_lflag &= ~(ICANON | ECHO); tcsetattr(0, TCSANOW, ); } void reset() { tcsetattr(0, TCSAFLUSH, ); } ~this() { reset(); } } void main() { import std.stdio: write, writeln; Terminal term; write("Press any key to continue:"); term.getch_once(); writeln; }
Re: How to simulate Window's "Press any key to continue..."
On Friday, 22 November 2019 at 04:10:23 UTC, FireController#1847 wrote: I'm an extreme beginner to DLang (just started using it.. oh, an hour ago?), and I already can't figure out a, what I'd consider, fairly simplistic thing. This is my current code: module DTestApp1; import std.stdio; int main() { write("Press any key to continue..."); stdin.read(); return 0; } I am using Visual Studio to write it, and no matter what I do I cannot get it to work. I attempted to import std.stream;, but it said that while it could find the file, it cannot be read. Am I using the wrong function? For those who don't know, what I'm trying to do is pause the program until literally any key is pressed while in the console. The error doesn't suggest the right replacement, but it still tells you that the function you want isn't available: ./test.d(6): Error: no property read for type File, did you mean std.stdio.File.readf(alias format, Data...)(auto ref Data data) if (isSomeString!(typeof(format)))? std.stdio's documentation is here: https://dlang.org/phobos/std_stdio.html and readln is a function you can use for your purpose. stdin.readln(); Or just: readln;
Re: The effect of ref
On Friday, 22 November 2019 at 03:42:26 UTC, dokutoku wrote: Is there a difference in the execution speed and stability when executing the program by rewriting the parameter of the function argument like this? ```d void test1 (int * X) { // some processing } void test2 (ref int X) { // some processing } ``` The Compiler Explorer supports D, so it's a good way to ask these questions. https://godbolt.org/z/gnR6Eu int example.test1(int*): mov eax, DWORD PTR [rdi] imuleax, eax add eax, 1 ret int example.test2(ref int): mov eax, DWORD PTR [rdi] imuleax, eax add eax, 1 ret
Re: How to get child class Type and members from parent class?
On Wednesday, 20 November 2019 at 10:05:11 UTC, zoujiaqing wrote: import std.stdio; class A { this(T)(T t) { } void write() { T _this = cast(T) this; writeln(this.v); Here, class A knows that a 'v' member is present. So why not just put that member in class A, and let B inherit it? If this method won't apply to some other child classes, you can have an intermediate class that adds the v member and specializes this method to use it, and all the v children can inherit from A through that intermediary. I think what you're wanting to do is a reversal of OO design. Maybe you can use proper OO instead, or maybe you'd prefer a discriminated union if different children will have different types for v. Like in an FP lang: https://github.com/pbackus/sumtype } } class B : A { string v = "hello"; } void main() { auto b = new B; writeln(b.write()); // print hello }
Re: What is the replacement for deprecated array removal
On Monday, 18 November 2019 at 21:25:12 UTC, kerdemdemir wrote: It is a bit weird that such a general case like removing list of elements does not work. And I really do not know the real use of [0,1,2,3].remove(1,2,3). I mean in unit test it looks cool but in real life you will have dynamically calculated indexes. Erdem It seems like a defect in phobos to me as well. Fortunately phobos is written in D so you can just copy this into your code: https://github.com/dlang/phobos/blob/master/std/algorithm/mutation.d#L2160 however, it still doesn't return the same thing as x.remove(1,2,3). ... maybe it'd be simpler to drop down to C-style D? // no checks for out-of-bounds or unsorted offsets void myRemove(ref int[] array, int[] offsets) { int from, to, offset; while (from < array.length) { if (offset < offsets.length && from == offsets[offset]) { ++offset; ++from; } else if (from == to) { ++to; ++from; } else { array[to++] = array[from++]; } } array.length = to; } unittest { int[] x = [1, 2, 3]; int[] y = x.dup, z = x.dup, q = x.dup; myRemove(x, [0]); myRemove(y, []); myRemove(z, [2]); myRemove(q, [1, 2]); assert(x == [2, 3]); assert(y == [1, 2, 3]); assert(z == [1, 2]); assert(q == [1]); } Perhaps it's nice to have the option?
Re: Strange double to uint conversion
On Monday, 18 November 2019 at 21:08:39 UTC, Luiz Silveira wrote: double f; If this is changed to `real f;`, you get the desired result. real is also the type used for the comparison code: https://dlang.org/spec/float.html#fp_const_folding
ints.choice vs. chars.choice
Howdy, The following program fails to compile if the second line is uncommented: import std; void main() { writeln([1, 2, 3].choice); //writeln(['a', 'b', 'c'].choice); } Error: template std.random.choice cannot deduce function from argument types !()(char[], MersenneTwisterEngine!(uint, 32LU, 624LU, 397LU, 31LU, 2567483615u, 11LU, 4294967295u, 7LU, 2636928640u, 15LU, 4022730752u, 18LU, 1812433253u)), candidates are: /usr/include/dmd/phobos/std/random.d(2559): std.random.choice(Range, RandomGen = Random)(auto ref Range range, ref RandomGen urng) if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen) /usr/include/dmd/phobos/std/random.d(2569): std.random.choice(Range)(auto ref Range range) What is going on here? I get it that choice() isn't simply an algorithm over T[], that there are some additional constraints, but surely a char[] is just as random acc... ... Oh. It's because of emojicode. This works: import std; void main() { writeln([1, 2, 3].choice); writeln(cast(char)(cast(uint8_t[])['a', 'b', 'c']).choice); } and this outputs false: writeln(isRandomAccessRange!(char[])); I no longer have any questions but I wish the dlang.org docs were much more generous with examples.
Re: Should I stop being interested in D language if I don't like to see template instantiation in my code?
On Wednesday, 13 November 2019 at 14:01:13 UTC, BoQsc wrote: I don't like to see exclamation marks in my code in as weird syntax as these ones: to!ushort(args[1]) s.formattedRead!"%s!%s:%s"(a, b, c); I'd suggest learning to love it, or at least getting to it, vs. to(args[1]) C++ syntax. Template *syntax* benefits are 1. D's is relatively quick to parse. 2. the ! is an attention getter so you can see that some special action is taking place (although templates don't always require this). Personally this is more of a comfort ("I'm *definitely* doing some work at compile-time here, instead of at runtime like other languages force me to") than an alert ("something weird is happening!") though. 3. it's very clear what's a compile-time vs. a runtime parameter to the template. I'm not sure why, but template instantiation syntax is prevalent in the documentation examples of d lang libraries. It almost seems like every other example contains at least one or two of them. Templates are so beneficial that people put up with C++. D uses them everywhere and if you persist in hating the syntax you'll just hate a lot of the D syntax that you see.
Re: Running unittests of a module with -betterC
On Monday, 28 October 2019 at 08:51:02 UTC, Daniel Kozak wrote: On Mon, Oct 28, 2019 at 9:40 AM Per Nordlöw via Digitalmars-d-learn wrote: Is it possible to run the unittests of a module with -betterC like dmd -D -g -main -unittest -betterC f.d ? This currently errors as /usr/include/dmd/druntime/import/core/internal/entrypoint.d:34: error: undefined reference to '_d_run_main' for an empty file f.d AFAIK no, https://dlang.org/spec/betterc.html#unittests -unittest sets the 'unittest' version identifier. So this works: unittest { assert(0); } version(unittest) { extern(C) void main() { static foreach(u; __traits(getUnitTests, __traits(parent, main))) u(); } } dmd -betterC -unittest -run module.d
Re: About the in expression, Why can't use with array.
On Friday, 25 October 2019 at 15:52:50 UTC, Paul Backus wrote: On Friday, 25 October 2019 at 09:25:21 UTC, Dennis wrote: I can overload the 'in' operator on my types to something that takes exponential time if I want, just like "+" can also be overloaded to a linear time operation on e.g. BigInt. Worth noting that `opIn` is a D1 operator overload, and thus deprecated as of 2.088.0. That wasn't mentioned though? Does it reverse the arguments so that the writeln() examples below can be more naturally ordered? #! /usr/bin/env rdmd import std.stdio; struct X { string data; bool opBinary(string op)(char p) if (op == "in") { foreach (c; data) if (p == c) return true; return false; } } void main() { auto x = X("hi there"); writeln(x in 'i'); writeln(x in '?'); }
Re: GtkD ListG Howto?
On Friday, 11 October 2019 at 19:53:33 UTC, Ron Tarrant wrote: Pixbuf airportImage1, airportImage2, airportImage3, airportImage4; void * image1, image2, image3, image4; airportImage1 = new Pixbuf("images/airport_25.png"); airportImage2 = new Pixbuf("images/airport_35.png"); airportImage3 = new Pixbuf("images/airport_60.png"); airportImage4 = new Pixbuf("images/airport_100.png"); image1 = image2 = image3 = image4 = ListG listG = null; I get the segfault to go away with ListG list = new ListG(null); which is usage you can find in APILookupGLib.txt listG = listG.append(image1); listG = listG.append(image2); listG = listG.append(image3); listG = listG.append(image4); setIconList(listG);
Re: Dynamic Arrays as Stack and/or Queue
On Tuesday, 8 October 2019 at 10:48:45 UTC, Jonathan M Davis wrote: The result of this is that code like stack.popBack(); stack ~= foo; stack ~= bar; stack.popBack(); stack ~= baz; will end up allocating all over the place. Every time you append to the array after shrinking it, you're going to end up with the GC allocating a new block of memory instead of appending in place. Thanks as well! I thought the code I posted would only allocate when the array ran out of capacity. And I see how, even if that's worked around with assumeSafeAppend, it becomes a bad idea to define the stack functions against `ref T[]` as this makes it too easy for other code to slice the array and cause the bugs that assumeSafeAppend allows.
Re: Dynamic Arrays as Stack and/or Queue
On Monday, 7 October 2019 at 19:16:31 UTC, IGotD- wrote: On Monday, 7 October 2019 at 17:36:09 UTC, Ferhat Kurtulmuş wrote: I'm not talking about memory deletion. I'm talking about push, pop, enqueue, and dequeue behavior. I'd assume in a garbage collected language letting the reference float off should be picked up by the GC. I'm sorry. Writing on my mobile phone. Maybe this is what you are looking for https://dlang.org/phobos/std_container_dlist.html I think what he is looking for are the general pop_front, push_front, pop_back and push_back that you would find in virtually any C++ STL container algorithms like list, vector or map. I think this is a good question as I don't really see any good example in the documentation of the dynamic arrays about this. This is very common use case for arrays. Is there any D equivalent? With the performance that you'd expect, I believe: #! /usr/bin/env rdmd import std.stdio; import std.algorithm : moveAll; void push_front(T)(ref T[] xs, T x) { ++xs.length; moveAll(xs[0 .. $-1], xs[1..$]); x[0] = x; } T pop_front(T)(ref T[] xs) { T x = xs[0]; moveAll(xs[1 .. $], xs[0 .. $-1]); --xs.length; return x; } void push_back(T)(ref T[] xs, T x) { xs ~= x; } T pop_back(T)(ref T[] xs) { T x = xs[$ - 1]; --xs.length; return x; } void main() { int[] xs; foreach (i; 0 .. 10) xs.push_back(i); writeln(xs.pop_back()); // output: 9 writeln(xs.pop_front()); // output: 0 writeln(xs.pop_front()); // output: 1 writeln(xs); // output: [2, 3, 4, 5, 6, 7, 8] }
Re: Dynamic Arrays as Stack and/or Queue
On Monday, 7 October 2019 at 17:11:08 UTC, Just Dave wrote: I need a stack and a queue and I noticed that the standard library doesn't appear to have one. Which is ok. I just need something that can logically behave as a stack and queue, which I think the dynamic array should be able to do (if I understand correctly this is effectively the equivalent of vector in C++ or List in C#). However, I'm having a hard time figuring out the best way to push, pop, enqueue and dequeue using D. I'm not seeing here: https://dlang.org/spec/arrays.html, anyway to remove from the array. What's the correct syntax/method call for this? I see you can easily concatenate with '~', but I see no corresponding delete. Sorry for the newbie question, but I'm just unsure where to look for this. if the top of the stack is the last element, --stack.length works as a simple pop.
Re: Blog Post #75: Cairo X - Noodling with the Mouse
On Friday, 4 October 2019 at 20:56:31 UTC, Greatsam4sure wrote: On Tuesday, 1 October 2019 at 09:58:42 UTC, Ron Tarrant wrote: Here's the second installment of the Nodes-n-noodles coverage in which we get the mouse involved: https://gtkdcoding.com/2019/10/01/0075-cairo-x-mouse-noodle.html Pls sir can you make a pdf of the tutorials. that can be easily downloaded once and for all. So that I need to be online. Not everybody have cheap internet. The github repo at https://github.com/rontarrant/gtkDcoding includes the blog posts as a jekyll site under docs/ So you can clone the repo and then follow the instructions at https://jekyllrb.com/ to view the site locally. If you don't use Ruby at all you'll probably get a series of errors with those instructions actually, but each one will suggest a fix that worked for me.
Re: What is the extension of ".pdf"
On Friday, 4 October 2019 at 19:58:16 UTC, Andre Pany wrote: Hi, I try to solve the puzzle https://www.codingame.com/training/easy/mime-type but have some issue because std.path:extension returns null for file name ".pdf" while the puzzle (test case 3) expects that the extension is ".pdf". Is the puzzle wrong or the phobos extension implementation? The implementation is very likely thinking of Unix dotfiles, like .bash_profile, where the intent is to hide the file from normal displays rather than suggest an extension. I don't see a mention of dotfiles in the source, but it has these tests: assert(extension(".foo".dup).empty); assert(extension(".foo.ext"w.dup) == ".ext"); Kind regards Andre
Re: Using algorithms with ranges
On Thursday, 3 October 2019 at 08:52:22 UTC, Andrea Fontana wrote: On Thursday, 3 October 2019 at 05:33:04 UTC, mipri wrote: void main() { import std.range : iota; foreach (x; iota(1, 10).withHistory) writeln(x); } This doesn't work as expected, I think. auto r = iota(1,10).withHistory; writeln(r.front); writeln(r.front); Oops. That output should be the same, since popFront hasn't been called. I made this mistake in my other ranges as well... The code's also bad for preserving the entire history when only the latest is needed for what it's doing.
Re: Using algorithms with ranges
On Thursday, 3 October 2019 at 08:52:22 UTC, Andrea Fontana wrote: On Thursday, 3 October 2019 at 05:33:04 UTC, mipri wrote: void main() { import std.range : iota; foreach (x; iota(1, 10).withHistory) writeln(x); } This doesn't work as expected, I think. auto r = iota(1,10).withHistory; writeln(r.front); writeln(r.front); Oops. That output should be the same, since popFront hasn't been called. The code's also bad for preserving the entire history when only the latest is needed for what it's doing.
Re: Using algorithms with ranges
On Thursday, 3 October 2019 at 05:20:47 UTC, mipri wrote: It'd be nicer to do compose a range over iota, as in iota(1, 10).newThingWithHistory but I don't know how to do that yet. I guess c.f. std.range.retro This is a bit better: #! /usr/bin/env rdmd import std.stdio; auto withHistory(Range)(Range r) { import std.traits : Unqual; import std.range.primitives : ElementType; static struct Result { private: alias R = Unqual!Range; alias T = ElementType!R; R source; T[] history; public: bool empty() { return source.empty; } void popFront() { source.popFront; } T front() { T x = source.front; history ~= x; if (history.length > 1) { return x + history[$-2]; } else { return x; } } } return Result(r); } void main() { import std.range : iota; foreach (x; iota(1, 10).withHistory) writeln(x); }
Re: Using algorithms with ranges
On Thursday, 3 October 2019 at 04:33:10 UTC, Brett wrote: I routinely have to generate data using points sequentially and refer to previous points in the data set, maybe even search them. I also may have to break up the algorithm in to parts. I'd like to get more in to ranges but I simply do not use them much because I don't know all the fancy stuff that makes them more useful over just doing it manually(usually for loop or 3). Is there a way to express an algorithm that generates a data point that may depend on previous data points and "rangify" them? One usually starts with some integer range: iota(-5,5,1) The idea then is to be able to generates points off the range but have access to the previous generated points without having to regenerate them(very inefficient). so if P_k is our kth point then we need to have access to P_j for j < k. ... Again, if the range code is very complicated and one has to jump through a lot of hoops then it is easier to just do it manually. The main thing I'm interested in is the "History" feature and maybe a way to easily partition the range(range of ranges). Basic use (which is all I know) of ranges is easy-peasy. You just define empty/front/popFront and use it as a range. You can keep whatever state you want in addition to that. I've got a range that internally has an open file handle and PCRE pointers in it. The only complication is that I have to put my destructor code in a normal function so that both the destructor (in case of unintended use that leaves the GC cleaning things up) and exhausting the range (in the intended case) can both call it. Here: #! /usr/bin/env rdmd import std.stdio; struct iotaPlus(T) { import std.range : iota; typeof(iota(0,0)) r; T[] history; this(T a, T b) { r = iota(a, b); } bool empty() { return r.empty; } void popFront() { r.popFront; } T front() { T x = r.front; history ~= x; if (history.length > 1) { return x + history[$-2]; } else { return x; } } } void main() { foreach (x; iotaPlus!int(1, 10)) writeln(x); } Output: 1 3 5 7 9 11 13 15 17 It'd be nicer to do compose a range over iota, as in iota(1, 10).newThingWithHistory but I don't know how to do that yet. I guess c.f. std.range.retro
Re: Struct initialization has no effect or error?
On Thursday, 3 October 2019 at 04:33:26 UTC, Brett wrote: I was trying to avoid such things since X is quite long in name. Not a huge deal... and I do not like the syntax because it looks like a constructor call. It is a constructor call, though. You can define your own as well: #! /usr/bin/env rdmd import std.stdio; struct X { int a; this(int x) { a = x * 2; } } void main() { auto test = X(22); writeln(test.a); } output: 44
Re: Why is it difficult to reference arrays in structs?
On Thursday, 3 October 2019 at 04:32:52 UTC, Brett wrote: struct Y { double q; } struct X { Y[] a; } X x; auto r = x.a; r is not a reference?!?! Arrays are (ptr,length) pairs. r is a copy of them: #! /usr/bin/env rdmd import std.stdio; struct X { int[] a; } void main() { auto test = X([0]); test.a.reserve(10); // for later auto r = test.a; writeln(test.a.ptr == r.ptr); // true writeln(test.a.length == r.length); // true } Mutate it and they're still using the same ptr: r ~= [1]; writeln(test.a.ptr == r.ptr); // true writeln(test.a.length == r.length); // false But r is still a copy of the ptr,length pair, and its length is updated separately. Consider: #! /usr/bin/env rdmd import std.stdio; struct X { int[] a; } void main() { X test; test.a.reserve(3); auto a = test.a; a ~= [1, 2, 3]; auto r = test.a.ptr[0..3]; writeln(r); // output: [1, 2, 3] } I have to slice the ptr directly as array operations are aware of all this. Consider: #! /usr/bin/env rdmd import std.stdio; struct X { int[] a; } void main() { X test; test.a.reserve(3); auto a = test.a; a ~= [1, 2, 3]; test.a.length = 3; writeln(test.a); // [0,0,0] writeln(a); // [1,2,3] } What you can do copy the (ptr,length) pair, do what you want with it, and then assign it back to the struct. Don't worry about tricky stuff. auto r = Now r is a reference, great!. look at it: writeln(typeid(a)); // output: int[]* It's a pointer to an int[]. It behaves like a pointer. I want to have a slice of an array that I can append to as a sort of temporary and have it append to the main array(the end of the slice always is the end of the main array).. I've tried assumeSafeAppend but it does nothing to help. Learning D goes into tons of detail about slices and appending to copies and when you'd want assumeSafeAppend and so on.
Re: Struct initialization has no effect or error?
On Wednesday, 2 October 2019 at 17:37:57 UTC, Brett wrote: X y = {3}; works fine. So one has to do x[0] = y; You could initialize x all at once. Complete example: import std.stdio; struct Point { int x, y; string toString() { import std.format : format; return format("(%d, %d)", x, y); } } void main() { Point[2] ps = [{0,0}, {4,4}]; foreach (p; ps) writeln(p); }
Re: Struct initialization has no effect or error?
On Wednesday, 2 October 2019 at 17:54:20 UTC, H. S. Teoh wrote: On Wed, Oct 02, 2019 at 05:37:57PM +, Brett via Digitalmars-d-learn wrote: struct X { int a; } X[1] x; x[0] = {3}; or x[0] = {a:3}; fails; This works: x[0] = X(123); I'd knew I'd gotten the impression from somewhere that this was the recommended way to initialize structs, but it took me a while to find it. Learning D: auto ms1 = MyStruct(10, 11);// struct literal MyStruct ms2 = {10, 11};// C-style, not preferred MyStruct ms3 = {b:11, a:10};// Named initializers .. Struct literals are convenient for simple types ... but they only allow for direct initialization of member variables. If more complex initialization is required, struct constructors should be used. And then the impression was probably just from every single example using the first form. https://dlang.org/spec/struct.html#static_struct_init doesn't say that this is dispreferred in any way, nor does it emphasize that you can't use initialization syntax to assign to an already initialized variable (this is probably obvious to C types). But there are 'Best Practices' notes elsewhere in the page. This section could have one of those, to say to just use the constructors.