Re: 200-600x slower Dlang performance with nested foreach loop
On Tuesday, 26 January 2021 at 21:55:47 UTC, mw wrote: On Tuesday, 26 January 2021 at 17:40:36 UTC, methonash wrote: foreach( i, ref pStr; sortedArr ) { foreach( j, ref cStr; sortedArr[ i + 1 .. $ ] ) { if( indexOf( pStr, cStr ) > -1 ) { // ... yourInnerOp } } } Before adding the code excerpt above, the Dlang program was taking ~1 second on an input file containing approx. 64,000 strings. What's the typical length of your strings? Actually, I think it's reasonable given your algo: Your algo (double-loop) is O(n^2), n = 64,000 so the loop will run n^2 = 4,096,000,000 i.e 4G Suppose your CPU is 2GHz, and suppose each loop operation take just 1 machine cycle (very unlikely), this algo will take 2 seconds. However, string searching i.e `indexOf`, or `yourInnerLoop` can easily take hundreds of cycles, let's suppose it's 100 machine cycles (still a very low estimate), then the algo will take ~200 seconds = ~3.3 minutes. If you want, you can try to rewrite your algo in Java or Python, and compare the run time with the Dlang version.
Re: 200-600x slower Dlang performance with nested foreach loop
On Tuesday, 26 January 2021 at 17:40:36 UTC, methonash wrote: foreach( i, ref pStr; sortedArr ) { foreach( j, ref cStr; sortedArr[ i + 1 .. $ ] ) { if( indexOf( pStr, cStr ) > -1 ) { // ... } } } Before adding the code excerpt above, the Dlang program was taking ~1 second on an input file containing approx. 64,000 strings. What's the typical length of your strings?
Re: Open question: what code pattern you use usually for null safety problem
On Thursday, 14 January 2021 at 18:24:44 UTC, ddcovery wrote: I know there is other threads about null safety and the "possible" ways to support this in D and so on. This is only an open question to know what code patterns you usually use to solve this situation in D: if(person.father.father.name == "Peter") doSomething(); if(person.father.age > 80 ) doSomething(); knowing that *person*, or its *father* property can be null i.e.: the incremental null check solution I just use this most simple one: if( person !is null && person.father !is null && person.father.father !is null && person.father.father.name == "Peter" ) { doSomething(); } Reason: easy to read and reason about, esp for non-authors of this piece of the code.
Re: Why many programmers don't like GC?
On Thursday, 14 January 2021 at 09:26:06 UTC, Ola Fosheim Grøstad wrote: On Thursday, 14 January 2021 at 00:37:29 UTC, mw wrote: ok, what I really mean is: ... in other "(more popular) languages (than D, and directly supported by the language & std library only)" ... Well, even Python supports both Python's `del` isn't guaranteed to free the memory, that's what we are discussing here: core.memory.GC.free / core.stdc.stdlib.free https://www.quora.com/Why-doesnt-Python-release-the-memory-when-I-delete-a-large-object In CPython (the default reference distribution), the Garbage collection in Python is not guaranteed to run when you delete the object - all del (or the object going out of scope) does is decrement the reference count on the object. The memory used by the object is not guaranteed to be freed and returned to the processes pool at any time before the process exits. Even if the Garbage collection does run - all it needs is another object referencing the deleted object and the garbage collection won’t free the object at all.
Re: Why many programmers don't like GC?
On Thursday, 14 January 2021 at 00:15:12 UTC, Ola Fosheim Grøstad wrote: On Wednesday, 13 January 2021 at 21:56:58 UTC, mw wrote: I think this flexibility to mix GC & manual memory management is very unique in D. Actually I'm not sure if it can be done in other languages at all. It sure can. Most AOT languages that provide GC also provide C-interfaces and manual memory management. C++ also had the Boehm-collector since the 90s. Chrome uses Oilpan, a library-style GC with write barriers and incremental collection. ok, what I really mean is: ... in other "(more popular) languages (than D, and directly supported by the language & std library only)" ...
Re: Why many programmers don't like GC?
On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote: I've always heard programmers complain about Garbage Collector GC. But I never understood why they complain. What's bad about GC? I want to stress: in D you can *MIX* GC with manual memory management, which gives you the best of both world. I summarized my experience in one earlier post, (and copy & pasted below); and I also add the code to jdiutil: Just-Do-It util https://wiki.dlang.org/Memory_Management#Explicit_Class_Instance_Allocation https://github.com/mingwugmail/jdiutil/blob/master/source/jdiutil/memory.d === https://forum.dlang.org/post/hzryuifoixwwywwif...@forum.dlang.org One of the upside of D I like is that one can mix GC with manual memory management: https://dlang.org/library/core/memory/gc.free.html which gives you the best of both world. Currently I have a personal project, initially I was solely relying on GC just like in Java: allocate all the objects via `new`, and let the GC take care of all the bookkeeping. But there is a particular set of objects which takes the majority of memory consumption of the program, and even after I carefully removed all the reference after the object is no longer used, the program still use lots of memory because GC collection is un-predictable, both in terms of timing and efficiency. Then I decided to do manual core.memory.GC.free just for that particular objects, (it was not very easy in a multi-threaded program to make all the logic right, but eventually I got it done). And the resulting program now only use ~10% of the memory it used to use. I think this flexibility to mix GC & manual memory management is very unique in D. Actually I'm not sure if it can be done in other languages at all. ===
Re: Collections in D
On Wednesday, 13 January 2021 at 12:06:05 UTC, Roguish wrote: which seems perfectly adequate. What about sets? You can also search https://code.dlang.org I use: https://code.dlang.org/packages/emsi_containers Which has hashset: https://github.com/dlang-community/containers/blob/fc1625a5a0c253272b80addfb4107928495fd647/src/containers/hashset.d
Re: Getting the source text of an expression
On Thursday, 17 December 2020 at 19:45:38 UTC, Dave P. wrote: In C, you can use a macro to get the source text of an expression as a string. For example #include #define PRINT_INT(x) printf(#x " = %d\n", x) int main(){ // prints "3 = 3" PRINT_INT(3); int x = 4; // prints "x = 4" PRINT_INT(x); #define FOO 5 // prints "FOO = 5" PRINT_INT(FOO); #define BAR FOO // prints "BAR = 5" PRINT_INT(BAR); return 0; } Is there a feature of D that allows you to achieve a similar goal? I’ve used this in the past for logging for example. https://code.dlang.org/packages/jdiutil
how to print progress of a long running parallel() loop?
https://dlang.org/phobos/std_parallelism.html#.parallel auto logs = new double[1_000_000]; foreach (i, ref elem; parallel(logs)) { elem = log(i + 1.0); } In Python, using joblib, I can use `verbose` level like this: r = Parallel(n_jobs=2, verbose=10)(delayed(sleep)(.2) for _ in range(10)) to print out the progress. How to do this in D's parallel loop? thanks.
Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
On Monday, 7 December 2020 at 04:38:07 UTC, Paul Backus wrote: On Monday, 7 December 2020 at 04:03:05 UTC, mw wrote: So my next question: given N, how do I create a Tuple!(double, double, ... n-double) type programmatically? import std.meta: Repeat; alias NDoubles = Tuple!(Repeat!(N, double)); Note that N must be a compile-time constant, since the number of elements in a Tuple is fixed at compile time. Yes, I just realized that Tuple (upper T, compile time) and tuple (lower t) are different things. Now, how to convert it to a native array: double[] row = record; Error: cannot implicitly convert expression record of type Tuple!(double, double, double, ..., double) to double[] (I know for tuple, we can do: double[] arr = [record];)
Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
On Monday, 7 December 2020 at 03:51:02 UTC, Paul Backus wrote: On Monday, 7 December 2020 at 02:25:23 UTC, mw wrote: onlineapp.d(8): Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar) should `r`'s type be integer array? and how do I access each elelment of the row? Thanks. The docs [1] say that csvReader returns an input range, not an array. Input ranges don't support indexing, only iteration (e.g. with `foreach`). If you want an array, you will have to use `std.array.array` to create one. [1] http://phobos.dpldocs.info/std.csv.csvReader.1.html Thanks. I saw the 1st example on this page: https://dlang.org/phobos/std_csv.html foreach (record; csvReader!(Tuple!(string, string, int))(text)) { writefln("%s works as a %s and earns $%d per year", record[0], record[1], record[2]); } So my next question: given N, how do I create a Tuple!(double, double, ... n-double) type programmatically?
how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
Hi, I'm trying this code: i.e. print out the 1st element of each row https://run.dlang.io/is/pG921a void main() { import std.csv; import std.stdio: write, writeln, writef, writefln; import std.algorithm.comparison : equal; string text = "76,26,22"; auto records = text.csvReader!int; foreach(r; records) {writeln(r[0]);} // line 8 assert(records.equal!equal([ [76, 26, 22], ])); } but I got a compile error: onlineapp.d(8): Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar) should `r`'s type be integer array? and how do I access each elelment of the row? Thanks.
why `top` report is not consistent with the memory freed by core.stdc.stdlib : free?
Hi, I'm trying this: https://wiki.dlang.org/Memory_Management#Explicit_Class_Instance_Allocation using core.stdc.stdlib : malloc and free to manually manage memory, I tested two scenarios: -- malloc & free -- malloc only and I use Linux command `top` to check the memory used by the program, there is no difference in this two scenarios. I also tried to use `new` to allocate the objects, and GC.free(). The memory number reported by `top` is much less than those reported by using core.stdc.stdlib : malloc and free. I'm wondering why? shouldn't core.stdc.stdlib : malloc and free be more raw (low-level) than new & GC.free()? why `top` shows stdlib free() is not quite working? thanks.
Re: nested module problem
IMO, 3rd party libraries should always be in their own package namespace. Leave the top-level for user code! Why should a local module 'util' conflict with any dependency? It should be the library author's job to make sure his code doesn't conflict with the user's! logged: https://github.com/ariovistus/pyd/issues/140
Re: nested module problem
On Wednesday, 28 October 2020 at 22:52:33 UTC, Adam D. Ruppe wrote: On Wednesday, 28 October 2020 at 22:43:12 UTC, mw wrote: I wonder what's the best way to resolve this conflict, i.e my local file name with 3rd party library dir name. Don't write any module with a single name unless you are guaranteed to never import it. pyd should have called it like `module pyd.util;` Then you call yours like `module mw.util;` This makes such conflicts a lot less likely. Thanks for the tip, Adam. And I fixed the imports in multiple files with: ``` $ sed -i 's/import util;/import mw.util;/g' *.d ``` Hope this will help if someone else also run into this issue.
Re: nested module problem
I run into a similar issue today: -- I try to use a library `pyd`, and -- my local project has a file called "source/util.d" the dub build error out: /.dub/packages/pyd-0.13.1/pyd/infrastructure/util/typelist.d(1,1): Error: package name 'util' conflicts with usage as a module name in file source/util.d I wonder what's the best way to resolve this conflict, i.e my local file name with 3rd party library dir name.
Re: Why does sum not work in static arrays?
On Sunday, 6 December 2015 at 12:27:49 UTC, cym13 wrote: On Sunday, 6 December 2015 at 12:23:05 UTC, Tim K. wrote: Hi! I have the following code: int main(string[] argv) { import std.algorithm: sum; import std.stdio: writeln; uint[3] a1 = [1, 2, 3]; uint[] a2; for (int i = 1; i <= 3; ++i) a2 ~= i; writeln("a1: ", sum(a1)); writeln("a2: ", sum(a2)); return 0; } This throws the error: dummy.d(11): Error: template std.algorithm.iteration.sum cannot deduce function from argument types !()(uint[3]), candidates are: /usr/include/dmd/phobos/std/algorithm/iteration.d(3916): std.algorithm.iteration.sum(R)(R r) if (isInputRange!R && !isInfinite!R && is(typeof(r.front + r.front))) /usr/include/dmd/phobos/std/algorithm/iteration.d(3927): std.algorithm.iteration.sum(R, E)(R r, E seed) if (isInputRange!R && !isInfinite!R && is(typeof(seed = seed + r.front))) So a dynamic array works just fine. In fact, if I uncomment the line in question the program compiles and outputs the correct value (for a2). Why does "sum" not work on static arrays? Regards So that you do not shoot yourself in the foot too easily. A static array is a value type so it is passed by value to functions. If you pass a 1M array to a function... well, I guesse you don't want to do that. Can the template func `sum()` be made to take `ref` of a static array? The solution is to slice it: a1[].sum; That way you avoid the problem. While I understand the explanation of the current behavior, and the work-around, this inconstancy of making func calls means either the library, or the language leaves something to be desired: i.e dynamic array and static array cannot be used interchangeably: (sure I'm not talking about array decl / allocation, the user have to take different actions) I'm talking about a simple function call to calc the sum of the array. ``` sum(static_array[]); // v.s. sum(dynamic_array); ``` For example, if the user first decl a static array for fast prototyping, and later changed mind to use dynamic array, then s/he need to change the call all over the places. (I hope you are not telling me, every time people should use: ``` array_func(any_array[]); ``` is the correct D-idiom to use array in a func call)
Re: What classification should shared objects in qeued thread pools have?
On Thursday, 1 October 2020 at 00:13:41 UTC, IGotD- wrote: I think that the shared in shared structs should not be transitive to members of the struct. The compiler should not Once the aggregate struct data is decl-ed `shared` as a whole, it needs to be transitive to play safe. The compiler (technology) is not that advanced enough to either prove that for a particular sub-component of a shared struct data is fine without protection, or the programmer's intention. enforce this as we don't really know what the programmer will do inside the struct to ensure the thread safety. If the programmer is really sure about his/her design, just cast() the `shared` away.
Re: What classification should shared objects in qeued thread pools have?
On Thursday, 1 October 2020 at 00:00:06 UTC, mw wrote: On Wednesday, 30 September 2020 at 20:13:47 UTC, IGotD- wrote: [...] I think declaring the container and item as `shared` is the D's encouraged way of sharing data among different threads. [...] then just cast the `shared` away: cast()data. [...] I think using `shared` is the D's encouraged way. If there is a better way do this in D, I'd want to know it too. BTW, this is what I learnt from my previous thread: https://forum.dlang.org/post/nlhjzafnmywrgkyjl...@forum.dlang.org
Re: What classification should shared objects in qeued thread pools have?
On Wednesday, 30 September 2020 at 20:13:47 UTC, IGotD- wrote: This where the memory model of D starts to become confusing for me. By default memory allocations/deallocation are not allowed between threads, however setting the object to shared circumvents this. This seems to work as there is no more aborts from the D memory management. However, this has a weird side I think declaring the container and item as `shared` is the D's encouraged way of sharing data among different threads. effect. Now the compiler wants that all my integer member variables operates by using atomic primitives. I don't need this, I know that this object will be sequentially used. then just cast the `shared` away: cast()data. Is shared the wrong way to go here and is there another way to solve this? I think using `shared` is the D's encouraged way. If there is a better way do this in D, I'd want to know it too.
help: cannot build profdump, dub error (bug): Enforcement failed
I remember I used to able to build this package: https://github.com/AntonMeep/profdump but now, I cannot. Since that package haven't changed for 2 years, maybe it's a dub bug? System information $ uname -a Linux 4.15.0-117-generic #118-Ubuntu SMP Fri Sep 4 20:02:41 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $ /usr/bin/dub --version DUB version 1.23.0, built on Sep 27 2020 $ /usr/bin/dmd --version DMD64 D Compiler v2.094.0 Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved written by Walter Bright $ /usr/bin/dub build -v Using dub registry url 'https://code.dlang.org/' Refreshing local packages (refresh existing: true)... Looking for local package map at /var/lib/dub/packages/local-packages.json ... ... No valid package found in current working directory: Enforcement failed Enforcement failed Bug Description Enforcement failed How to reproduce? ``` git clone https://github.com/AntonMeep/profdump cd profdump dub build ``` https://github.com/dlang/dub/issues/2017
what's the best way to convert a sysTime to local machine's time (zone)?
Hi, I'm just wondering what's the best way to convert sysTime to local machine's time (zone)? Is there any library function does this already? https://dlang.org/phobos/std_datetime_systime.html#SysTime (The time in SysTime is kept internally in hnsecs from midnight, January 1st, 1 A.D. UTC.) Thanks.
Re: Why is "delete" unsafe?
On Saturday, 27 October 2012 at 01:08:12 UTC, Jonathan M Davis wrote: On Saturday, October 27, 2012 01:09:39 Alex Rønne Petersen wrote: On 27-10-2012 01:03, Minas wrote: > So the delete keyword has been deprecated - so good bye > manual memory management... Um, no. Use destroy() from the object module instead. Definitely, though it's important to note that what it's doing is inherently different. It destroys what you pass to it but does _not_ free the memory, which is why it's safer. To free memory from the GC, use core.memory.GC.free(). Yes. But using core.memory.GC.free is unsafe for the same reasons that delete is. It's just that it's a druntime function instead of a part of the language, so it's less likely for someone to free GC memory without knowing what they're doing. It's there because there _are_ times when it makes sense and is useful, but it's definitely not safe, so you have to be careful and know what you're doing. What do you mean by saying "it's definitely not safe" here? I mean: if I'm careful and know what I'm doing, e.g. remove all the reference to any part of the `object` before call core.memory.GC.free(object), is there still any inherit "unsafe" side of `free` I should be aware of? FYI: I just described my use case here: https://forum.dlang.org/post/hzryuifoixwwywwif...@forum.dlang.org
Re: create and initialise array
On Thursday, 20 June 2019 at 07:57:25 UTC, KnightMare wrote: On Thursday, 20 June 2019 at 01:32:04 UTC, matheus wrote: import std.stdio; import std.array; void main(){ auto s = uninitializedArray!(float[])(100); s[] = 0.0f; writeln(s[0]); } Even with this, user has to write two statement, why we can't just have: auto s = new float[100](0); another version: auto arr = new double[ 10 ]; writeln( arr[5] ); // NaN arr.length += 10; writeln( arr[15] ); // NaN imo NaN is useless, weird and unusual coz integrals and pointers are "all bits zeroes" but float and chars are "all bits ones". WTF? its strange that bool.init is false in such case. .init = "all zeroes" can be faster initialize any block of memory. I have the same question, why float/double are init to NaN, instead of 0? as other post-C++ language does? e.g Java, C# ... What's the reason for this design decision?
Re: vibe.d: How to get the conent of a file upload ?
On Friday, 18 September 2020 at 00:07:12 UTC, wjoe wrote: Are there other frameworks besides vibe that can do what I want? Just FYI, there is also: https://code.dlang.org/packages/hunt-framework I never used myself, you need to investigate.
Re: Call C variadic function from D variadic function
Just a observation, from the questions & answers in this thread and mine[1]: I think meta-programming in D is somehow like C++, it starts becoming a baroque language. The language is complex enough that there may be ways to get things done, but it's just quite difficult for ordinary users to find *THE* way. [1] https://forum.dlang.org/thread/ujcbioaghvofwowih...@forum.dlang.org
Re: how to do this meta-programming? print the address of random element's address of a variable length of arrays?
On Sunday, 13 September 2020 at 10:16:46 UTC, Paul Backus wrote: On Sunday, 13 September 2020 at 07:00:36 UTC, mw wrote: Here it is: D wrapper for https://ta-lib.org/ https://github.com/mingwugmail/talibd I end up using C macro to generate D functions, the single template is this one: https://github.com/mingwugmail/talibd/blob/master/source/talibd.h#L117 #define DECL_TA_FUNC(TA_FUNC, FUNC_INS, FUNC_OUTS, expected_lookback) __NL__\ The most straightforward way to do this in D is with a mixin template. Something like: mixin template DECL_TA_FUNC(string TA_FUNC, FUNC_INS, FUNC_OUTS, int expected_lookback) { bool impl(...) { // ... } // Could also wrap the whole function in a string mixin, // but this is easier. mixin("alias ", TA_FUNC, " = impl;"); } Which you would then use like this: mixin DECL_TA_FUNC!( "TA_MA", Tuple!(int, "MA_optInTimePeriod", TA_MAType, "opInMAType"), Tuple!(double[], "outMA"), MA_optInTimePeriod - 1 ); Thanks, I will do the exercise some other day. But, I'd reflect on my experience so far on compile-time meta-programming in D as a novice user, the big problems are: -- in D, there are too many choices, with no clear guideline which one is *THE* one to use for a particular purpose: language or library mechanisms? mixin? template? AliasSeq / aliasSeqOf? Tuple? (non-)?-eponymous version of ...?; and even for a particular option, e.g. Tuple!(int, "MA_optInTimePeriod", TA_MAType, "opInMAType"), there are choices to use either token (int) or string ("MA_optInTimePeriod"). And user does not have a strong guide on which choice is *THE* way to proceed. Each mechanism seems to have / fit a particular purpose, but when you start to use it, you'll probably find there are new problems come-in later, and you want to revisit the choice you made earlier on. By contrast, in C: there is only *ONE* mechanism, i.e. macro, that's it. -- in D, there is no easy way to convert between token <==> string. Given a token, does token.stringof always work to paste with other strings to generate a new token? and given a string, does mixin!"string" always work to be a valid token? By contrast, in C: there is only *ONE* way: xxx ## yyy. -- in D, there is no easy way to see directly the generated source code by the compiler at compile-time, which makes the debug difficult during development. By contrast, in C: one can easily see the result via: cpp -P foo.h > foo.c As I said earlier, I'm not very experienced with C macros either, however with some googling, I was able to work out a C macro version to generate D code; but with all the help so far, I still have no confidence that I can work out a solution in D to implement this: ``` bool impl(...) { // ... } ```
Re: how to do this meta-programming? print the address of random element's address of a variable length of arrays?
On Sunday, 13 September 2020 at 01:25:43 UTC, mw wrote: On Saturday, 12 September 2020 at 20:29:40 UTC, Paul Backus If you have a "real-life" application in mind for this, I'd be curious to hear what it is. I'm wrapping a C library, trying to write a single D function / template that can work with a group of C functions, hence I need that kind of signature I described. I'll post the code when I'm ready. Here it is: D wrapper for https://ta-lib.org/ https://github.com/mingwugmail/talibd I end up using C macro to generate D functions, the single template is this one: https://github.com/mingwugmail/talibd/blob/master/source/talibd.h#L117 #define DECL_TA_FUNC(TA_FUNC, FUNC_INS, FUNC_OUTS, expected_lookback) __NL__\ and the macro instantiations are on line 144, 158, 168: DECL_TA_FUNC(TA_MA, MA_INS, MA_OUTS, (MA_optInTimePeriod-1)) DECL_TA_FUNC(TA_RSI, RSI_INS, RSI_OUTS, RSI_optInTimePeriod) DECL_TA_FUNC(TA_MACD, MACD_INS, MACD_OUTS, (optInSlowPeriod+optInSignalPeriod-2)) the generated D functions are here: https://github.com/mingwugmail/talibd/blob/master/source/talibd.d#L47 you can take a look of the 3 generated functions to see the similarities, and pay attention to: -- func decl: TA_xxx( , ) -- assertions on -- func calls: TA_xxx_Lookback() -- func call: talib.TA_xxx(, arrays>, ) There are a number of C macro tricks was used, which I just did some googling to be able to get it done in C -- and with the added benefits that I can directly see the generated source file to debug in the development process. I think it's a non-trivial task to get this compile-time meta-programming done in D, if it can be done at all (I'm not sure). Anyone want to give it a try? and submit a PR :-)
Re: how to do this meta-programming? print the address of random element's address of a variable length of arrays?
On Saturday, 12 September 2020 at 20:29:40 UTC, Paul Backus wrote: On Saturday, 12 September 2020 at 19:31:57 UTC, mw wrote: (I'm asking for a more general solution, e.g. what if we have 3, or N sets of variadic parameters?) Looks like we can only pass 1 variadic parameters, then the question is what's the best way to divide it? Is there any special marker (variable or type?) can be used to divide? and what's the staticSplit? It's possible, but there's no widely-used technique, because it's much easier to simply pass each "parameter set" as a separate array or tuple. So your function signature would look like: auto fun(Set1, Set2, Set3)(Set1 args1, Set2 args2, Set3 args3) if (allSatisfy!(Or!(isArray, isTuple), Set1, Set2, Set3)) Or in the variadic case: auto fun(Args...)(Args args) if (allSatisfy!(Or!(isArray, isTuple), Args)) If you have a "real-life" application in mind for this, I'd be curious to hear what it is. I'm wrapping a C library, trying to write a single D function / template that can work with a group of C functions, hence I need that kind of signature I described. I'll post the code when I'm ready.
Re: how to do this meta-programming? print the address of random element's address of a variable length of arrays?
On Saturday, 12 September 2020 at 19:06:47 UTC, Paul Backus wrote: On Saturday, 12 September 2020 at 18:16:51 UTC, mw wrote: Now, let me expand this challenge: suppose we need to add a new set of variable length extra parameters in parallel to the arrays, i.e: [...] Now the question is how to pass & handle 2 sets of variadic parameters? alias firstSet = args[0 .. $/2]; alias secondSet = args[$/2 .. $]; This solution assumes the two sets are of equal size; what if we don't have such assumption? i.e. we only know the two sets divided into two logical groups. I've tried something like this: the AliasSeq specify the logical divide printRandomElemAddr(AliasSeq!(extraA, extraB, extraC, extraD), a, b, c); but cannot make it work. (I'm asking for a more general solution, e.g. what if we have 3, or N sets of variadic parameters?) Looks like we can only pass 1 variadic parameters, then the question is what's the best way to divide it? Is there any special marker (variable or type?) can be used to divide? and what's the staticSplit?
Re: how to do this meta-programming? print the address of random element's address of a variable length of arrays?
On Saturday, 12 September 2020 at 14:31:59 UTC, Paul Backus wrote: On Saturday, 12 September 2020 at 03:19:23 UTC, mw wrote: I.e. I want to learn the generic meta-programming way to assemble such parameter list (&(x[i], &(y[j])) at compile time, it is possible? It's possible if you use a helper function. Here's how: import std.meta: allSatisfy; import std.traits: isArray; void printRandomElemAddr(Arrays...)(Arrays arrays) if (allSatisfy!(isArray, Arrays)) { auto randomElemAddr(size_t i)() if (i < arrays.length) { import std.random: uniform; return [i][uniform(0, $)]; } import std.stdio: writeln; import std.meta: staticMap, aliasSeqOf; import std.range: iota; writeln(staticMap!(randomElemAddr, aliasSeqOf!(iota(arrays.length; } void main() { int[] a = [1]; int[] b = [2, 3]; double[] c = [4, 5, 6]; printRandomElemAddr(a); printRandomElemAddr(a, b); printRandomElemAddr(a, b, c); } Thanks, this works. staticMap and aliasSeqOf is the key. Now, let me expand this challenge: suppose we need to add a new set of variable length extra parameters in parallel to the arrays, i.e: // just use scalar type for demo intextraA; string extraB; double extraC; // need to be called as: printRandomElemAddr(extraA, a); printRandomElemAddr(extraA, extraB, a, b); printRandomElemAddr(extraA, extraB, extraC, a, b, c); basically, two sets of variadic parameters, but need to be treated differently: -- the 1st scalar set, just use as it is -- the 2nd array set, need some processing (which you have done). Now the question is how to pass & handle 2 sets of variadic parameters?
Re: how to do this meta-programming? print the address of random element's address of a variable length of arrays?
On Saturday, 12 September 2020 at 03:11:09 UTC, Ali Çehreli wrote: On 9/11/20 6:44 PM, mw wrote:> e.g. > > int[] a = new int[la]; > int[] b = new int[lb]; > int[] c = new int[lc]; > int[] d = new int[ld]; > > > the func I want to write, e.g. for 2 arrays (instantiation) is like this: > > void print_random_elem_addr(int[] x, int[] y) { >auto i = random_int_between(0, x.length); >auto j = random_int_between(0, y.length); >print(&(x[i], &(y[j])); // only single print() func call allowed! > } > > > But I want one generic function, which can be called as: > > print_random_elem_addr(a, b); > print_random_elem_addr(a, b, c); > print_random_elem_addr(a, b, c, d); Thanks for the reply. If they are all of same type like int[] in this case, then you but, this is not the intention, we should suppose the array's are heterogeneous type ... can variable number of parameters, which means "any number of int[] arrays" below, elements of which can be called either as separate arguments or as a single array argument: import std.stdio; import std.random; void print_random_elem_addr(int[][] arrays...) { ... to prevent passing in parameters as array of array like this. foreach (i, array; arrays) { const chosen = uniform(0, array.length); writefln!"Array %s, element %s: %s"(i, chosen, [chosen]); actually this writefln will be called n times. I intentionally require: print(&(x[i], &(y[j])); // only single print() func call allowed! I.e. I want to learn the generic meta-programming way to assemble such parameter list (&(x[i], &(y[j])) at compile time, it is possible?
how to do this meta-programming? print the address of random element's address of a variable length of arrays?
e.g. int[] a = new int[la]; int[] b = new int[lb]; int[] c = new int[lc]; int[] d = new int[ld]; the func I want to write, e.g. for 2 arrays (instantiation) is like this: void print_random_elem_addr(int[] x, int[] y) { auto i = random_int_between(0, x.length); auto j = random_int_between(0, y.length); print(&(x[i], &(y[j])); // only single print() func call allowed! } But I want one generic function, which can be called as: print_random_elem_addr(a, b); print_random_elem_addr(a, b, c); print_random_elem_addr(a, b, c, d); ... My main question is how to meta-program (generate the parameter list) this line: print(&(x[i], &(y[j])); // only single print() func call allowed! Thanks!
Re: how to run 'dub upgrade' from within VisualD?
On Monday, 24 August 2020 at 21:19:14 UTC, mw wrote: Hi, Just wonder how to run 'dub upgrade' from within VisualD? on Windows of course. As a work around, I just delete the proj.sln, and regenerated it: ``` C:\\ dub.exe generate visuald ``` then it have the latest package versions.
Re: Shallow copy object when type is know
On Thursday, 21 April 2016 at 11:53:13 UTC, rumbu wrote: On Wednesday, 20 April 2016 at 12:32:48 UTC, Tofu Ninja wrote: Is there a way to shallow copy an object when the type is known? I cant seem to figure out if there is a standard way. I can't just implement a copy function for the class, I need a generic solution. extern (C) Object _d_newclass(TypeInfo_Class ci); Object dup(Object obj) { if (obj is null) return null; ClassInfo ci = obj.classinfo; size_t start = Object.classinfo.init.length; size_t end = ci.init.length; Object clone = _d_newclass(ci); (cast(void*)clone)[start .. end] = (cast(void*)obj)[start .. end]; return clone; } Is this the established D-idiom of a generic class bit-wise clone function (as of 2020)? Any risk of using this implementation I should be aware of? Thanks.
Re: what's this Error: corrupt MS Coff object module
On Tuesday, 25 August 2020 at 01:44:16 UTC, mw wrote: I just tried, using -m32: /mnt/c/project/dlang/dmd-2.093.1/windows/bin/sc.ini [Environment] DFLAGS="-I%@P%\..\..\src\phobos" "-I%@P%\..\..\src\druntime\import" "-d" "-m32" at least that error is gone, and I was able to build: .dub/lib/unit-threaded_property.lib So, looks like this unit-threaded_property.lib cannot be build with -m64, but I just wonder why? Looks like a VisualD issue: https://issues.dlang.org/show_bug.cgi?id=21194 I cannot build with VisualD, but I can build on Windows using command line: C:\project\dlang\dmd-2.093.1\windows\bin64\dub.exe test --build=unittest
Re: what's this Error: corrupt MS Coff object module
On Tuesday, 25 August 2020 at 01:35:00 UTC, mw wrote: On Tuesday, 25 August 2020 at 01:13:11 UTC, Adam D. Ruppe wrote: On Tuesday, 25 August 2020 at 01:08:49 UTC, mw wrote: Is it safe to just delete all the: yup. I have to do this every other week on my work box to keep its hard drive from filling up lol I just completely deleted that `packages` dir, and the /.dub dir and also the app.sln file; then I start from scratch: dub.exe generate visuald But I got the exact same build error: corrupt MS Coff object. I think it's showhow caused by the build process itself, maybe just inside the unit-threaded-1.0.4 package, any suggestions where to check further? I just tried, using -m32: /mnt/c/project/dlang/dmd-2.093.1/windows/bin/sc.ini [Environment] DFLAGS="-I%@P%\..\..\src\phobos" "-I%@P%\..\..\src\druntime\import" "-d" "-m32" at least that error is gone, and I was able to build: .dub/lib/unit-threaded_property.lib So, looks like this unit-threaded_property.lib cannot be build with -m64, but I just wonder why?
Re: what's this Error: corrupt MS Coff object module
On Tuesday, 25 August 2020 at 01:13:11 UTC, Adam D. Ruppe wrote: On Tuesday, 25 August 2020 at 01:08:49 UTC, mw wrote: Is it safe to just delete all the: yup. I have to do this every other week on my work box to keep its hard drive from filling up lol I just completely deleted that `packages` dir, and the /.dub dir and also the app.sln file; then I start from scratch: dub.exe generate visuald But I got the exact same build error: corrupt MS Coff object. I think it's showhow caused by the build process itself, maybe just inside the unit-threaded-1.0.4 package, any suggestions where to check further? Thanks.
Re: what's this Error: corrupt MS Coff object module
On Tuesday, 25 August 2020 at 00:56:51 UTC, Adam D. Ruppe wrote: Might help to just delete the old directories and let it redownload and recompile fresh with all the new settings. Is it safe to just delete all the: C:\Users...\AppData\Local\dub\packages\ and run `dub upgrade` again to redownload everything from the web?
what's this Error: corrupt MS Coff object module
I got this error, when build with VisualD-v1.0.1-dmd-2.093.1-ldc2-1.23.0.exe dmd: lib\unit-threaded_property.lib: Error: corrupt MS Coff object module obj\debug\dummy\dummy\dummy\dummy\dummy\dummy\unit-threaded_property\..\..\..\..\..\..\Users...\AppData\Local\dub\packages\unit-threaded-1.0.4\unit-threaded\subpackages\property\source\unit_threaded\randomized\benchmark.obj 320 lib\unit-threaded_property.lib: Error: corrupt MS Coff object module obj\debug\dummy\dummy\dummy\dummy\dummy\dummy\unit-threaded_property\..\..\..\..\..\..\Users...\AppData\Local\dub\packages\unit-threaded-1.0.4\unit-threaded\subpackages\property\source\unit_threaded\randomized\package.obj 320 Building lib\unit-threaded_property.lib failed! (I didn't add package unit-threaded myself, guess it's indirectly pulled in by some other packages.) How to fix this Coff object issues? (BTW, why there are so many \dummy\... dirs?)
Re: how to run 'dub upgrade' from within VisualD?
On Monday, 24 August 2020 at 21:19:14 UTC, mw wrote: Hi, Just wonder how to run 'dub upgrade' from within VisualD? on Windows of course. In "Solution Explorer", I right click "asdf" and select "DUB Upgrade", but nothing happened: $ grep asdf ats.sln Project("{0CA079BF-A082-4301-BEDE-EB6FE7D43252}") = "asdf", ".dub/asdf.visualdproj", "{CEC987BE-D5B9-4938-BE49-3FDEF54D1BA0}" and in .dub/asdf.visualdproj "..\..\..\..\..\..\Users\zhou\AppData\Local\dub\packages\asdf-0.5.7\asdf\source" it's pointing to an old version, while in dub.json: "asdf": "~>0.6.2", Also, are we suppose to right click on each project and run "DUB Upgrade", instead of just do it once on the solution for all its dependency packages?
how to run 'dub upgrade' from within VisualD?
Hi, Just wonder how to run 'dub upgrade' from within VisualD? on Windows of course. thanks.
SIGUSR1 in clock_nanosleep()? how to isolate this issue?
Hi, I run into an issue: it's SIGUSR1 in clock_nanosleep() --- ... [New Thread 0x70ae0700 (LWP 36860)] [New Thread 0x7fffcbfff700 (LWP 36861)] [Detaching after fork from child process 36862] [New Thread 0x7fffd2eff700 (LWP 36863)] [New Thread 0x7fffd26fe700 (LWP 36864)] [New Thread 0x7fffd1efd700 (LWP 36865)] [New Thread 0x7fffd16fc700 (LWP 36866)] Thread 10 "lt" received signal SIGUSR1, User defined signal 1. [Switching to Thread 0x70ae0700 (LWP 36860)] 0x75d99361 in clock_nanosleep () from /usr/lib/x86_64-linux-gnu/libc.so.6 (gdb) where #0 0x75d99361 in clock_nanosleep () from /usr/lib/x86_64-linux-gnu/libc.so.6 #1 0x75d9eeb7 in nanosleep () from /usr/lib/x86_64-linux-gnu/libc.so.6 #2 0x5585cb89 in _D4core6thread8osthread6Thread5sleepFNbNiSQBo4time8DurationZv () #3 0x555d42b2 in checktatus() (this=0x71262170) at ttt.d:1368 #4 0x55612ee5 in xxxThread() () at aaa.d:88 #5 0x555d736f in _D3std11concurrency__T6_spawnTPFZvZQnFbQjZ4execMFZv () at .../ldc2-1.23.0-linux-x86_64/bin/../import/std/concurrency.d:556 #6 0x5585c32a in thread_entryPoint () #7 0x76020609 in start_thread (arg=) at pthread_create.c:477 #8 0x75ddb103 in clone () from /usr/lib/x86_64-linux-gnu/libc.so.6 --- I tried some simple example which is similar to my app structure, e.g. -- void threadFunc() { foreach (i; 0..10) { auto stats = core.memory.GC.stats(); writeln(stats); Thread.sleep( dur!("msecs")( 50 ) ); } } void main() { spawn(); spawn(); thread_joinAll(); } -- however, it runs fine. Anyone has some suggestions on how to isolate this issue? Thanks.
Re: getopt Basic usage
On Saturday, 15 August 2020 at 04:09:19 UTC, James Gray wrote: I am trying to use getopt and would not like the program to throw an unhandled exception when parsing command line options. Is the following, adapted from the first example in the getopt documentation, a reasonable approach? life is short, use a good library (instead of the raw std lib, or re-invent the wheels): https://code.dlang.org/packages/commandr
Re: vibe.d and my first web service
On Wednesday, 12 August 2020 at 13:46:06 UTC, James Blachly wrote: ... The ctrl-C non-termination bug has existed since at least 2015 from what I can tell from the forums. It's such a pity that so many dub packages are not in friction-free mode. For this particular problem, maybe before it get fixed, can we add to the vibe.d doc suggesting people develop web-server on a virtual machine (e.g. VirtualBox): at least it can reduce some friction to reboot the (virtual) machine more easily.
Re: how to assign to shared obj.systime?
On Friday, 10 July 2020 at 17:35:56 UTC, Steven Schveighoffer wrote: Mark your setTime as shared, then cast away shared (as you don't need atomics once it's locked), and assign: synchronized setTime(ref SysTime t) shared { (cast()this).time = t; } I know I can make it work by casting, my question is: we had a lock on the owning shared object already, WHY we still need the cast to make it compile.
Re: how to assign to shared obj.systime?
On Friday, 10 July 2020 at 17:18:25 UTC, mw wrote: On Friday, 10 July 2020 at 08:48:38 UTC, Kagamin wrote: On Friday, 10 July 2020 at 05:12:06 UTC, mw wrote: looks like we still have to cast: as of 2020, sigh. Why not? Because cast is ugly. I've also tried this: ``` class A { SysTime time; synchronized setTime(ref SysTime t) { time = t; } } void main() { shared A a = new A(); SysTime time; a.setTime(time); } ``` Same Error: template std.datetime.systime.SysTime.opAssign cannot deduce function from argument types !()(SysTime) shared, candidates are: /usr/include/dmd/phobos/std/datetime/systime.d(659,17): opAssign()(auto ref const(SysTime) rhs) However, we have a lock on the owning shared object, still we need cast to make it compile: ``` cast()time = t; ``` Shall I log an enhancement bug for this?
Re: how to assign to shared obj.systime?
On Friday, 10 July 2020 at 08:48:38 UTC, Kagamin wrote: On Friday, 10 July 2020 at 05:12:06 UTC, mw wrote: looks like we still have to cast: as of 2020, sigh. Why not? Because cast is ugly. I've also tried this: ``` class A { SysTime time; synchronized setTime(ref SysTime t) { time = t; } } void main() { shared A a = new A(); SysTime time; a.setTime(time); } ``` Same Error: template std.datetime.systime.SysTime.opAssign cannot deduce function from argument types !()(SysTime) shared, candidates are: /usr/include/dmd/phobos/std/datetime/systime.d(659,17): opAssign()(auto ref const(SysTime) rhs) However, we have a lock on the owning shared object, still we need cast to make it compile: ``` cast()time = t; ```
Re: how to assign to shared obj.systime?
On Friday, 10 July 2020 at 03:01:20 UTC, mw wrote: On Friday, 10 July 2020 at 02:59:56 UTC, mw wrote: Error: template std.datetime.systime.SysTime.opAssign cannot deduce function from argument types !()(SysTime) shared, candidates are: /usr/include/dmd/phobos/std/datetime/systime.d(659,17): opAssign()(auto ref const(SysTime) rhs) of course, better without casting. looks like we still have to cast: https://forum.dlang.org/post/lehfwimpolhrmkfmt...@forum.dlang.org as of 2020, sigh.
Re: how to assign to shared obj.systime?
On Friday, 10 July 2020 at 02:59:56 UTC, mw wrote: Error: template std.datetime.systime.SysTime.opAssign cannot deduce function from argument types !()(SysTime) shared, candidates are: /usr/include/dmd/phobos/std/datetime/systime.d(659,17): opAssign()(auto ref const(SysTime) rhs) of course, better without casting.
how to assign to shared obj.systime?
``` import std.datetime; class A { SysTime time; } void main() { shared A a = new A(); SysTime time; a.time = time; } ``` Error: template std.datetime.systime.SysTime.opAssign cannot deduce function from argument types !()(SysTime) shared, candidates are: /usr/include/dmd/phobos/std/datetime/systime.d(659,17): opAssign()(auto ref const(SysTime) rhs)
Re: How to specify a version from dub build command
On Tuesday, 7 July 2020 at 06:34:15 UTC, adnan338 wrote: I have a separate version for flatpak builds in my app. Let's say I have a large project that builds with dub that goes like this: import std.stdio; void main() { version (flatpak) { writeln(`Flatpak build`); } else { writeln("Edit source/app.d to start your project."); } } Now if I try `dub build --version=flatpak` it's not recognized by the compiler. How can I set the version __from command line__ before building my project? I cannot depend on dflags inside dub.json because dub.json has no idea whether if it's being parsed in a flatpak version build or a regular build. try dub Configurations? https://dub.pm/package-format-json.html#configurations
Re: Associative array on the heap
On Tuesday, 19 May 2015 at 12:21:48 UTC, Steven Schveighoffer wrote: On 5/18/15 7:55 PM, Freddy wrote: How do you allocate an associative array on the heap? void main(){ alias A=int[string]; auto b=new A; } $ rdmd test test.d(4): Error: new can only create structs, dynamic arrays or class objects, not int[string]'s Failed: ["dmd", "-v", "-o-", "test.d", "-I."] As others have said, I don't know why you would want to do this, since AA is already simply a wrapper for a pointer to a AA is a wrapper for a pointer (e.g a struct with some extra info beyond the plain pointer), or AA is just the plain pointer (nothing extra)? I tried this: class Foo {} Foo[string] foos; writeln(foos.sizeof); // print 8 looks like it's just a plain pointer? The usage pattern to have AA on the heap is, e.g: class Class { StudentInfo[string] students; // dict-by-name // many other fields } suppose in a multi-threaded app, the Class object is shared, and one thread will perform a lengthy updates on all the students. To ensure data consistency among all the students object, instead of updating each student's info of the original AA in a loop (with lengthy locking period), it can be achieved by heap-alloc a new AA, update the new AA, and atomic-set: new_students = new StudentInfo[string]; // heap-alloc a new AA // length update on each of new_students atomicStore(theClass.students, new_students);
Re: Translating C headers to D: How do I compile it?
On Sunday, 28 June 2020 at 04:59:12 UTC, Kirill wrote: Hello. I am learning how to translate C headers to D. But how do I compile it? I am stuck with this. You can try just to use dpp: https://code.dlang.org/packages/dpp instead of doing the translation manually.
Re: are std.traits.FieldNameTuple and std.traits.Fields returned value always in sync?
On Monday, 22 June 2020 at 20:08:37 UTC, Stanislav Blinov wrote: But if you'd like it spelled out in text as well, you can make a PR for the Phobos repository. Just-Did-It: https://github.com/dlang/phobos/pull/7540 The point of doc is that the user don't have to dive into the code to know it's usage.
Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();
On Monday, 22 June 2020 at 21:27:12 UTC, Steven Schveighoffer wrote: auto line = range.front; range.popFront; // pop immediately This is a bad idea, once you popFront, the original front is possibly invalid (and technically is the case for byLine). In this case, it's caused by underlying structure may reuse the `byLine` buffer, but I'm asking a more general question about range interface: why not provide an extra popAndReturnFront(), and the user to choose in the actual usage scenario.
Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();
On Monday, 22 June 2020 at 21:22:10 UTC, H. S. Teoh wrote: On Mon, Jun 22, 2020 at 08:51:49PM +, mw via Digitalmars-d-learn wrote: [...] >auto line = range.front; >range.popFront; // pop immediately [...] This is dangerous, because it assumes .front is not invalidated by .popFront. It will not work, for example, with byLine because .front returns a buffer which is reused by .popFront (a so-called "transient range"). This is valid reason, but as I replied in the other post: it depends on the actual underlying data structure and usage scenario, so: "why not provide a popAndReturnFront(), and let the user decide based on his/her own actual usage?"
Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();
On Monday, 22 June 2020 at 20:58:58 UTC, Ali Çehreli wrote: Others have other explanations for this but my understanding is about exception safety: If it changed internal state and returned the front object, you would no be able to make a function like popFront() strongly exception safe. (There are ample documentation for this topic in C++ circles.) That's one consideration. But, it will be more interesting in knowing (based on actual usage): (a) how many bugs % are due to exception un-safe (b) how many bugs % are due to front / popFront separation? And which is more bug-prone for a typical programmer? my gut feeling is (b), at least we just saw one in this thread. And -- loop thru a static structure content like a simple array, why we need to worry about exception safe? -- loop thru dynamically generated content, esp. network or more external complex structure may worth considering exception safety. But even there, do people always need to call !range.empty() check first? when it's not empty, how much more exception un-safety that popAndReturnFront() can introduce than the combination of `front(); ...; popFront();"? And why not provide a popAndReturnFront(), and let the user decide based on his/her own actual usage? Another reason is cohesion: We want functions to have as little responsibility as possible (ideally single). Again we have to weight which way is more bug-prone, any actual statistics on the above (a) v.s (b)? > (or do we have another function for this)? There are many useful functions in std.range: https://dlang.org/phobos/std_range.html The "take" and "drop" functions may be useful. Use these functions inside a while(!range.empty()) {...} can only introduce more code complexity.
Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();
On Monday, 22 June 2020 at 20:49:55 UTC, mw wrote: On Monday, 22 June 2020 at 20:46:30 UTC, mw wrote: On Monday, 22 June 2020 at 20:00:50 UTC, Steven Schveighoffer wrote: I wouldn't recommend it, instead do a while loop: auto range = File(fn).byLine; while(!range.empty) { auto line = range.front; if(someCond(line)) { range.popFrontN(n); I'm asking this, because here it need to be either range.popFrontN(n+1); i.e. bug-prone or can be fixed by: auto line = range.front; range.popFront; // pop immediately of course.
Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();
On Monday, 22 June 2020 at 20:46:30 UTC, mw wrote: On Monday, 22 June 2020 at 20:00:50 UTC, Steven Schveighoffer wrote: I wouldn't recommend it, instead do a while loop: auto range = File(fn).byLine; while(!range.empty) { auto line = range.front; if(someCond(line)) { range.popFrontN(n); I'm asking this, because here it need to be range.popFrontN(n+1); i.e. bug-prone can be fixed by: auto line = range.front; range.popFront; // pop immediately } else { regularProcess(line); range.popFront; } } Thanks. so `front` is peek, and `popFront` is the pop action whose return type is `void`, why we need two *separate* calls instead of just let `popFront` return T (or do we have another function for this)? i.e if the user forget `popFront`, it will prone to infinite loop bug? so my question.
Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();
On Monday, 22 June 2020 at 20:00:50 UTC, Steven Schveighoffer wrote: I wouldn't recommend it, instead do a while loop: auto range = File(fn).byLine; while(!range.empty) { auto line = range.front; if(someCond(line)) { range.popFrontN(n); } else { regularProcess(line); range.popFront; } } Thanks. so `front` is peek, and `popFront` is the pop action whose return type is `void`, why we need two *separate* calls instead of just let `popFront` return T (or do we have another function for this)? i.e if the user forget `popFront`, it will prone to infinite loop bug?
Re: are std.traits.FieldNameTuple and std.traits.Fields returned value always in sync?
On Saturday, 20 June 2020 at 20:42:03 UTC, Stanislav Blinov wrote: On Saturday, 20 June 2020 at 20:17:54 UTC, mw wrote: Are their returned value, i.e the field names and their types are always in the same order, and of the same length? If they are not, how to get sync-ed pairs (name, type)? If they are, why we need two separate calls, which cause confusion. Yes, in the same order and of the same length. Can we add this information to the doc? to make it clear to the user: https://dlang.org/library/std/traits.html
how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();
Hi, I need this logic: ``` auto range = File(fn).byLine(); foreach (line; range) { if (comeCond(line)) { // skip the next n line // and continue the foreach loop from the (n+1) line } else { regularProcess(line); } } ``` Is it possible to do this in a foreach loop? If not, how can I achieve that, esp. when reading a file line-by-line? do I have to read the whole file into memory, and split by line and using regular `for` loop?
are std.traits.FieldNameTuple and std.traits.Fields returned value always in sync?
Are their returned value, i.e the field names and their types are always in the same order, and of the same length? If they are not, how to get sync-ed pairs (name, type)? If they are, why we need two separate calls, which cause confusion.
Re: why cannot spawn function defined in unittest block {}?
On Saturday, 20 June 2020 at 18:08:06 UTC, mw wrote: On Saturday, 20 June 2020 at 18:01:51 UTC, Adam D. Ruppe wrote: On Saturday, 20 June 2020 at 17:43:42 UTC, mw wrote: the function defined in unittest become a delegate? how to work-around this? just add the keyword static to the functions https://github.com/mingwugmail/dlang_tour/blob/master/spawn_in_unittest.d#L50 Tried, still doesn't work: $ dmd -unittest spawn_in_unittest.d spawn_in_unittest.d(57): Error: static function spawn_in_unittest.__unittest_L33_C1.threadProducer cannot access frame of function spawn_in_unittest.__unittest_L33_C1 spawn_in_unittest.d(74): Error: static function spawn_in_unittest.__unittest_L33_C1.threadConsumer cannot access frame of function spawn_in_unittest.__unittest_L33_C1 oh, need to add static to all the function the spawned function calls. static void safePrint(T...)(T args)
Re: why cannot spawn function defined in unittest block {}?
On Saturday, 20 June 2020 at 18:01:51 UTC, Adam D. Ruppe wrote: On Saturday, 20 June 2020 at 17:43:42 UTC, mw wrote: the function defined in unittest become a delegate? how to work-around this? just add the keyword static to the functions https://github.com/mingwugmail/dlang_tour/blob/master/spawn_in_unittest.d#L50 Tried, still doesn't work: $ dmd -unittest spawn_in_unittest.d spawn_in_unittest.d(57): Error: static function spawn_in_unittest.__unittest_L33_C1.threadProducer cannot access frame of function spawn_in_unittest.__unittest_L33_C1 spawn_in_unittest.d(74): Error: static function spawn_in_unittest.__unittest_L33_C1.threadConsumer cannot access frame of function spawn_in_unittest.__unittest_L33_C1
why cannot spawn function defined in unittest block {}?
put the code from: https://tour.dlang.org/tour/en/multithreading/synchronization-sharing in file, and put unittest block from safePrint() to main() as here: https://github.com/mingwugmail/dlang_tour/blob/master/spawn_in_unittest.d#L33 - $ dmd -unittest spawn_in_unittest.d spawn_in_unittest.d(87): Error: template std.concurrency.spawn cannot deduce function from argument types !()(void delegate(shared(SafeQueue!int) queue, shared(int)* queueCounter) @system, shared(SafeQueue!int), shared(int)*), candidates are: /usr/include/dmd/phobos/std/concurrency.d(460):spawn(F, T...)(F fn, T args) with F = void delegate(shared(SafeQueue!int), shared(int)*) @system, T = (shared(SafeQueue!int), shared(int)*) must satisfy the following constraint: isSpawnable!(F, T) spawn_in_unittest.d(88): Error: template std.concurrency.spawn cannot deduce function from argument types !()(void delegate(Tid owner, shared(SafeQueue!int) queue, shared(int)* queueCounter) @system, Tid, shared(SafeQueue!int), shared(int)*), candidates are: /usr/include/dmd/phobos/std/concurrency.d(460):spawn(F, T...)(F fn, T args) with F = void delegate(Tid, shared(SafeQueue!int), shared(int)*) @system, T = (Tid, shared(SafeQueue!int), shared(int)*) must satisfy the following constraint: isSpawnable!(F, T) - spawn in unitest: why this compiler error? confusing message
Re: why cannot spawn function defined in unittest block {}?
the function defined in unittest become a delegate? how to work-around this?
Re: Windows + LDC/DMD installation nightmare when changing VS versions
On Friday, 12 June 2020 at 16:16:18 UTC, mw wrote: On Friday, 12 June 2020 at 15:21:12 UTC, Guillaume Piolat wrote: - With LDC + 32-bit it still fail with: libcmt.lib(chkstk.obj) : fatal error LNK1112: module machine type 'X86' conflicts with target machine type 'x64' Error: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\link.exe failed with status: 1112 ldc2 failed with exit code 1. error: Command 'dub build --build=debug --arch=x86_64 --arch=x86_64 ? check where this config is set? you said it’s for 32 bit --compiler=ldc2 --config=VST-FULL' returned 2 - With DMD + 32-bit it works. Find the corresponding DMD working command config, and set it to ldc2 accordingly.
Re: Windows + LDC/DMD installation nightmare when changing VS versions
On Friday, 12 June 2020 at 15:21:12 UTC, Guillaume Piolat wrote: - With LDC + 32-bit it still fail with: libcmt.lib(chkstk.obj) : fatal error LNK1112: module machine type 'X86' conflicts with target machine type 'x64' Error: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\link.exe failed with status: 1112 ldc2 failed with exit code 1. error: Command 'dub build --build=debug --arch=x86_64 --arch=x86_64 ? check where this config is set? you said it’s for 32 bit --compiler=ldc2 --config=VST-FULL' returned 2
Re: Error: llroundl cannot be interpreted at compile time, because it has no available source code
On Monday, 8 June 2020 at 19:05:45 UTC, Steven Schveighoffer wrote: On 6/8/20 2:53 PM, mw wrote: And with a symbol-to-c-func table, it should be able to just call that C func. Consider that the libc available to the compiler might not be the same as the libc for the target (e.g. cross compilation). Not just that, but this opens the compiler up to a huge hole of unpredictability and security. I head that. But, can we take a pragmatic approach, not the "all-or-none" approach as I talked about in the other MI thread: (https://forum.dlang.org/post/lsnhqdoyatkzbzqbs...@forum.dlang.org) We can have an approved list of C funcs that allowed to be called during CTFE? e.g. math funcs about numbers, but not network or string C funcs. Most people define static const for some numerical values, allow C math func at CTFE may solve a large part of the problems (80-90%? just my guess).
Re: Error: llroundl cannot be interpreted at compile time, because it has no available source code
On Monday, 8 June 2020 at 18:43:58 UTC, Stanislav Blinov wrote: On Monday, 8 June 2020 at 18:08:57 UTC, mw wrote: 2) even it does so, but why such simple function as lroundl cannot be CTFE-ed? Because, as the error message states, there's no source for it :) std.math calls into C math library. OK, but the compiler knows it's external C func: return core.stdc.math.llroundl(x); And with a symbol-to-c-func table, it should be able to just call that C func. This is dramatically enhance CTFE's eval ability, esp for math funcs.
Error: llroundl cannot be interpreted at compile time, because it has no available source code
Hi, I'm trying to build this package: https://code.dlang.org/packages/fixed however, the compiler error out: ldc2-1.21.0-linux-x86_64/bin/../import/std/math.d(5783,39): Error: llroundl cannot be interpreted at compile time, because it has no available source code Looks like it does some CTFE, but 1) I cannot find where CTFE happens in: https://github.com/jaypha/fixed/blob/master/src/jaypha/fixed.d 2) even it does so, but why such simple function as lroundl cannot be CTFE-ed?
Re: how to append (ref) int[] to int[][]?
On Monday, 8 June 2020 at 06:42:44 UTC, Simen Kjærås wrote: Arrays (technically, slices) in D are essentially this struct: struct Array(T) { T* ptr; size_t length; // operator overloads } So when you have int[][], each element of the outer array is an Array!int. These, as simple structs, are copied about, so that changing one does not change another. Thank you for the reply, I think this explanation should be added to the top of https://dlang.org/spec/arrays.html Then people (esp with C/C++ background) can easily understand D's array behavior.
how to append (ref) int[] to int[][]?
Hi, I have this program: import std.stdio; void f(ref int[] arr) { arr ~= 3; } void main() { int[][] arrs; int[] arr; foreach (i; 0 .. 3) { arr = new int[0]; arrs ~= arr; //(a) [[], [], []] f(arr); // arrs ~= arr; //(b) [[3], [3], [3]] } writeln(arrs); } This program will print out [[], [], []]. If I comment out (a), and use (b), it will print out [[3], [3], [3]] So based on this behavior, looks like "~=" will append a copy of `arr`; but what I really want in (a) is append `ref arr` and output [[3], [3], [3]], i.e. the real `arr` be appended instead of its copy. I have to say this semantics surprised me. I tried to change arrs' decl to: (ref (int[]))[] arrs; // the intended semantics I want But I got compiler error out: "found ( when expecting function literal following ref". 1) I'm wondering how to achieve what I want? and 2) why "~=" here will append a copy rather than the real `arr` itself to arrs? Thanks.
Re: Metaprogramming with D
On Saturday, 6 June 2020 at 09:57:36 UTC, Jan Hönig wrote: We have two (little) student projects, which should use D for meta-programming/code generation. More specifically string mixins and templates. I found this doc: https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/D-templates-tutorial.md Really, we should put all these docs in a central place.
Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?
On Thursday, 4 June 2020 at 19:42:57 UTC, mw wrote: On Thursday, 4 June 2020 at 18:42:05 UTC, H. S. Teoh wrote: TBH, whenever I run into a diamond inheritance problem or similar, my first reaction is, I'm using the wrong tool for ^^ Haha, it's also because most of the populate OO languages didn't solve the diamond problem, and made the multiple inheritance hard to use in such situation, that's how the programmers learnt this "first reaction" from past bad experience. Conversely, if all the OO languages solved the diamond problem cleanly from the very start, the programmers will never learn such reaction.
Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?
On Thursday, 4 June 2020 at 18:42:05 UTC, H. S. Teoh wrote: TBH, whenever I run into a diamond inheritance problem or similar, my first reaction is, I'm using the wrong tool for modelling my data; I should be using some kind of component-based system instead of OO inheritance. I have no problem with whatever modelling technique the programmer want to choose. What I hate to see is: if a language does provide the OO mechanism, but having some loop-holes that causes trouble for the programmer who choose to use it. Esp. when these loop-holes are crept in after the language's initial design. (For example, I won't discuss multiple inheritance on a C forum, it's not that language designed for.)
Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?
On Sunday, 31 May 2020 at 06:28:11 UTC, mw wrote: This is better, ... but it breaks std.traits: void main() { auto fields = FieldNameTuple!(Point); writeln(fields); } $ ./b varvarvar And normally, we cannot define 2 fields with different types: class P { int x; double x; // b.d(45): Error: variable b.P.x conflicts with variable b.P.x at b.d(44) } With the above template we somehow tricked the compiler to be able to do this? Is this a loop-hole we should file a bug? This is related to D's silent crept-in multiple inheritance problem, a solution via language improvement is here: https://forum.dlang.org/post/lsnhqdoyatkzbzqbs...@forum.dlang.org I'd imagine something like this: -- class Person : NameI, AddrI { mixin NameT!Person rename equals as name_equals; mixin AddrT!Person rename equals as addr_equals; bool equals(Person other) { return this.name_equals(other) && this.addr_equlas(other); } } --
Re: Logging best practices
On Sunday, 31 May 2020 at 07:49:01 UTC, Luis wrote: On Saturday, 30 May 2020 at 18:17:21 UTC, mw wrote: A related question: how to log to multiple destinations? e.g. both console & log file? any examples? Thanks. ```D auto multiLogger = new MultiLogger(); multiLogger.insertLogger("console", new FileLogger(stdout, LogLevel.all)); multiLogger.insertLogger("file", new FileLogger(outputFile, LogLevel.all)); sharedLog = multiLogger; ``` If you are missing color output for log level , you can use this ConsoleLogger Thanks. For the colored console logger, I'm using this one: https://code.dlang.org/packages/colored-logger so far so good. (I prefer to use library, instead of reinvent my own wheels :-).
Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?
On Sunday, 31 May 2020 at 09:37:24 UTC, Ali Çehreli wrote: On 5/31/20 2:26 AM, Ali Çehreli wrote: Ok, I solved that too with a very convoluted "eponymous mixin template opDispatch." :) struct RW(T) { template opDispatch(string name) { static codeImpl() { import std.format; return format!q{ private %s _%s; public auto %s() { return _%s; } public auto %s(%s val) { _%s = val; return this; } }(T.stringof, name, name, name, name, T.stringof, name); } mixin template opDispatch(alias code = codeImpl()) { mixin (code); } } } struct Point { mixin RW!int.x;// <-- NICE :) mixin RW!int.y; // etc. } import std.traits; import std.stdio; void main() { pragma(msg, FieldNameTuple!(Point)); auto p = Point(1, 2); p.x = 42; p.y = 43; writeln(p); } Ali Thank you all for the refinement. One question: in Sebastiaan's solution opDispatch is performed at run-time, how efficient is the D runtime's implementation of opDispatch compared with a direct regular method call (or a virtual method call in general): ``` public final int x() {return _x;} // in this example it can be final ``` In short, while I want to reduce the boilerplate code I have to write, I don't want to pay any extra run-time cost; compile-time cost is fine. @Ali in your solution, opDispatch is also performed at run-time instead of compile-time (I'm not sure)? since it's inside struct RW, (each x, y is actually a struct inside Point)?
Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?
On Sunday, 31 May 2020 at 00:46:09 UTC, Paul Backus wrote: You can simplify this considerably using a mixin template [1]: --- mixin template RW(T, string name) { private T var; public T get() { return var; } public typeof(this) set(T val) { var = val; return this; } mixin("private alias _", name, " = var;"); // two aliases with the same name create an overload set mixin("public alias ", name, " = get;"); mixin("public alias ", name, " = set;"); } class Point { mixin RW!(int, "x"); mixin RW!(int, "y"); mixin RW!(string, "z"); // add } --- This is better, ... but it breaks std.traits: void main() { auto fields = FieldNameTuple!(Point); writeln(fields); } $ ./b varvarvar And normally, we cannot define 2 fields with different types: class P { int x; double x; // b.d(45): Error: variable b.P.x conflicts with variable b.P.x at b.d(44) } With the above template we somehow tricked the compiler to be able to do this? Is this a loop-hole we should file a bug?
Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?
On Saturday, 30 May 2020 at 22:21:14 UTC, Paul Backus wrote: enum f(string x) = "_" ~ x; int main() { mixin("int ", f!"x", " = 3;"); return _x; } This uses a templated [1] manifest constant [2] to generate the variable name at compile time, and a mixin statement [3] to insert the definition of `_x` into the program. [1] https://dlang.org/spec/template.html#variable-template [2] https://dlang.org/spec/enum.html#manifest_constants [3] https://dlang.org/spec/statement.html#mixin-statement Thank you all for the reply. I hate to write boilerplate code: class Point { private int _x; publicint x() {return _x;} public Point x(int v) {_x=v; return this;} ... // ... y, z } this is what I've got: $ cat b.d // dmd -unittest -vcg-ast -c b.d import std.format; enum RW(string T, string name) = format(q{ private %1$s _%2$s; public %1$s %2$s(){return _%2$s;} public auto %2$s(%1$s v) {_%2$s = v; return this;} }, T, name); class Point { mixin(RW!("int", "x")); mixin(RW!("double", "y")); mixin(RW!("string", "z")); } $ dmd -unittest -vcg-ast -c b.d $ head -n 24 b.d.cg import object; import std.format; enum RW(string T, string name) = format("\x0aprivate %1$s _%2$s;\x0apublic %1$s %2$s(){return _%2$s;}\x0a public auto %2$s(%1$s v) {_%2$s = v; return this;}\x0a ", T, name); class Point : Object { mixin(RW!("int", "x") { enum string RW = ['\x0a', ' ', ' ', ' ', ' ', 'p', 'r', 'i', 'v', 'a', 't', 'e', ' ', 'i', 'n', 't', ' ', '_', 'x', ';', '\x0a', ' ', ' ', ' ', ' ', 'p', 'u', 'b', 'l', 'i', 'c', ' ', ' ', 'i', 'n', 't', ' ', ' ', 'x', '(', ')', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '{', 'r', 'e', 't', 'u', 'r', 'n', ' ', '_', 'x', ';', '}', '\x0a', ' ', ' ', ' ', ' ', 'p', 'u', 'b', 'l', 'i', 'c', ' ', ' ', 'a', 'u', 't', 'o', ' ', ' ', 'x', '(', 'i', 'n', 't', ' ', 'v', ')', ' ', ' ', '{', '_', 'x', ' ', '=', ' ', 'v', ';', ' ', ' ', 'r', 'e', 't', 'u', 'r', 'n', ' ', 't', 'h', 'i', 's', ';', '}', '\x0a', ' ', ' ']; } ); mixin(RW!("double", "y") { enum string RW = ['\x0a', ' ', ' ', ' ', ' ', 'p', 'r', 'i', 'v', 'a', 't', 'e', ' ', 'd', 'o', 'u', 'b', 'l', 'e', ' ', '_', 'y', ';', '\x0a', ' ', ' ', ' ', ' ', 'p', 'u', 'b', 'l', 'i', 'c', ' ', ' ', 'd', 'o', 'u', 'b', 'l', 'e', ' ', ' ', 'y', '(', ')', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '{', 'r', 'e', 't', 'u', 'r', 'n', ' ', '_', 'y', ';', '}', '\x0a', ' ', ' ', ' ', ' ', 'p', 'u', 'b', 'l', 'i', 'c', ' ', ' ', 'a', 'u', 't', 'o', ' ', ' ', 'y', '(', 'd', 'o', 'u', 'b', 'l', 'e', ' ', 'v', ')', ' ', ' ', '{', '_', 'y', ' ', '=', ' ', 'v', ';', ' ', ' ', 'r', 'e', 't', 'u', 'r', 'n', ' ', 't', 'h', 'i', 's', ';', '}', '\x0a', ' ', ' ']; } ); mixin(RW!("string", "z") { enum string RW = ['\x0a', ' ', ' ', ' ', ' ', 'p', 'r', 'i', 'v', 'a', 't', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', '_', 'z', ';', '\x0a', ' ', ' ', ' ', ' ', 'p', 'u', 'b', 'l', 'i', 'c', ' ', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', ' ', 'z', '(', ')', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '{', 'r', 'e', 't', 'u', 'r', 'n', ' ', '_', 'z', ';', '}', '\x0a', ' ', ' ', ' ', ' ', 'p', 'u', 'b', 'l', 'i', 'c', ' ', ' ', 'a', 'u', 't', 'o', ' ', ' ', 'z', '(', 's', 't', 'r', 'i', 'n', 'g', ' ', 'v', ')', ' ', ' ', '{', '_', 'z', ' ', '=', ' ', 'v', ';', ' ', ' ', 'r', 'e', 't', 'u', 'r', 'n', ' ', 't', 'h', 'i', 's', ';', '}', '\x0a', ' ', ' ']; } ); } Am I doing the right thing in D? any improvement you'd suggest? e.g. I don't quite like have to put the type and var name in the quotes as string: mixin(RW!("int", "x")); Is there a better way to achieve this? esp. for the type `int`, is there any way I don't have to quote it as string? Thanks.
how to achieve C's Token Pasting (##) Operator to generate variable name in D?
I want to generate a new symbol (new variable name) from existing one: e.g. in C: $ cat t.c #define f(x) _##x int main() { int f(x) = 3; return _x; } $ make t cc t.c -o t $ ./t $ echo $? 3 I wonder how to do this in D? using template / mixin? traits? Can you show me an example? Thanks.
Re: Logging best practices
On Monday, 29 April 2019 at 16:02:25 UTC, Arun Chandrasekaran wrote: std.experimental.logger is perfectly thread safe. However printing the logging thread ID is still pending with this PR https://github.com/dlang/phobos/pull/6978 Also is any file logger thread safe?
Re: Logging best practices
On Thursday, 25 April 2019 at 10:33:00 UTC, Vladimirs Nordholm wrote: Hello. Is there a current "Best Practices" for logging in D? For the actual logging, I know of `std.experimental.logger`. However, the `experimental` has kept me away from it. Is it good, or are there any better alternatives? A related question: how to log to multiple destinations? e.g. both console & log file? any examples? Thanks.
Re: How to target ldc compiler only in dub
On Wednesday, 27 May 2020 at 00:54:45 UTC, data pulverizer wrote: On Wednesday, 27 May 2020 at 00:52:55 UTC, mw wrote: On Tuesday, 26 May 2020 at 22:28:14 UTC, data pulverizer wrote: I am trying to build a package to target LDC compiler only. I set env: LDC= DUB = $(LDC)/bin/dub then, run this new dub: $(DUB) build Thanks. Building with `dub run --compiler=ldc2` works so I think I'll do that instead. And you can use option dub -v to verify it's calling the correct compiler cmd.
Re: How to target ldc compiler only in dub
On Tuesday, 26 May 2020 at 22:28:14 UTC, data pulverizer wrote: I am trying to build a package to target LDC compiler only. I set env: LDC= DUB = $(LDC)/bin/dub then, run this new dub: $(DUB) build
Re: String interpolation
On Thursday, 21 May 2020 at 06:57:28 UTC, mw wrote: On Thursday, 21 May 2020 at 01:13:27 UTC, Paul Backus wrote: On Wednesday, 20 May 2020 at 23:41:15 UTC, mw wrote: Can we do string interpolation in D now? There's an implementation in the dub package "scriptlike": https://code.dlang.org/packages/scriptlike#string-interpolation Thank you! very nice: // Output: The number 21 doubled is 42! int num = 21; writeln( mixin(interp!"The number ${num} doubled is ${num * 2}!") ); Is there any way to make it shorter? e.g. writeln( s!"The number ${num} doubled is ${num * 2}!" ); i.e how to write this 's'? And for debug print, I like the output be: The number num=21 doubled is num * 2=42! i.e print out the string of the original expression, like the stringy operator in C’s macro #var
Re: String interpolation
On Thursday, 21 May 2020 at 12:53:50 UTC, Adam D. Ruppe wrote: On Thursday, 21 May 2020 at 06:57:28 UTC, mw wrote: i.e how to write this 's'? gimme a like on the proposal to add to the language! https://github.com/dlang/DIPs/pull/186 If accepted, that would let you write i"stuff here".idup to get an interpolated string. Liked. BTW, is the .idup must be there?
Re: String interpolation
On Thursday, 21 May 2020 at 01:13:27 UTC, Paul Backus wrote: On Wednesday, 20 May 2020 at 23:41:15 UTC, mw wrote: Can we do string interpolation in D now? There's an implementation in the dub package "scriptlike": https://code.dlang.org/packages/scriptlike#string-interpolation Thank you! very nice: // Output: The number 21 doubled is 42! int num = 21; writeln( mixin(interp!"The number ${num} doubled is ${num * 2}!") ); Is there any way to make it shorter? e.g. writeln( s!"The number ${num} doubled is ${num * 2}!" ); i.e how to write this 's'?
Re: String interpolation
On Tuesday, 10 November 2015 at 13:36:44 UTC, Andrea Fontana wrote: On Tuesday, 10 November 2015 at 12:40:07 UTC, Márcio Martins wrote: writeln(interp!"The number #{a} is less than #{b}"); Quite pleasant syntax this way :) Not sure if it's feasible to do this on the language side. Yes. Here a (stupid!) proof of concept: http://dpaste.dzfl.pl/74b1a4e3c8c6 $ cat i.d - import std.stdio; template interp(X) { alias interp = mixin(interpGenCode!X); } void main() { int a = 10; int b = 20; writeln(mixin(interp!"The number #{a} is less than #{b}")); writeln(interp!"The number #{a} is less than #{b}"); } - $ dmd.exe i.d i.d(10): Error: template instance interp!"The number #{a} is less than #{b}" does not match template declaration interp(X) i.d(11): Error: template instance interp!"The number #{a} is less than #{b}" does not match template declaration interp(X) I'm wondering if this code has once worked? and seems dpaste.dzfl.pl no longer there. Can we do string interpolation in D now? Speaking of language evolution in the other thread, C# has string interpolation now, here: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated string name = "Mark"; var date = DateTime.Now; Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now."); Python have it here: https://www.python.org/dev/peps/pep-0498/ import datetime name = 'Fred' age = 50 anniversary = datetime.date(1991, 10, 12) f'My name is {name}, my age next year is {age+1}, my anniversary is {anniversary:%A, %B %d, %Y}.' 'My name is Fred, my age next year is 51, my anniversary is Saturday, October 12, 1991.' f'He said his name is {name!r}.' "He said his name is 'Fred'." How can we do it in D? or when will we have it :-)?