How to make project with main application and cli application in the same folder?
Hi guys. Trying to play with vibe-d and want to create separate web app, and cli app which can add admin users. When I just keep both files app.d and cli.d in source folder, I get an error that I can't have more then 1 main function. I already asked chatGPT, and it replied that I need to use subpackages. I put cli into separate folder, and now I get an error, that it can't see some model from main app(I want to reuse UserModel for both, cli and web app). How can I make it visible for both cli and web without making copy? My folder: project | -- dub.json | -- source/ | -- app.d | -- user_model.d | -- cli/ | -- source | -- cli.d dub.json: { "name": "project", "subPackages": [ { "name": "app", "sourcePaths": ["source"], "mainSourceFile": "source/app.d", "targetType": "executable", "dependencies": { "vibe-d": "~>0.9" } }, { "name": "cli", "sourcePaths": ["cli/source"], "mainSourceFile": "cli/source/cli.d", "targetType": "executable", "dependencies": { "vibe-d": "~>0.9" } } ] }
Re: How to make project with main application and cli application in the same folder?
On Sunday, 21 April 2024 at 16:41:08 UTC, Mike Parker wrote: On Sunday, 21 April 2024 at 08:44:38 UTC, alex wrote: Hi guys. Trying to play with vibe-d and want to create separate web app, and cli app which can add admin users. When I just keep both files app.d and cli.d in source folder, I get an error that I can't have more then 1 main function. You can do this using configurations. Whichever you list first will be the default. Then you can use `-c configName` or `--config=configName` to build the other one. You'll want to exclude one of the main functions when building the configuration to which it doesn't belong. You can do that with version specifications (e.g., add a `cli` version in the cli configuration, then `vesrion(cli) void main {...}` in the code). Alternatively, if the files the main functions are in are self-contained, then you can just exclude the one you don't need in each configuration with the `excludeSourceFiles` directive. Configurations: https://dub.pm/dub-guide/recipe/#configurations Thanks, that really helped me. For everyone who has the same trouble I can attach my working solution based on sub packages and configurations. Here is my dub.json: ```json { "name": "cool", "subPackages": [ { "name": "app", "sourcePaths": ["source"], "mainSourceFile": "source/app.d", "targetType": "executable", "configurations": [ { "name": "app", "targetType": "executable", "versions": ["app"] } ] }, { "name": "cli", "sourcePaths": ["source"], "mainSourceFile": "source/cli.d", "targetType": "executable", "configurations": [ { "name": "cli", "targetType": "executable", "versions": ["cli"] } ] } ] } ``` Main functions: app.d: ```d version(app) void main() {...} ``` cli.d: ```d version(cli) void main() {...} ``` And here how I run/build it: ```make dub run :cli dub run :app ``` OR ```make dub build :cli dub build :app ``` During building, it will create executable like "{name_of_project}_app" or "{name_of_project}_cli".
Re: Abstract classes vs interfaces, casting from void*
On Saturday, 10 August 2019 at 08:20:46 UTC, John Colvin wrote: On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote: Thanks for the extra detail. Is there a solid reason to ever use an interface over an abstract class? (Other than multiple inheritance). I'm such a noob at anything related to OO. The general question is tricky, as different languages differ in details what is forced and what is allowed for abstract classes and interfaces. But roughly speaking, my opinion is: if you can/want to provide some default behavior than you are about to write an abstract class. If you are about to provide information/restriction of behavior, then this is more like an interface.
Re: Abstract classes vs interfaces, casting from void*
On Saturday, 10 August 2019 at 14:29:03 UTC, John Colvin wrote: On Saturday, 10 August 2019 at 10:11:15 UTC, Alex wrote: On Saturday, 10 August 2019 at 08:20:46 UTC, John Colvin wrote: On Friday, 9 August 2019 at 13:39:53 UTC, Simen Kjærås wrote: Thanks for the extra detail. Is there a solid reason to ever use an interface over an abstract class? (Other than multiple inheritance). I'm such a noob at anything related to OO. The general question is tricky, as different languages differ in details what is forced and what is allowed for abstract classes and interfaces. But roughly speaking, my opinion is: if you can/want to provide some default behavior than you are about to write an abstract class. If you are about to provide information/restriction of behavior, then this is more like an interface. Ok. What would go wrong (in D) if I just replaced every interface with an abstract class? ´´´ void main(){} interface A { void fun(); } abstract class B{ void fun(); } class C : A{ void fun(){} } class D : B{ /*override*/ void fun(){} } ´´´ case 1: interface A and class C implementing interface A: You don't need to "override" anything. You are forced to provide an implementation of the function inside the class. case 2: abstract class B and class D inheriting from it: You can but not have to provide an implementation of a function inside the abstract class. If I don't and do not provide any implementation inside D I get a linker error. Don't how this case behaves on your system. If you provide an implementation inside the abstract class, you don't have to provide any in the derived one. In any case, if you want to provide an implementation inside the derived class you have to literally "override", as in D implicit overrides are not allowed.
Re: Passing nested template function
On Saturday, 10 August 2019 at 17:45:43 UTC, Prateek Nayak wrote: A nested function can be passed to another function evident from this example: https://run.dlang.io/is/6waRkB However if the nested function is a template function, it raises an error https://run.dlang.io/is/PQhkwl The error being: cannot get frame pointer to the nested function Is there a way to pass a nested template function to a function declared outside the outer function scope? The part I'm not sure about: This is not possible: Before instantiation, the object does not exist, you cannot, therefore, pass its pointer, not to speak about the pointer of its frame. However, how about this: https://run.dlang.io/is/8drZRf
Re: Abstract classes vs interfaces, casting from void*
On Sunday, 11 August 2019 at 13:09:43 UTC, John Colvin wrote: Ok. What would go wrong (in D) if I just replaced every interface with an abstract class? I think there's some confusion here, because B.foo is not abstract. abstract on a class is not inherited by its methods. https://dlang.org/spec/attribute.html#abstract Now, I'm confused, as you asked about abstract classes. So, yes, you can define the abstractness of classes differently. And what is your point?
Re: Abstract classes vs interfaces, casting from void*
On Sunday, 11 August 2019 at 16:05:20 UTC, John Colvin wrote: I'm trying to narrow down exactly what patterns work with each and how they overlap. What I was trying to get at with the abstract method thing is that abstract class C { void foo(); } is an abstract class with a non-abstract method, whose implementation is going to come from somewhere else (not a common pattern in D). class C { abstract void foo(); } is an abstract class with an abstract method foo, which means you have to override it in a inheriting class to get a non-abstract class. As I see this, everything you wrote is correct. :) But you compared abstractness with interface usage, initially. So... I would say, interfaces are more like the abstract method case without any function body. But then, you will have to use "override" all across the inherited classes.
Re: Abstract classes vs interfaces, casting from void*
On Sunday, 11 August 2019 at 20:32:14 UTC, John Colvin wrote: As I see this, everything you wrote is correct. :) But you compared abstractness with interface usage, initially. So... I would say, interfaces are more like the abstract method case without any function body. But then, you will have to use "override" all across the inherited classes. Ok. So that means the difference is pretty subtle, give or take a few extra keywords. Which leaves multiple inheritance as the only significant difference? From my perspective it looks like there are two massively overlapping features with some quite arbitrary feeling restrictions and differences. E.g. why can I not inherit from multiple 100% abstract empty classes? Wouldn't that be the same as inheriting from multiple interfaces? The overlap is there, but it is not so massive, I would say. If you inherit from abstract classes, then you do not plan to keep them empty. So, the overlap you are speaking about is exactly as large as the amount of "100% abstract empty classes". And for these, the approach to keep the interface as a separate interface seems more convenient, as Adam said. In the end, by forcing an explicit override, some semantic is also implied.
Re: What the abstrac final class mean?
On Monday, 12 August 2019 at 08:54:56 UTC, lili wrote: Hi: Why need defined an abstract final class? see https://github.com/Rikarin/Trinix/blob/master/Kernel/arch/amd64/gdt.d From what I saw, all members are static. So, this is a kind of utility class, which is not supposed to be instantiated, nor to be derived from. Maybe, it serves like a namespace, for convenience...
Re: need this for name of type string
On Tuesday, 10 September 2019 at 10:32:29 UTC, Andre Pany wrote: Hi, following coding is throwing compiler error: need this for name of type string The error disappears if I delete method0. My gut feeling is, this is a compiler bug? --- class C { static this() { getT!(typeof(this))(); } @Foo void method0(){} @Foo("abc") void method1(){} } struct Foo { string name; } void getT(T)() { import std.traits: hasUDA, getUDAs; static foreach(fieldName; __traits(allMembers, T)) { static if (hasUDA!(__traits(getMember, T, fieldName), Foo)) { pragma(msg, getUDAs!(__traits(getMember, T, fieldName), Foo)[0].name); } } } void main(){} --- Kind regards André Don't think so. In case of @Foo, you don't instantiate an object. Therefore, name cannot exist. So... in this case, the UDA is a type, not an object you can query for a name. It's more the like the example with SimpleAttr on the help page [1], I think. [1] https://dlang.org/library/std/traits/get_ud_as.html
Re: Looking for a Simple Doubly Linked List Implementation
On Friday, 20 September 2019 at 20:26:03 UTC, Ron Tarrant wrote: Hi guys, I've been banging my head on the screen with this one for the last week or so. For whatever reason, I'm having major problems understanding how to implement a doubly-linked list in D. I don't know if it's because I'm losing my ability to sort these things or if it's just that different from C. If someone could please post a minimal example (if there's extra stuff in there, I'll get confused; I'm getting that old, dammit) I'd be ever so grateful. rosetta code is quite good for such problems http://rosettacode.org/wiki/Doubly-linked_list/Definition#D
Re: how to determine if a function exists in a class?
On Wednesday, 2 October 2019 at 06:06:20 UTC, TodNaz wrote: Hello everyone! I have a question: how to determine if a function exists in a class? Is this possible with @pointer tagging? Do you mean, like in examples of https://dlang.org/library/std/traits/has_member.html ?
Re: Dynamic Arrays as Stack and/or Queue
On Monday, 7 October 2019 at 19:38:50 UTC, mipri wrote: 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 [...] I assume this is a little bit more complicated: while popFront and popBack are ubiquitous in ranges in D, the push functions can't be unified in terms of memory management. For example, you cannot guarantee any performance, while using GC. This opposed to complexity, which is, of course, known. Maybe, this is the reason, why such containers are omitted in Phobos (?) But: There is a priority queue, named binaryheap: https://dlang.org/phobos/std_container_binaryheap.html and there are hints, that for a stack you have to rely e.g., on an array or a list implementation http://www.cplusplus.com/reference/stack/stack/ both exist in phobos: https://dlang.org/phobos/std_container_array.html https://dlang.org/phobos/std_container_dlist.html This gives rise to user implementations like https://code.dlang.org/packages/queue https://code.dlang.org/packages/mergearray etc. Maybe, there will be more soon? ;)
Re: Unable to pass a D function member to a C callback
On Saturday, 2 November 2019 at 17:49:09 UTC, Luh wrote: Hello, When trying to pass a D function to the C callback, the compiler says: 'Error: cannot implicitly convert expression &this.onProcessCb of type extern (C) bool delegate(const(short*) a, ulong b, void* c) to extern (C) bool function(const(short*), ulong, void*' because my function is member of a class (compiles when the function is out of the class). Is there any way to say to solve this ? The wiki isn't very clear about the C callbacks: https://dlang.org/spec/interfaceToC.html#callbacks C code: typedef bool (*onProcessCallback)(const short*, size_t, void*); D Code: - class Game { onProcessCallback m_onProcessCb; this() { m_onProcessCb = &onProcessCb; // Error here } void onProcess() { // ... } extern(C) bool onProcessCb(const short* a, size_t b, void* c) { onProcess(); return true; } } private extern(C) { // Should call onProcess() when executed by the C lib alias onProcessCallback = bool function(const short*, size_t, void*); } - This is because onProcessCb is a member of an object. Therefore, it carries also the information about the context, which includes e.g. all members of the class. Due to this onProcessCb is a delegate, which is something different from a function, cf. https://dlang.org/spec/function.html#closures So, there is a type mismatch.
Re: Splitting a stream of data on based on data change.
On Thursday, 21 November 2019 at 21:36:08 UTC, Taylor R Hillegeist wrote: I was looking through the standard library for a good way to split a range into several ranges based on value changes in the stream: AAABB would be split on the AB transition into: AAA BB I just couldn't figure out an elegant way to do it? Any ideas? Like this? ´´´ void main() { import std; "AAABB" .chunkBy!((a,b) => a == b) .writeln; } ´´´ https://dlang.org/library/std/algorithm/iteration/group.html https://dlang.org/library/std/algorithm/iteration/chunk_by.html
Re: Simple casting?
On Tuesday, 26 November 2019 at 05:17:54 UTC, Taylor R Hillegeist wrote: On Tuesday, 26 November 2019 at 05:05:48 UTC, Taylor R Hillegeist wrote: I'm attempting to do a segment group. details: alias ProbePoint[3]=triple; triple[] irqSortedSet = UniqueTriples.keys .sort!("a[1].irqid < b[1].irqid",SwapStrategy.stable) .array; 83:triple[][] irqSortedSets = irqSortedSet.chunkBy!((a,b) => a[1].irqid == b[1].irqid); GetAllTriplesExtractFileIrqSplit.d(83): Error: cannot implicitly convert expression `chunkBy(irqSortedSet)` of type `ChunkByImpl!(__lambda4, ProbePoint[3][])` to `ProbePoint[3][][]` I have something that looks like a triple[][] but I can't seem to get that type out. when I add .array it converts to a Group which doesn't make sense to me because I'm not using a unary comparison. Any thought? a simpler example: import std.algorithm.comparison : equal; import std.array; // Grouping by particular attribute of each element: uint[3][] data = [ [1, 1,0], [1, 2,0], [2, 2,0], [2, 3,0] ]; uint[3][][] r1 = data.chunkBy!((a,b) => a[0] == b[0]); fails in the same way. What exactly is the problem, as this works for me if I understood your goal correctly: ´´´ void main() { import std.algorithm.comparison : equal; import std.array; import std; // Grouping by particular attribute of each element: uint[3][] data = [ [1, 1,0], [1, 2,0], [2, 2,0], [2, 3,0] ]; auto r1 = data.chunkBy!((a,b) => a[0] == b[0]); } ´´´ If it is the type of the return value --> the return value of chunkBy has a different one compared to the input. Instead, you get an abstracted range whereas the input data serves as a source.
Re: Intersection of two sets
On Tuesday, 3 December 2019 at 13:43:26 UTC, Jan Hönig wrote: It seems i don't google the right keywords. What i want to do: I have two sets. (I didn't find how to do sets, so i have two associative boolean arrays `bool[]`). And i want to join them, via an intersection. I know how to code this. Loop over one AA, if the key is also in the other one, we add that to the third array which is going to be returned. pseudocode: alias set = bool[] set foo = ... set bar = ... set result; foreach(key; foo) { if (key in bar) { result[key] = true; } } return result; 1) Is there a better way for creating a set, other then `alias set = bool[keyClass]`? 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
Re: array of functions/delegates
On Tuesday, 24 December 2019 at 07:37:02 UTC, Rumbu wrote: I am trying to create an array of functions inside a struct. struct S { void f1() {} void f2() {} alias Func = void function(); immutable Func[2] = [&f1, &f2] } What I got: Error: non-constant expression '&f1' Tried also with delegates (since I am in a struct context but I got: no `this` to create delegate `f1`. So, is there any way to have an array of functions without adding them at runtime? If you don't need runtime, probably like this: ´´´ import std; void f1(S s) {assert(1);} void f2(S s) {assert(1);} alias field = AliasSeq!(f1, f2); struct S{} void main() { S s; field[0](s); } ´´´ Don't know why UCFS doesn't work in this case though. Maybe, this is also helpful: https://forum.dlang.org/post/mailman.2415.1354291433.5162.digitalmars-d-le...@puremagic.com
Re: Multi-threaded sorting of text file
On Saturday, 4 January 2020 at 07:51:49 UTC, MGW wrote: Need help: There' s a large text file (hundreds of thousands of lines). The structure is as follows: 2345|wedwededwedwedwe .. 872625|rfrferwewweww . 23|rergrferfefer It is necessary to sort this file by the first field having received: 23|rergrferfefer... 2345|wedwededwedwedwe... 872625|rfrferwewweww... There are also N CPU (from 4 to 8) and 16 Gb of Memory. Necessary come up with an algorithm in D for fast sorting using multithreading. As far as I know, there isn't any native in D. Maybe I overlooked some at code.dlang.org. But there are plenty out there in the wild. Found this on the first shoot: https://stackoverflow.com/questions/23531625/multithreaded-sorting-application/23532317
Re: What type does byGrapheme() return?
On Monday, 6 January 2020 at 08:39:19 UTC, Robert M. Münch wrote: On 2020-01-05 04:18:34 +, H. S. Teoh said: At a minimum, I think we should file a bug report to investigate whether Grapheme.opSlice can be implemented differently, such that we avoid this obscure referential behaviour that makes it hard to work with in complex code. I'm not sure if this is possible, but IMO we should at least investigate the possibilities. Done... my first bug report :-) I copied togehter all the findings from this thread. For the sake of completeness https://issues.dlang.org/show_bug.cgi?id=20483
Re: need help to get member function const address
On Thursday, 19 March 2020 at 04:30:32 UTC, Calvin P wrote: I use this code to get member function address on runtime: = struct A { this(){}; } auto ctor = (&__traits(getMember, A.init,"__ctor")).funcptr; = my question is, how to get it in compile time like static function address: = struct A { void d(){}; static void fn(){}; } enum FN = &A.fn; // static method address is ok enum A0 = &(A.d).funcptr; // Error: need this for d of type void() enum A1 = (&__traits(getMember, A,"d")).funcptr; // Error: no property funcptr for type void function() enum A2 = (&__traits(getMember, A.init,"d")).funcptr; // Error: (&A().d).funcptr cannot be evaluated at compile time = A non-static member method can use the context of the struct where it is defined in. E.g. it could alter a member variable. This context has to be constructed at run time (and there could be many instances of the context) and does not exist in compile time. Therefore the difference to the static method.
Re: Option and Result [was Integration tests]
On Tuesday, 21 April 2020 at 16:30:15 UTC, Russel Winder wrote: On Mon, 2020-04-20 at 20:19 +, aliak via Digitalmars-d-learn wrote: […] [0]: https://github.com/aliak00/optional Rust has Option and Result, and most languages are rapidly introducing at least Option if not Result – and yes it is almost certain all this comes from Haskell. Is Option intended for adding to Phobos? There is Nullable in Phobos. This is not really an Option, I know. But just in case. But back to integration tests, there are indeed only few possibilities to mock something. However, the basics are there. I found a section of code generation a while ago in std.typecons. https://dlang.org/library/std/typecons.html There are Black and White holes there, for example, which could help to implement a basic mocking framework.
Re: Type sniffing at runtime
On Saturday, 16 May 2020 at 05:22:49 UTC, n0den1te wrote: [...] For example, like this: ´´´ import std; alias types = AliasSeq!( bool, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real, char, wchar, dchar ); void main() { static foreach(type; types) { sniffType!type; } } void sniffType(T)() { writeln("Type : ", T.stringof); writeln("Length in bytes: ", T.sizeof); static if(__traits(compiles, T.min)) writeln("Minimum value : ", T.min); writeln("Maximum value : ", T.max); writeln("Initial value : ", T.init); } ´´´ However, for the char, wchar and dchar types the results of min, max and init are somewhat cumbersome. And T.min does not compile for the floating point types.
template evaluation
Hi all, I must overlook something, but given this: ´´´ void main(){} static assert(isMatching!(D, S!(D, true))); // place 1: works as expected. struct D { auto static s = S!(typeof(this), true).init; } enum bool isMatching(T, U) = (){ bool b; static foreach(i, m; __traits(allMembers, T)) { static if(is(typeof(__traits(getMember, T, m)) == U)) { if(b) return false; else b = true; } } return b; }(); struct S(T, bool c = false) //if(isMatching!(T, S!(T, true))) // place 2: does not work {} ´´´ While "place 1" works as expected: it static asserts to true, if type D has a single coinciding member to the checked one and static asserts to false if it doesn't or if there are more of them then one; Why I can't use the same template in "place 2"? PS: Taken the (){}() pattern from here: https://p0nce.github.io/d-idioms/#Precomputed-tables-at-compile-time-through-CTFE
Re: template evaluation
Ok, trying to reduce my example a little bit, I arrived at this: ´´´ void main(){} struct D { size_t dummy; auto static s = S!D.init; } struct S(alias container = null) { pragma(msg, container); static if(__traits(compiles, __traits(allMembers, container))) { static foreach(m; __traits(allMembers, container)) { pragma(msg, m); pragma(msg, is(typeof(__traits(getMember, container, m; /* for D.dummy this yields "true" for D.s this yields "false" */ } } } ´´´ What I clearly have, is a circular reference, now I'm aware of this. So, am I trying something illegal? It seems, I can't get the type of the according member of the template parameter, even then (or should I say "especially because") the analyzing type has the same type. But if this would be the only member, which I can't get the type of, the information would be enough, to ensure what I want. Is it like this?
Re: "%s"-format template function arguments
On Sunday, 15 April 2018 at 12:04:19 UTC, vladdeSV wrote: Hello people of D-land. In a template function, I want to format all arguments as if it was an array. Se this snippet of code: foo(1,2,3); void foo(T...)(T args) { writefln("expected: %s", [1,2,3]); writefln("actual: %s", args); } The code above will output expected: [1, 2, 3] actual: 1 How would I go on about to print all the arguments as I expected it, using "%s"? Best regards, Vladimirs Nordholm --- P.S. I do not understand why only a `1` is printed in the actual result. If you define foo like that, then, you advice D to handle the input as separate objects. That's ok. But then, you have to define that you still assume, they belong together, like an array. In this example the solution is simple: ´´´ void main() { foo(1,2,3); } void foo(T...)(T args) { import std.stdio : writefln; import std.range : only; writefln("expected: %s", [1,2,3]); writefln("actual: %s", args.only); } ´´´ However, there will be problems, if the types of elements differs: While the template foo will be able to handle this, the std.range : only function won't. It assumes at least something common across them. https://dlang.org/library/std/range/only.html
Re: Assoc. Array and struct with immutable member
On Sunday, 15 April 2018 at 17:59:01 UTC, Dgame wrote: How am I supposed to insert a struct with immutable members into an assoc. array? Reduced example: struct A { immutable string name; } A[string] as; as["a"] = A("a"); // Does not work Via a static this() it would work. But I guess, this is not what you are looking for, is it? ´´´ static this() { as["a"] = A("a"); } void main() { assert(as["a"].name == "a"); } struct A { immutable string name; } A[string] as; ´´´ It also works, if you hide the AA in a class and all the insertions into the constructor. ´´´ /* static this() { as["a"] = A("a"); } */ void main() { auto c = new Container(A("a")); assert(c.as["a"].name == "a"); } struct A { immutable string name; } class Container { A[string] as; this(A a) { as[a.name] = a; } } ´´´
Re: Assoc. Array and struct with immutable member
On Tuesday, 17 April 2018 at 11:07:55 UTC, bauss wrote: Even though it works in static this, then it still looks like a bug if you ask me, because the associative array itself isn't immutable. Yeah... I'm not sure, if this behavior is wanted, too... If you argue, that an absent field in in AA is not created, then it is a bug. But if you argue that after creation of the AA everything is created, then adding another field is equal to modifying this very field, and that would be correctly forbidden. So... no clue where a hint in the docu is hidden.
Re: Getting the overload set of a template
On Thursday, 19 April 2018 at 13:57:04 UTC, Simen Kjærås wrote: Currently, there is no way (that I've found, at least) to do this. If you have a workaround, that's great, but there really should be a way - probably __traits(getOverloads). Having __traits(getOverloads) return templates as well should fix some of the issues __traits(getOverloads) has, as a bonus. Would it be possible at all? I mean, if the two following codes are equivalent ´´´ @S("Has foo_A") template foo(string s) if (s == "a") { enum foo = "foo_A"; } @S("Has foo_B") template foo(string s) if (s == "b") { enum foo = "foo_B"; } ´´´ ´´´ template foo(string s) { static if (s == "a") { @S("Has foo_A") enum foo = "foo_A"; } else static if (s == "b") { @S("Has foo_B") enum foo = "foo_B"; } } ´´´ How would you define a "template overload"? And which "overloads" would you like to get if constraints are more general? And last but not least, the getOverloads is defined on functions, which are callable, whereas templates are not, in general...
Re: Getting the overload set of a template
On Thursday, 19 April 2018 at 17:55:47 UTC, Simen Kjærås wrote: Your first example defines two templates (which are overloads of the same name), the second only one. There's no ambiguity there. So, do you mean, that the constraint belongs to the interface of a template?
Re: Getting the overload set of a template
On Saturday, 21 April 2018 at 19:51:05 UTC, Simen Kjærås wrote: On Saturday, 21 April 2018 at 11:23:33 UTC, Alex wrote: So, do you mean, that the constraint belongs to the interface of a template? Not necessarily - it depends on what you want to achieve. The only thing I mean is that the code clearly defines two templates in one case (and chooses which template to instantiate based on the arguments), and one template in the other (and chooses the contents of that template based on the arguments). This is wrong, at least as I understand this: Lowering rules apply. These rules define a set of semantic equivalent constructs. I expect all semantic equivalent constructs to be handled equivalent.** Sure, the end result may be similar*, but how it works in the language is clearly defined, and different between the two cases. *In this case, there are important differences - in the first case the template itself is marked with a UDA, in the second the enum member is. This is a good point. But you won't be able to get the UDA from an uninstantiated template will you? If you will, then, I'm wrong, I think... ** So my point is: If you can transform some construct into another one by lowering rules, than - either: you can't define an overload - or: you can define same overloads on both forms. [1] In the first case foo!"c" will fail to instantiate, in the second it won't. This is due, I didn't add ´´´ else { assert(0); } ´´´ sorry for this. [1] http://www.drdobbs.com/architecture-and-design/so-you-want-to-write-your-own-language/240165488?pgno=2
Re: Getting the overload set of a template
On Sunday, 22 April 2018 at 18:25:29 UTC, Simen Kjærås wrote: No lowering occurs here. A lowering is when the compiler takes one piece of syntax and replaces it with a different one, usually one that's more verbose. In a way, it's kind of like a template being instantiated, in that you write some code and it's being replaced by something else. It's not, however, the same thing. So, how to distinguish it? Templates are sort of like compile-time functions - overloads are chosen in a similar way way to how function overloads are chosen, and the result may depend on the parameters given. Two templates, just like two functions, can give the same result without the templates themselves being the same. *In this case, there are important differences - in the first case the template itself is marked with a UDA, in the second the enum member is. This is a good point. But you won't be able to get the UDA from an uninstantiated template will you? If you will, then, I'm wrong, I think... Why not try it? @("Has foo1_A") template foo1(string s) if (s == "a") { enum foo1 = "foo1_A"; } @("Has foo1_B") template foo1(string s) if (s == "b") { enum foo1 = "foo1_B"; } template foo2(string s) { static if (s == "a") { @("Has foo2_A") enum foo2 = "foo2_A"; } else static if (s == "b") { @("Has foo2_B") enum foo2 = "foo2_B"; } } // tuple("Has foo1_A") pragma(msg, __traits(getAttributes, foo1)); // tuple() pragma(msg, __traits(getAttributes, foo2)); So yes, we can. Templates are real things and can be manipulated, passed to other templates, etc. The example you give, is not what I mean. Compare it with this: @("Has foo1_A") template foo1(string s) if (s == "a") { enum foo1 = "foo1_A"; } @("Has foo1_B") template foo1(string s) if (s == "b") { enum foo1 = "foo1_B"; } template foo2(string s) { static if (s == "a") { @("Has foo2_A") enum foo2 = "foo2_A"; } else static if (s == "b") { @("Has foo2_B") enum foo2 = "foo2_B"; } } // tuple("Has foo1_A") pragma(msg, __traits(getAttributes, foo1!"a")); // tuple("Has foo1_A") pragma(msg, __traits(getAttributes, foo2!"a")); // tuple("Has foo1_B") pragma(msg, __traits(getAttributes, foo1!"b")); // tuple("Has foo1_B") pragma(msg, __traits(getAttributes, foo2!"b"));
Re: Getting the overload set of a template
On Monday, 23 April 2018 at 00:26:23 UTC, Simen Kjærås wrote: // tuple("Has foo1_A") pragma(msg, __traits(getAttributes, foo1!"a")); // tuple("Has foo1_A") pragma(msg, __traits(getAttributes, foo2!"a")); // tuple("Has foo1_B") pragma(msg, __traits(getAttributes, foo1!"b")); // tuple("Has foo1_B") pragma(msg, __traits(getAttributes, foo2!"b")); You explicitly stated 'uninstantiated template'. These are instantiated templates. This seems to indicate that we're talking past each other. I may have misunderstood what you meant when you wrote "But you won't be able to get the UDA from an uninstantiated template will you?", or one of us has misunderstood some other part of the discussion. That could be, but we are getting closer :) So, from the output, we can see, that the both implementation cannot be distinguished (at least by the given pragmas) However, they would be after the new getOverloads version. And I'm wondering all the time, if this is wanted, as the new getOverloads would imply, that I cannot choose between both versions freely. There is a limited set of lowerings, and they are defined in the language, not in user code. They include operator overloading (where `a op b` is translated to `a.opBinary!op(b)`), foreach over ranges (where `foreach(e; range) { }` becomes `for (auto e = range.front; !range.empty(); range.popFront()) { }`), string switching (which is forwarded to a template in druntime), and more that I can't recall right now. This is compiler magic meant to make implementating new features and reasoning about existing features, easier. They are briefly described in the article you linked, but I agree it offers limited insight. I've not found any other great sources of information about it, sadly. This is not true, in my opinion. As an example, Walter gives the rewrite of a while-loop and a foreach-loop into a for-loop, stating that by the ability to do this, the for-loop is more basic than both of the former. So, in my mind, every action of rewriting of something into something else is "lowering". And if you can do this (of course, maintaining the full semantic equivalence), available actions have to remain the same. Said this, I'm not against the new getOverloads. On the contrary, I find the feature cool. But if it is present, it has to yield the same results for foo1 and foo2, just like the pragmas. I'm not sure about the procedure... should I post this as a question to the GitHub, so it can be discussed? pull 2351 or 8195? And yes. I'm lacking information about lowering too. But, if all rewrite processes are "lowering" an explicit definition is not needed, as "everything" is allowed. It has something natural so far... However, if the PR would be accepted in the form it is now, I would make an enhancement request on the docu.
Re: Getting the overload set of a template
On Monday, 23 April 2018 at 07:49:39 UTC, Simen Kjærås wrote: On Monday, 23 April 2018 at 04:58:38 UTC, Alex wrote: On Monday, 23 April 2018 at 00:26:23 UTC, Simen Kjærås wrote: There is a limited set of lowerings, and they are defined in the language, not in user code. They include operator overloading (where `a op b` is translated to `a.opBinary!op(b)`), foreach over ranges (where `foreach(e; range) { }` becomes `for (auto e = range.front; !range.empty(); range.popFront()) { }`), string switching (which is forwarded to a template in druntime), and more that I can't recall right now. This is compiler magic meant to make implementating new features and reasoning about existing features, easier. They are briefly described in the article you linked, but I agree it offers limited insight. I've not found any other great sources of information about it, sadly. This is not true, in my opinion. As an example, Walter gives the rewrite of a while-loop and a foreach-loop into a for-loop, stating that by the ability to do this, the for-loop is more basic than both of the former. So, in my mind, every action of rewriting of something into something else is "lowering". And if you can do this (of course, maintaining the full semantic equivalence), available actions have to remain the same. That's not the definition of lowering used elsewhere, and so will lead to confusion and misunderstanding. I would strongly suggest you rethink your definition of lowering. There is no official definition. That's because some natural rewrite rules are implied, which are very general, I assume... Said this, I'm not against the new getOverloads. On the contrary, I find the feature cool. But if it is present, it has to yield the same results for foo1 and foo2, just like the pragmas. In the general case, this is impossible. Even just limiting ourselves to simple usages of static if it gets unwieldy. This template is from Phobos (all unnecessary code removed). It has 224 different possible combinations of features: private struct _Cache(R, bool bidir) { static if (bidir) {} else {} static if (isInfinite!R) {} else {} static if (hasLength!R) {} version(assert) {} static if (isForwardRange!R) {} static if (hasSlicing!R) { static if (hasEndSlicing) {} static if (!isInfinite!R) {} else static if (hasEndSlicing) {} } } And that's before we even instantiate any templates that this template references - any templates used inside _Cache could increase the number of combinations. But wait, there's more! How many does this have? struct Bar(string s) { mixin(s); } If that's just one overload because of the impossibility of generating the options, what if we introduce a single static if inside it? Is that still one, or is it two? Do we count the possibilities introduced by a template mixin, but not by a string mixin? What if the template mixin comes from a template argument? Sorry if I come off as very dismissive right now - I kind of like the idea, but it seems impossible in practice. I'm not sure about the procedure... should I post this as a question to the GitHub, so it can be discussed? pull 2351 or 8195? What you are suggesting would be a fundamental change in the language, and should be discussed in the digitalmars.D forum. Either PR is not the right place to discuss it. If there's any interest, you will have to write a DIP for how the change will work. -- Simen My point, is that if it is impossible to catch all cases of template rewriting (which I'm advocating from the beginning) getOverloads should not be extended to templates, as this would be a fundamental change in the language.
Re: Getting the overload set of a template
On Monday, 23 April 2018 at 10:57:59 UTC, Simen Kjærås wrote: There is no official definition. That's because some natural rewrite rules are implied, which are very general, I assume... How official do you want it to be? That's the only definition in common use by others in the context of compilers. Stating the existence of rewriting rules is a complex thing. They is no place in the docu (which I could find until now) where they are defined. Therefore, I rely on something which is common. https://en.wikipedia.org/wiki/Natural_transformation We can discuss, whether a template is a functor, but I think this would go beyond the scope of this thread. You mentioned a limited set of lowerings, defined by the language. Where can I find them? I'm very interested in that. There is no template rewriting taking place in the language today - that seems to be a feature you are arguing for. Semantic rewriting is not something which one can take control of. Either you have semantically equal constructs or not. getOverloads should return the overloads of a template as they are defined in the language today. This is the topic of discussion. I argue, that getOverloads can (so far) act only on functions, because only there the term overload is well defined. I see, that it could be defined on templates too, but not in the way you do. Template overloads are mentioned in the D spec[0], and are clearly a real thing that it's useful to be able to manipulate. Yes. But using the term "overload" for templates with the same name does not justify to wrongly apply existing features to more abstract objects. This is what you try to do by using getOverloads with templates. You seem to be arguing against a feature on the basis that if the language were significantly different from what it is, the feature would be confusing. The language isn't that way, so the feature isn't confusing in that way. Well, as we both saw with the pragma output, the language is exactly that way I'm describing it. New getOverload functionality would introduce a new constraint in comparison to the current state. Having getOverloads return template overloads solves a real issue right now, and would be useful even if your suggested change were implemented (though the behavior would be slightly different). What I'm saying is: it would be useful only then, if my suggested change were implemented. Otherwise, it is a new constraint and not a feature. [0]: https://dlang.org/concepts.html
Re: Getting the overload set of a template
On Monday, 23 April 2018 at 14:22:13 UTC, Simen Kjærås wrote: As with all things D, the only real spec is the compiler source code. :p :( :p Proving that two templates are equivalent is in general impossible, since any amount of wasted computation could be performed before the end result is returned, and inputs must be tested exhaustively for the proof to be valid. The fact that two templates give the same result in one special case does not mean that they are equivalent in the general case, and the compiler needs to care about the general case. Ok, thats exactly the point. If you have functions void foo() {} void foo(int n) {} There is no ambiguity which function will be chosen if it will be called. If you have templates // form 1 template Foo(int N) if (N & 1){} // A template Foo(int N) if (!(N & 1)) {} // B OR // form 2 template foo(int N) { static if(N & 1){} // A else{} // B } There is also no ambiguity which will be called. However, getOverloads will behave differently. This is not bad at all. But you have to admit, that while now, there is no way to distinguish form 1 and form 2, with the new getOverloads there will be. This seems strange to me, because there is no reason to distinguish form 1 and form 2. (Because the callable code, which will be generated is the same, I hope... ?) So, in particular, I'm not against the feature. And if the equivalence between form 1 and form 2 is gone, so what. But I don't understand the reasoning why something which is now equal won't be equal any more later?
Re: Getting the overload set of a template
On Monday, 23 April 2018 at 15:44:10 UTC, Simen Kjærås wrote: Ah, but I'm not looking to instantiate the templates, but to learn about them - how many parameters do they take? Are their UDAs different, so that I should warn the programmer? Must I wrap them in different ways? So... Do I have to correct my semantic equality assumptions? There should be a large chapter in the docu about this. It would change at the same time with your feature and the things which are implied and which are not would be evident to the world...
Re: Getting the overload set of a template
On Monday, 23 April 2018 at 16:16:09 UTC, Arafel wrote: ``` import std.meta; void main() { pragma(msg, __traits(getMember, A, "Foo1").stringof); // Foo1(int N) if (N & 1) pragma(msg, __traits(getAttributes, __traits(getMember, A, "Foo1"))[0]); // tuple("int", "odd") alias f1a = Instantiate!(__traits(getMember, A, "Foo1"), 1); // This is expected pragma(msg, f1a); // A alias f1b = Instantiate!(__traits(getMember, A, "Foo1"), "+"); // Why would I know that I can even instantiate?? Also, can I haz UDA plz? pragma(msg, f1b); // B } class A { @("int", "odd") template Foo1(int N) if (N & 1){ enum Foo1 = "A"; } @("string", "+") template Foo1(string op) if (op == "+") { enum Foo1 = "B"; } } ``` I'm not arguing about the case of different interfaces. It is more or less ok, as from different argument types it will be unambiguous which template will be instantiated. It is the case of differentiating templates by their structure and/or constraints. In this case, it is almost sure, that more then one form of implementation exists. However, the forms will yield the same semantic result. And I'm wondering why the implementation form alone leads to differentiation.
Re: Getting the overload set of a template
On Monday, 23 April 2018 at 17:46:10 UTC, Arafel wrote: You could also argue that function overloads are just semantically equivalent to a single function with variadic arguments. It is not. As there are exact known, distinct, finite numbers and types of arguments of functions, which can be used. For example, zero and one. So: void foo(){} void foo(int){} How this is achievable with variadic functions? Whether the compiler actually lowers it like that or not should be just an implementation detail, and thus simply not relevant. Right. And from a syntactical point of view, it wouldn't make any sense if the following "overloads" were treated differently: ``` class A { @("int", "odd") template Foo1(int N) if (N & 1){ enum Foo1 = "A"; } @("int", "even") template Foo1(int N) if (!(N & 1)){ enum Foo1 = "B"; } @("string", "+") template Foo1(string op) if (op == "+") { enum Foo1 = "C"; } @("multi", "string") template Foo1(T...) if (allSatisfy!(isSomeString, typeof(T)) && T.length > 1) { enum Foo1 = "D"; } @("multi", "double") template Foo1(T...) if (allSatisfy!(isFloatingPoint, typeof(T)) && T.length > 1) { enum Foo1 = "E"; } } ``` So, in my opinion, a callable object is overloaded, when there exist more then one interface how to call it. Before a template is instantiated, no callable objects exist. Now, you can go on say well, a template defines a family of objects, which build up an overload set. This is not doable, see the discussion before. But of course, you can go the other way and say well, if there exist a declaration then, based on the declaration inspection, let us define an overload set, based on the same symbol names. This is a different way of defining an overload, which is not obvious, especially if you see the pragma output from a former post. Therein the pragmas, which act also before runtime do not differ between declarations, but only between instantiations.
Re: Troubles with template constraints on string and static if
On Thursday, 26 April 2018 at 15:06:49 UTC, sungal wrote: I have this piece of code and I can't understand why the `static if` conditionals are always false. ``` import std.digest.sha; import std.file; import std.stdio; void main() { auto hash1 = produceHash!string("prova.d"); auto hash2 = produceHash!File(File("./prova.d")); } string produceHash(Type)(Type data) if(is(Type == string) || is(Type == File)) { string h; static if(is(Type == File)) { enforce(data.exists, "File does not exist."); // Hashing both name and file, to avoid having the same Hash on empty files return toHexString(digest!SHA256(data.byChunk(4096*1024))).dup; } else static if(is(Type == string)){ return toHexString(digest!SHA256(data)).dup; } static assert(false, "Data must be string or file. "); } ``` ``` prova.d(22): Error: static assert "Data must be string or file. " prova.d(7):instantiated from here: produceHash!string ``` The static assert is unconditionally evaluated after the static if/else clause. This leads to a compile time assertion failure. Add an "else", maybe.
Re: Template to retrieve compile-time enum member from run-time enum member?
On Friday, 27 April 2018 at 13:43:47 UTC, Timoses wrote: `instantiateWith` gets called in three variations (menum.A, menum.B and menum.C). This causes instantiateWith to return TempStruct for each case of Temp... However, I was under the impression that a templated function will exist multiple (in this case 3) times, so the return type should be allowed to be different?! I think, because the enum value is a runtime parameter for instantiateWith, only a single variation of it exists. And this cannot have different return types. So... "alias Fn" and "T" stay the same. The value of x varies. https://run.dlang.io/is/jX4Ybh states the same.
Error: module `hello` is in file 'hello.d' which cannot be read
Hi I just installed D on my windows 10 and want to try to compile a hello world. My source is a classical import std.stdio; void main() { writeln("Hello, World!"); } And I try to compile and get C:\D>dmd hello.d Error: module `hello` is in file 'hello.d' which cannot be read import path[0] = C:\D\dmd2\windows\bin\..\..\src\phobos import path[1] = C:\D\dmd2\windows\bin\..\..\src\druntime\import What do I do wrong ? D is installed at de root of C:, and the hello.d source code is at C:\D\dmd2\sources. Thank you to you Alex
Re: Error: module `hello` is in file 'hello.d' which cannot be read
Thank you for you for your quick answer. I think I allready tryed this, before asking, but ... C:\>cd D\dmd2\sources C:\D\dmd2\sources>dmd hello.d Error: module `hello` is in file 'hello.d' which cannot be read import path[0] = C:\D\dmd2\windows\bin\..\..\src\phobos import path[1] = C:\D\dmd2\windows\bin\..\..\src\druntime\import C:\D\dmd2\sources>
Re: Error: module `hello` is in file 'hello.d' which cannot be read
On Saturday, 5 May 2018 at 12:26:20 UTC, Bauss wrote: Try to add module hello; To the top of the file Still not working. I tryed both module hello; and module 'hello'; C:\D\dmd2\sources>dmd hello.d Error: module `hello` is in file 'hello.d' which cannot be read import path[0] = C:\D\dmd2\windows\bin\..\..\src\phobos import path[1] = C:\D\dmd2\windows\bin\..\..\src\druntime\import C:\D\dmd2\sources>
Re: Error: module `hello` is in file 'hello.d' which cannot be read
On Saturday, 5 May 2018 at 17:13:08 UTC, IntegratedDimensions wrote: You need to make sure hello.d is in the current dir dir C:\D does hello.d show up? If not, then dmd can't find it and you have to tell it where it is or be in the right location. type dmd ThereIsNowFileHere12342123242231231412.d and you will get the same error message. You have to be right. I removed the directory and started making de hello world file again and now it works. Thank you to everyone? Alex
pointer to object resolution
Hi all, I'm sure, I didn't find something obvious, but: Given this: ´´´ void main() { auto s = S(); s.operator; assert(s.myOp(42)); assert(42 in s); auto sptr = new S(); sptr.operator; assert(sptr.myOp(42)); //assert(42 in sptr); //<-- does not compile } struct S { void operator() const { assert(true); } bool opBinaryRight(string op)(size_t input) const if(op == "in") { return true; } bool myOp(size_t input) { return input in this; } } ´´´ The last line in the main does not compile with the message source/app.d(9,9): Error: incompatible types for `(42) in (sptr)`: `int` and `S*` This behaves differently, w.r.t. to an arbitrary method, like "operator". Why? Is there any workaround?
Re: pointer to object resolution
On Friday, 11 May 2018 at 15:24:08 UTC, Steven Schveighoffer wrote: On 5/11/18 8:53 AM, Alex wrote: This behaves differently, w.r.t. to an arbitrary method, like "operator". Why? Is there any workaround? operators don't follow pointers. Imagine if you had a struct that overloads "+" and then you wanted to use pointer arithmetic, but instead it called ptr.opBinary. Ah! The workaround is to dereference the pointer. e.g. 42 in *sptr; -Steve Thanks a lot!
Re: Can I infer the type from this?
On Sunday, 20 May 2018 at 01:41:03 UTC, Dr.No wrote: I'd like to pass a symbol as paramater (class static member0 and at same time get the type of this, something like this: template myTemp(alias s) { enum myTemp = templateFunction!(??)(s.stringof); } the templateFunction has this signature: int templateFunction(T)(string targetMembername) but I don't how to get the type name from the give symbol name in myTemp. Can I make this work? Something like this? ´´´ import std.stdio; void main() { size_t s; auto res = myTemp!s; } template myTemp(alias s) { enum myTemp = templateFunction!(typeof(s))(s.stringof); } int templateFunction(T)(string targetMembername) { static assert(is(T == size_t)); assert(targetMembername == "s"); return 42; } ´´´
Re: Can I infer the type from this?
On Sunday, 20 May 2018 at 03:16:39 UTC, Dr.No wrote: Oh, my bad: I totally forgot a crucial thing on question: I want this to work with a static member, for example, call myTemp like this myTemp!(C.a) I don't mind if I to pass the type as parameter somehow, like myTemp!(C, C.a) or myTemp!(C)(C.a) but I do need to pass a symbol as parameter, hence I'm using alias template parameter. Still not sure, if I get you right... ´´´ import std.stdio; void main() { auto res = myTemp!(C.s); } class C { static size_t s; } template myTemp(alias s) { enum myTemp = templateFunction!(typeof(s))(s.stringof); } int templateFunction(T)(string targetMembername) { static assert(is(T == size_t)); assert(targetMembername == "s"); return 42; } ´´´ In general, I'm not sure, how you want to get a type of a general symbol (this is what templateFunction should do, isn't it?) as it could be a template or a value parameter for example. However, I tried these cases, and typeof yields something reasonable then. In particular, it still did compile and yields something which could be checked against...
Re: Locking data
On Tuesday, 22 May 2018 at 21:45:07 UTC, IntegratedDimensions wrote: an idea to lock data by removing the reference: class A { Lockable!Data data; } The idea is that when the data is going to be used, the user locks the data. The trick here is that data is a pointer to the data and the pointer is set to null when locked so no other data can use it(they see a null reference). To unlock, the data is reassigned: auto d = data.lock(); // A.data is now null deals with sync issues //use d d = data.unlock(d); // restores A.data (A.data = d;) and sets d to null so any future reference is an error(could produce bugs but should mostly be access violations) Anyone else trying to use data will see that it is null while it is locked. This basically pushes the standard locking mechanisms in to the Lockable!data(first come first serve) and code that has not captured the data see's it simply as null. Anyone use know if there exists an idiom like this and what it is called? Maybe some idiomatic code that is efficient? Ideally I'd want to be able to treat the Lockable!Data as Data. Right now I have to classes(or pointers to structs) and few weird hacks. I think what I'll have to end up doing is having a Locked!Data structure that is returned instead or use an UFCS. The idea being to attach the lock and unlock methods. Are you aware of NullableRef? https://dlang.org/library/std/typecons/nullable_ref.html Does it fit somehow?
each & opApply
This is a question is about usage of ´each´ https://dlang.org/phobos/std_algorithm_iteration.html#each with a type where different opApply overloads are defined. Say, I have something like this: ´´´ void main() { import std.stdio : writeln; import std.algorithm : each; auto c = Container(); c.arr1.length = 50; c.arr2.length = 5; c.each!((a, b) => writeln(a, b)); //c.each!(a => writeln(a)); // why this line does not compile? } struct El1{} struct El2{} struct Container { El1[] arr1; El2[] arr2; //http://ddili.org/ders/d.en/foreach_opapply.html int opApply(int delegate(ref El1, ref El2) operations){ assert(0); } int opApply(int delegate(ref El2) operations){ assert(0); } int opApply(int delegate(ref El1) operations){ assert(0); } int opApply(int delegate(ref El2, ref El1) operations){ assert(0); } } ´´´ The compilation error on the last line in the main is: /usr/local/opt/dmd/include/dlang/dmd/std/algorithm/iteration.d(966,21): Error: template `D main.__lambda2` cannot deduce function from argument types `!()(El1, El2)`, candidates are: source/app.d(12,13):`app.main.__lambda2` source/app.d(12,6): Error: template instance `app.main.each!((a) => writeln(a)).each!(Container)` error instantiating So... I get the idea, that ´each´ looks only on the first opApply overload, right? Is there any possibility, to convince it to use a specific one? Say, for the last line in the main, to use the third overload of opApply? By the way, iterating via foreach works as expected: each of ´´´ foreach(El1 el; c){} foreach(El2 el; c){} foreach(El1 el1, El2 el2; c){} foreach(El2 el1, El1 el2; c){} ´´´ compiles and iterates as it should.
Re: each & opApply
On Wednesday, 23 May 2018 at 13:49:45 UTC, Steven Schveighoffer wrote: Right, but not foreach(el1, el2; c), which is the equivalent of your each call. Yes. I tried this in the first place and get a compiler error. But it seemed logical to me, that if I define two opApply overloads, which both matches two arguments, then I need to specify which one I want to use. I achieved this by specifying the types inside the foreach... concisely enough for me :) So... I'm looking how to do the same with ´each´, as defining the type of the lambda didn't help.
Re: each & opApply
On Wednesday, 23 May 2018 at 14:19:31 UTC, Steven Schveighoffer wrote: On 5/23/18 9:59 AM, Alex wrote: On Wednesday, 23 May 2018 at 13:49:45 UTC, Steven Schveighoffer wrote: Right, but not foreach(el1, el2; c), which is the equivalent of your each call. Yes. I tried this in the first place and get a compiler error. But it seemed logical to me, that if I define two opApply overloads, which both matches two arguments, then I need to specify which one I want to use. I achieved this by specifying the types inside the foreach... concisely enough for me :) So... I'm looking how to do the same with ´each´, as defining the type of the lambda didn't help. In your example, you did not define the types for the lambda (you used (a, b) => writeln(a, b) ). But I suspect `each` is not going to work even if you did. Yep. Tried this... In essence, `each` does not know what the lambda requires, especially if it is a typeless lambda. So it essentially needs to replicate what foreach would do -- try each of the overloads, and if one matches, use it, if none or more than one matches, fail. I suspect it's more complex, and I'm not sure that it can be done with the current tools. But it's definitely a bug that it doesn't work when you specify the types. Ah... ok. Then, let me file a bug...
Re: each & opApply
On Wednesday, 23 May 2018 at 14:24:18 UTC, Alex wrote: Ah... ok. Then, let me file a bug... Bug filed. https://issues.dlang.org/show_bug.cgi?id=18898
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";");
Re: Any way to override base type with dervived in derived type
On Thursday, 24 May 2018 at 20:24:32 UTC, IntegratedDimensions wrote: class T; class TT : T; interface I { @property T t(); } abstract class A { T _t; @property T t() { return _t; } } class C : A { // Stuff below uses t as TT but compiler, of course, treats t as T ... } The issue is that I programmed the class C with a variable that directly was based off TT, I later subderived T from TT and exposed it in I. (TT was refactored in to T and not T) As as a side note: I can hardly follow this, as you don't show, where you use the interface I. However, especially if TT was refactored in such a way, that is a set difference of T and not T, why you choose to derive from T instead of to contain T? https://en.wikipedia.org/wiki/Composition_over_inheritance http://wiki.c2.com/?CompositionInsteadOfInheritance Well, can imagine useful cases though... But all the code in C assumes t is of type TT but now due to the interface it looks like a T, even though internally it is actually a TT. What I'd like to do is class C : A { private override @property TT t() { return cast(TT)(_t); } // null check if necessary // Stuff below uses t which is now a TT ... } or whatever. This is simply so I don't have to rename or cast all my uses of t in C to type TT. I'm pretty much guaranteed that in C, t will be type TT due to the design(C goes with TT like bread with butter). So, it would be nice if somehow I could inform the type system that in C, t is always of type TT and so treat it as such rather than forcing me to explicitly cast for every use. Again, I could rename things to avoid the same name usage but in this case it is not necessary because of the design. Is there any semantics that can get me around having to rename? Maybe, you are looking for Curiously Recurring Template Pattern? ´´´ interface I(P) { @property P t(); } abstract class T(P) : I!P { P _p; @property P t() { return _p; } } class TT : T!TT { } void main() { auto tt = new TT(); static assert(is(typeof(tt.t) == TT)); } ´´´
Re: range simple toy problem
On Friday, 1 June 2018 at 17:00:45 UTC, Xiaoxi wrote: import std.range; import std.algorithm; import std.string; import std.stdio; void main() { auto s = "1 2 3 4 5 6 7 8 9"; auto iter = s.split(" ").drop(2); // How to find the unconsumed/not-split part of s here? // i.e. "3 4 5 6 7 8 9" NOT ["3", "4", "5", "6", "7", "8", "9"] // s[??? .. $] <- what goes here? } split is just an example, it's a generic question if you chain multiple lazy functions and then consume a part of the data... how do you know how to slice the original buffer to point to the unconsumed data? Imagine the chain could be quite long s.one.two.three.four.five.six.seven() You don't really want to lazily add the inverse of all the functions and they might even be destructive so it might not be possible in all cases. Split is already destructive, as you loose the whitespaces. In this special case, maybe by iter.join(" "); https://dlang.org/library/std/array/join.html In case the the separator can't be known in advance, I would choose to store it somehow... Maybe by https://dlang.org/library/std/algorithm/searching/find_split.html ?
Re: determining if array element is null
On Tuesday, 5 June 2018 at 14:52:28 UTC, Timoses wrote: Does `int[4] nums = void` work? Work for what? If you avoid initialization, then the variable(s) are not initialized. https://dlang.org/spec/declaration.html#void_init However, an int is not nullable and always contains a value.
comparing nullables
Hi all, do you see any valid reason why the last line yields an error: import std.typecons; void main() { void* ptr1; void* ptr2; assert(ptr1 is null); assert(ptr2 is null); assert(ptr1 == ptr2); Nullable!uint val1; Nullable!uint val2; assert(val1.isNull); assert(val2.isNull); assert(val1 == val2); Nullable!(uint, uint.max) val3; Nullable!(uint, uint.max) val4; assert(val3.isNull); assert(val4.isNull); assert(val3 == val4); } The error is core.exception.AssertError@/usr/local/opt/dmd/include/dlang/dmd/std/typecons.d(3457): Called `get' on null Nullable!(uint,nullValue). As I can see, this is due the lack of opEquals in the Nullable(T, T nullValue), in contrast to Nullable(T).
Re: comparing nullables
On Friday, 15 June 2018 at 16:49:47 UTC, bauss wrote: https://github.com/dlang/phobos/pull/6583 Thanks a lot.
template recursion
Hi all, I have a strange case of template recursion, which I don't know how to solve: ´´´ import std.range; void main() { T.member.tarr.length = 42; //put(T.member, 4); // line 6 T.member.put(4); // line 7 } struct T { void put(Type)(Type t){} // line 13 static B member; } struct B { T[] tarr; void put(Type)(Type t) { put(tarr[t], t); // line 23 } } ´´´ Line 7 complains about: template app.B.put cannot deduce function from argument types !()(T, int) So, I see, that the compiler tries to use the same put function in line 23, as in line 7 and fails. Instead of this, I want to use the one in line 13. But I don't see any mistake at line 23... Besides this, as a secondary question: using line 6 does not yield any helpful debugging message. My put functions are templates and pretty long and branching, and I'm trying to debug them somehow, but using idiomatic writing all I get as a message is something like "Cannot put a XX into a YY." :(
Re: template recursion
On Tuesday, 26 June 2018 at 10:01:06 UTC, ag0aep6g wrote: On line 23, you're apparently trying to call std.range.put (which would in turn call tarr[t].put). But being in a method that is itself called "put", that line is instead interpreted as a recursive call (which fails). To refer to std.range.put, you have to prepend a dot (the "module scope operator"): .put(tarr[t], t); // line 23 https://dlang.org/spec/module.html#module_scope_operators Ah... that's cool :) Thanks a lot!
Re: anyway to pass the context of an inner type to a template so it can be constructed?
On Wednesday, 27 June 2018 at 12:02:10 UTC, aliak wrote: === The use case is for a non-nullable type, where I want to guarantee that the value inside will never be null. I can't do it for inner classes though. And I can't allow the user to do something like: void main() { class C {} auto s = construct(new C); } Because I can't guarantee that's not null. Cheers, - Ali Is there any reason, why you don't want to use a struct? An instance of such is never null, still having access to its context, if it is a function.
Re: Getting the underlying range from std.range.indexed, with elements in swapped order, when Indexed.source.length == Indexed.indices.length
On Wednesday, 27 June 2018 at 13:27:46 UTC, Uknown wrote: Title says it all. Is there a trivial way to do this? There are https://dlang.org/library/std/algorithm/mutation/reverse.html and https://dlang.org/library/std/range/retro.html both require a bidirectional range, which Indexed, luckily is.
Re: Getting the underlying range from std.range.indexed, with elements in swapped order, when Indexed.source.length == Indexed.indices.length
On Wednesday, 27 June 2018 at 14:29:33 UTC, Uknown wrote: On Wednesday, 27 June 2018 at 14:21:39 UTC, Alex wrote: On Wednesday, 27 June 2018 at 13:27:46 UTC, Uknown wrote: Title says it all. Is there a trivial way to do this? There are https://dlang.org/library/std/algorithm/mutation/reverse.html and https://dlang.org/library/std/range/retro.html both require a bidirectional range, which Indexed, luckily is. I wasn't clear enough. I meant getting back the underlying `Source` range with _its_ elements in the order that the indices specify. This wouldn't be possible in the generic case, but the special case when indices.length == source.length, it should be possible. So indexed(myRange, [2, 3, 5, 1, 4]).sourceWithSwappedElements should return a typeof(myRange) with the elements swapped in that order. I see. Ok, one possibility is source = indexed(source, indices).array; but I assume you want something without extra allocation, right?
Re: Getting the underlying range from std.range.indexed, with elements in swapped order, when Indexed.source.length == Indexed.indices.length
On Wednesday, 27 June 2018 at 15:07:57 UTC, Uknown wrote: On Wednesday, 27 June 2018 at 14:50:25 UTC, Alex wrote: On Wednesday, 27 June 2018 at 14:29:33 UTC, Uknown wrote: On Wednesday, 27 June 2018 at 14:21:39 UTC, Alex wrote: On Wednesday, 27 June 2018 at 13:27:46 UTC, Uknown wrote: [...] I see. Ok, one possibility is source = indexed(source, indices).array; but I assume you want something without extra allocation, right? This doesn't work for some reason. "123".byCodeUnit.permutations.array.writeln //[123, 123, 123, 123, 123, 123] This would: ["123".byCodeUnit.permutations].joiner.writeln;
Re: Why tuples are not ranges?
On Thursday, 28 June 2018 at 14:35:33 UTC, Mr.Bingo wrote: Seems like it would unify things quite a bit. Yeah... this is, because you can't popFront on a tuple, as the amount of entries is fixed. You can, however, popFront on every range. But as Timoses wrote you can easily make a range out of a tuple, for example by slicing: ´´´ import std.typecons, std.range, std.array, std.algorithm, std.stdio; void main() { auto t = tuple(3,4,5,6); auto m = [t[]]; writeln(m.map!(a => 3*a).sum()); } ´´´
Re: Why tuples are not ranges?
On Thursday, 28 June 2018 at 19:02:51 UTC, Ali Çehreli wrote: On 06/28/2018 11:08 AM, Mr.Bingo wrote: > Thanks, why not add the ability to pass through ranges and arrays and > add it to phobos? Makes sense. It needs an enhancement request at http://issues.dlang.org/, a good implementation, and a pull request. :) Ali Wouldn't this be weird from the semantic view? Assume, I define a tuple with named fields "key" and "value", where a popFront is defined. Now, I use popFront. Is the "key" field still available? Why? Or, why not? What happens, if I name a field of a tuple "front"? Is it available after using popFront? And where does it point to? I mean, I use something similar in my own project, but doesn't one has to make a clear distinction between a container and a slice of this container? Or should static arrays be unified in the same manner?
Re: Function Template for Dynamic Parameter
On Sunday, 1 July 2018 at 11:19:50 UTC, vino.B wrote: Hi Timoses, Thank you very much, can you help me on how to rewrite the below using Variadic template Passing function as a parameter to another function: void ptFun(T)(T function(string, string, int) coRoutine, Array!string Dirlst, ) { alias scRType = typeof(coRoutine(string.init, string.init, int.init)); where the "function(string, string, int) coRoutine" should be a variadic function From, Vino.B I'm not sure, if get your question right, is this what you are looking for? ´´´ import std.stdio; import std.traits; void main() { alias instantiation = ptFun!(size_t, fun!string); instantiation(4); alias instantiation2 = ptFun2!(fun!string); instantiation2(4); } auto fun(T...)(T input) { return size_t(42); } void ptFun(T, alias funToCall)(size_t definedParam) if(is(T == ReturnType!(funToCall))) { "ptFun called".writeln; assert(42 == funToCall("some string")); } void ptFun2(alias funToCall)(size_t definedParam) if(__traits(isSame, TemplateOf!(funToCall), fun)) { "ptFun2 called".writeln; assert(42 == funToCall("some string")); } ´´´
Re: ranges.chunks and map! does not work
On Thursday, 5 July 2018 at 09:47:32 UTC, Andre Pany wrote: Is it correct that I need to call ".map!(c => c.array)"? Kind regards André Well, no. It depends on how you define the formatting string. This would also work: ´´´ import std.experimental.all; void main() { double[] timestamps = [1.1]; double[] temperatures = [2.2]; double[] pressures = [3.3]; string content = roundRobin(timestamps, temperatures, pressures) .chunks(3) //.map!(c => c.array) .map!(c => "%(%g,%)".format(c)) .join("\n"); writeln(content); } ´´´
Re: 'is(T==return)' How does is expression with return keyword as TypeSpecialization
On Thursday, 5 July 2018 at 10:32:01 UTC, Timoses wrote: int fun(T)(T i) { static assert(is(typeof(return) == T)); //true pragma(msg, is(T == return)); // false static if (is(T ReturnType == return)) pragma(msg, ReturnType); // does not enter return i; } unittest { fun(3); } What's the purpose of 'is(T == return)' if not the above? I always thought that "return" is a keyword. https://dlang.org/spec/lex.html#keywords And the fact, that you can ask the keyword about its type is just a nice feature... ;)
Re: 'is(T==return)' How does is expression with return keyword as TypeSpecialization
On Thursday, 5 July 2018 at 11:37:16 UTC, Timoses wrote: I think it refers to this section: https://dlang.org/spec/expression.html#is_expression I don't remember where I read this usage (think it was in a book), but I noted it down and now I wonder how it can be used. I saw some usage cases, which are like "opposites" to auto fun() declarations: So either you can declare ´´´ auto fun() { int retVal; ... return retVal; } ´´´ or ´´´ int fun() { typeof(return) retVal; ... return retVal; } ´´´
Re: Outside array bounds
On Saturday, 7 July 2018 at 08:09:51 UTC, vino.B wrote: Hi All, Request you help, on the below code import std.stdio: writeln; void process(T ...)(string ID, T args) { if (ID == "I1") { writeln(args.length, "\t", args[0]); } else if (ID == "I2") { writeln(args.length, "\t", args[1]);} } void main() { string S1 = "Test1", S2 = "Test2", ID1 = "I1", ID2 = "I2"; int Size = 1; process(ID1, S1); process(ID2, S2, Size); } Error: Test.d(5): Error: array index [1] is outside array bounds [0 .. 1] Test.d(11): Error: template instance `Test.process!string` error instantiating From, Vino.B Ok, the problem here is, that as args (and especially its length) are known at compile time, args are checked for having enough length in all cases of the run time parameter. My question would be, why do you need the ID string, if you know what to print from the length of args? ´´´ void process2(T ...)(string ID, T args) { static if(args.length == 1) { if (ID == "I1") { writeln(args.length, "\t", args[0]); } } else static if(args.length == 2) { if (ID == "I2") { writeln(args.length, "\t", args[1]); } } } void main() { string S1 = "Test1", S2 = "Test2", ID1 = "I1", ID2 = "I2"; int Size = 1; process2(ID1, S1); process2(ID2, S2, Size); } ´´´
Re: Outside array bounds
On Saturday, 7 July 2018 at 08:24:21 UTC, Timoses wrote: Interesting.. Looks like the compiler does some boundschecking during compile time. You could circumvent this: void process(T ...)(string ID, T args) { if (ID == "I1") { writeln(args.length, "\t", args[0]); } static if (T.length > 1) // only add below code if cond. true if (ID == "I2") { writeln(args.length, "\t", args[1]);} } Oddly, when leaving out the "static if" statement, the error still occurs when compiling with "-release" or with "-boundscheck=off"... I thought those would/should disable bounds checking at compile time??? Nonono )) In this case, the bound checks are like interface checking... or like type checking... As there are different processes instantiations for different number of args. I hope this can't be turned off so easily...
Re: Outside array bounds
On Saturday, 7 July 2018 at 11:22:38 UTC, Timoses wrote: Aw, got it. So args is actually a tuple type where accessing beyond the defined tuple (T) is invalid? auto a = [1, 2, 4]; // works pragma(msg, typeof(a[3])); auto t = tuple(3, 4, 5.3); // ERROR: // pragma(msg, typeof(t[3])); Yes. The absence of the next element in the array, doesn't matter, while asking its type, while the absence of the next tuple element means also the absence of any type, as I understand it.
Re: guard clause style static if
On Saturday, 7 July 2018 at 12:54:03 UTC, kdevel wrote: On Saturday, 7 July 2018 at 12:46:08 UTC, rikki cattermole wrote: On 08/07/2018 12:40 AM, kdevel wrote: Interesting alternative That was not an alternative. That is what your code was doing. What my original code was supposed to do. But it did not compile. Error: array index [0] is outside array bounds [0 .. 0] Error: string slice [1 .. 0] is out of bounds My question is if it is intentionally failing to compile a static if guard clause. The site you cited for the guard clause above (c2.com) works at runtime. The intention is to shorten the paths inside a function, I think. Therefore, a static "guard clause" is a contradiction, if I understand it correctly. The constraint in form fun(...)(...) if(...) is a static construct. Therefore, all parts should be mentioned statically. And by https://dlang.org/spec/version.html#staticif paragraph: 24.5.4.2 a static if does not introduce a new scope. So, the argument about arrow code is not valid here.
Re: Passing function(whose parameter would be dynamic and the type is unknown) as a parameter to another function.
On Sunday, 8 July 2018 at 18:46:31 UTC, vino.B wrote: Request you help, in the below code we pass the function "Testfun" as a parameter to another function "process" in order for the function "process" to work we have to specify the type of the parameter that is passed to the function "(T function(string, int) coRoutine, string Test, int Size) ", so now how do we pass a function whose parameter would be dynamic and the type is unknown. What do you mean with a "function with dynamic parameters" and "unknown type"? But how about ´´´ void main() { process!fun(); } void process(alias coRoutine, T...)(T params) { coRoutine(params); } auto fun(T...)(T params) { } ´´´
Re: Passing function(whose parameter would be dynamic and the type is unknown) as a parameter to another function.
On Monday, 9 July 2018 at 15:40:53 UTC, vino.B wrote: On Sunday, 8 July 2018 at 19:10:24 UTC, Alex wrote: On Sunday, 8 July 2018 at 18:46:31 UTC, vino.B wrote: Request you help, in the below code we pass the function "Testfun" as a parameter to another function "process" in order for the function "process" to work we have to specify the type of the parameter that is passed to the function "(T function(string, int) coRoutine, string Test, int Size) ", so now how do we pass a function whose parameter would be dynamic and the type is unknown. What do you mean with a "function with dynamic parameters" and "unknown type"? But how about ´´´ void main() { process!fun(); } void process(alias coRoutine, T...)(T params) { coRoutine(params); } auto fun(T...)(T params) { } ´´´ HI Alex, I tried you method, but it not working as expected, the process!fun1(Test1) works but the process!fun2(Test1, Size ) does not work, instead of displaying the value (Test, 1) it output's the parameter "Test1". Output: Test Test1 If I comment process!fun1(Test1); then the output is same Output : Test1 import std.stdio: writeln; void main() { string Test1 = "Test"; int Size = 1; process!fun1(Test1); process!fun2(Test1, Size ); } void process(alias coRoutine, T...)(T params) { coRoutine(params); } auto fun1(T...)(T params) { writeln(params); } auto fun2(T...)(T params) { writeln(params); } From, Vino.B As I can see, this is the expected output. The "1" after "Test" is the value of parameter "Size"...
Re: Passing function(whose parameter would be dynamic and the type is unknown) as a parameter to another function.
On Monday, 9 July 2018 at 17:26:30 UTC, vino.B wrote: Request Help: void process(alias coRoutine, T...)(Array!string Dirlst, T params) { ReturnType!coRoutine rData; / This line is not working alias scRType = typeof(coRoutine(string.init, T.init)); auto PFresult = taskPool.workerLocalStorage!scRType(); foreach (string FFs; parallel(Dirlst[],1)) { PFresult.get ~= coRoutine(FFs, params); } foreach(i; PFresult.toRange) { rData ~= i[][]; } } Error: test.d(206): Error: template instance `std.traits.ReturnType!(coAgedDirClean)` does not match template declaration ReturnType(func...) if (func.length == 1 && isCallable!func) Yeah... for ReturnType to work, you need a function, but you have only a template. The easy solution is to execute the template and to ask the result for its type: ´´´ void main() { process!fun(); } void process(alias coRoutine, T...)(T params) { auto res = coRoutine(params); pragma(msg, typeof(res)); } auto fun(T...)(T params) { return 42; } ´´´ If you need it in advance... It is a little bit longer. There was a place, where I used this once... See https://run.dlang.io/is/Xy6Xf4 However, I wonder why you need this, especially as your process is void. Why not just using auto for results of the coroutines?
Re: Passing function(whose parameter would be dynamic and the type is unknown) as a parameter to another function.
On Tuesday, 10 July 2018 at 14:38:03 UTC, vino.B wrote: Hi Alex, The reason the I am storing the output of "PFresult.toRange" to another array "rData" is that the output of the PFresult.toRange is different each time we execute the code.(Data is correct) but the way the it output is different. Is there any way to get the result in a single array - Whole Data. Single array - Whole Data ["C:\\Temp\\TEAM1\\Test Result-Team1.docx", 2018-Jun-28 17:37:45.9376229, "C:\\Temp\\TEAM2\\Test Result-Team2.docx", 2018-Jun-28 17:37:45.9376229, "C:\\Temp\\SAPNAS3\\TEAM3\\Test Result-Team3.docx", 2018-Jun-28 17:37:45.9376229 ] One array - For Each Data [ C:\\Temp\\TEAM1\\Test Result-Team1.docx", 2018-Jun-28 17:37:45.9376229] - arr1 [ C:\\Temp\\TEAM2\\Test Result-Team2.docx", 2018-Jun-28 17:37:45.9376229] - arr2 [ C:\\Temp\\TEAM3\\Test Result-Team3.docx", 2018-Jun-28 17:37:45.9376229] - arr3 The code in the program. foreach(i; PFresult.toRange) { rData ~= i[][]; } if (!rData[].empty) { rData[].sort!((a,b) => a[1] < b[1]).each!(e => logF.writefln!"%-83s %.20s"(e[0].replace(`\\?\`, ""), e[1].to!string)); } From, Vino.B Not sure, if I get your point, but are you aware of tuples? https://dlang.org/phobos/std_typecons.html#tuple
Re: Check whether a range is empty
On Tuesday, 17 July 2018 at 13:59:45 UTC, Gary Willoughby wrote: I thought every range at the lowest level has an `empty` property. So, in this case, it would be: if (PFResutl.toRange.empty) { writeln("Empty"); } Yeah, but it seems, that PFResutl is a range of ranges, and the OP has the case, where both of the contained ranges are empty. However, this does not correspond to empty of the governing range. So [[], []].empty is false whereas [[], []].joiner.empty is true.
Re: HMAC and toHexString
On Wednesday, 18 July 2018 at 05:54:48 UTC, Nicholas Wilson wrote: ... string key = "blahblahblah"; auto mac = hmac!SHA256(key.representation); string s = ...,t=...u=...,v=...; foreach(w;AliasSeq!(s,t,u,v)) mac.put(w.representation); ubyte[32] s = mac.finish; string sig = toHexString!(LetterCase.lower)(s); writeln(sig); // From what I understand Should print something like 41771e2d0d6c1cf7f442aa8547783ea5b126bfc15a4b354e94d0eaea2ab0fa1a // Actually prints something like x"31 36 39 33 39 32 38 31 62 38 31 62 36 36 62 63 63 34 63 36 36 61 62 32 34 37 64 32 64 34 61 00 78 2A 55 5B FF 7F 00 00 78 2A 55 5B FF 7F 00 00 E0 2A 55 5B FF 7F 00 00 08 2C 55 5B FF 7F 00 00"c Note the nuls and things like FF What am I doing wrong here? Don't know, what you mean. Works for me: ´´´ import std.stdio; import std.digest.hmac; import std.digest.sha; import std.string; import std.meta; void main() { string key = "blahblahblah"; auto mac = hmac!SHA256(key.representation); string s = "...",t="...", u="...",v="..."; foreach(w;AliasSeq!(s,t,u,v)) mac.put(w.representation); ubyte[32] r = mac.finish; r.toHexString!(LetterCase.lower).writeln; } ´´´ output: dc84632fc9b5d1f4b879d9aa021ae0d089e7f66a2fd2e824829cfceedbece729
merging a group result
Hi all, I'm looking for a d-ish way to solve a basic "split-apply-combine" workflow. The idea is described (and solved) here: https://stackoverflow.com/questions/39922986/pandas-group-by-and-sum So, given a structure with some fields, say ´´´ struct S { string s; int i; } ´´´ I create an array of them, like ´´´ void main() { import std.experimental.all; S[] sarr; sarr.length = 6; sarr[0].s = "a"; sarr[1].s = "a"; sarr[2].s = "b"; sarr[3].s = "b"; sarr[4].s = "c"; sarr[5].s = "c"; sarr[0].i = 1; sarr[1].i = 2; sarr[2].i = 4; sarr[3].i = 8; sarr[4].i = 16; sarr[5].i = 32; auto res = sarr.group!((a, b) => a.s == b.s); //writeln(res); } ´´´ I'm also able to group them by a field, see last line. But now the problems begin: - The group operation tries to use the structure itself as a key, despite I provide a custom binary predicate. - I could ignore the fact above, but how, given the result of the grouping operation I can merge by some function (like sum) the group results? At this moment, I assume, that I'm approaching the problem from the wrong end, and simply don't see something trivial... Anyway, does anybody has a hint for me?
Re: merging a group result
On Monday, 23 July 2018 at 12:07:37 UTC, Seb wrote: You could use chunkBy: auto res = sarr.chunkBy!((a, b) => a.s == b.s).map!(a => tuple(a.front.s, a.map!(b => b.i).sum)); https://run.dlang.io/is/TJOEmf Ha... This helps! Thanks a lot! :)
Re: trait to get the body code of a function?
On Thursday, 26 July 2018 at 07:32:19 UTC, Mr.Bingo wrote: If all you need is the string you can write a template function that imports the file and searches for the function and returns it's body. It's not very robust but it can work for some cases. D really should allow one to get the function body in D, possibly in a type safe way(such as each line is parsed properly and return type info about what the line contains. I would argue, just because of "type safety" you mentioned, D should not allow one to get the function body. The type safety is not achievable because of https://en.wikipedia.org/wiki/Lambda_calculus#Undecidability_of_equivalence The string itself could be useful however... Whatever OP has in mind with this string...
Re: trait to get the body code of a function?
On Thursday, 26 July 2018 at 11:54:39 UTC, Mr.Bingo wrote: The string itself could be useful however... Whatever OP has in mind with this string... Having a code block is useful in many ways simply because not having it is the most limiting case. If one doesn't have it and requires it then it is impossible for them to do what they want. If one does have it and has no need, then no loss. Lots of people like to err on the side of "caution" which is really the side of limitations and frustrations and laziness. Of course, sometimes things should be limited, but I think this is probably not one of those cases(I see no harm in allowing meta code to get a function body and, say, create another function based off it but a slight change. For example, one could mutate algorithms and run genetics algorithms on them to see how function scan evolve. This might lead to genetic ways to assemble programs. In any case, one can't do it since one can't get at a functions body. For example, maybe one wants a way to debug a mixin: mixin("int x;"); <- can't debug void foo() { int x; } mixin(funcBody!foo) <- can debug since we defined foo outside of the mixin and the compiler see's it naturally. I'm with you in this part. I would argue, just because of "type safety" you mentioned, D should not allow one to get the function body. The type safety is not achievable because of https://en.wikipedia.org/wiki/Lambda_calculus#Undecidability_of_equivalence What the hell does that have to do with anything? I don't know what you are talking about when it comes to "type safety" and equivalence. What I am talking about is being able to parse the function body in a type safe way rather than having to hack strings or write a D parser oneself. Instead of "int x;" one has > or whatever the parser parses in to(some type of AST). I'll try to reformulate this. Take the example given at https://dlang.org/spec/function.html#closures Paragraph 2. Now, examine the contents of functions abc and def. Does the functionality differ? For sure not. Does the compiler knows it? It is not guaranteed. The article I cited and the literature behind it state, that in general, an equivalence of function contents can not be tracked. However, to state for a function to be equal with another function exactly this is needed. And I thought you meant this by "type safety"...
Re: Question about template argument matching with alias this
On Sunday, 29 July 2018 at 16:43:08 UTC, Johannes Loher wrote: I have a question about template argument matching in combination with implicit conversion and alias this. Consider the following code: interface SomeInterface { } class SomeClass : SomeInterface { } struct SomeStruct { SomeClass someClass; alias someClass this; } template isSuperType(T, S : T) { enum isSuperType = is(SomeStruct : SomeInterface); } void main() { static assert(is(SomeStruct : SomeInterface)); static assert(isSuperType!(SomeInterface, SomeStruct)); // why does the template not match? } The question is, why does the template declaration not match? Thanks for your help! Do you mean something like this? ´´´ interface SomeInterface {} class SomeClass : SomeInterface {} struct SomeStruct { SomeClass someClass; alias someClass this; } template isSuperType(T, S) if(is(S : T)) { enum isSuperType = is(S : T); } static assert(is(SomeStruct : SomeInterface)); static assert(isSuperType!(SomeInterface, SomeStruct)); void main(){} ´´´
Re: Newbie: out-of-source builds with "dub"?
On Monday, 30 July 2018 at 01:50:23 UTC, CC wrote: Before starting with D programming, most of my projects have configured their build systems with Autotools or CMake, and git for source control. With those systems, it's usually considered best practice to store all files generated during configuration and build to be located outside of the source tree. My usual modus operandi is: 1. check out the project into some directory "foo". 2. create another directory "foo.build", somewhere outside of "foo". 3. "cd foo.build" 4. Run some configuration script/file located in "foo", to generate "foo.build/Makefile". 5. Run "make". I've started playing with "dub", and it *seems* to assume that you want the files generated during the build process to reside directly inside your checked-out source tree. Is that true? And if so, am I fighting dub's design by attempting out-of-source builds? For example, you could define "targetPath" within the dub configuration, which points to a relative path somewhere. [1] https://code.dlang.org/package-format?lang=json
Re: Question about template argument matching with alias this
On Sunday, 29 July 2018 at 23:03:27 UTC, Johannes Loher wrote: Yeah, I know that it possible to implement the template like this, but that is not the point here. I would like to know why it does not work the way I described it. To me it seems very strange, that `S : T` has different semantics in `is` expressions and as template parameters. Yes... I see your point now. It is like "is" itself adds some semantics to the colon operator. So, while colon specifies, that only derivatives are matched, "is" matches all things, where the interface can be extracted... I think, this is intended: https://dlang.org/spec/template.html#argument_deductionp. 5 and https://dlang.org/spec/expression.html#is_expressionp. 2 But... maybe some native D speaker could comment on this... Now I could ask the author of poodinis to remove the restriction on the template parameters for register, but it actually perfectly makes sense to have that restriction, because we are registering a concrete type as an abstract type. I would say, for practical reasons not to remove the restriction, but to formulate it in a more abstract way. This seems to be with ´if(is(S : T))´ in this case... As otherwise the restriction is to use classes only... (?) So I am back to my question: Why do we have this strange behavior? All compiler version on run.dlang.io behave like that, so I suppose there is some reason for this...?
Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type?
On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote: Is this a bug? If not is there a workaround? I would like for the alias this to function as a normal A type unless B specifically disables certain features, but it seems weird that disabling one opAssign disables all of them inside the aliases type but not in the aliasing type? struct A { void opAssign(int) {} } struct B { A a; alias a this; @disable void opAssign(float); } void main() { B b; b = 3; } Error: function `onlineapp.B.opAssign` is not callable because it is annotated with @disable Cheers, - Ali What happens if you omit the @disable line?
Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type?
On Monday, 30 July 2018 at 19:33:45 UTC, aliak wrote: On Monday, 30 July 2018 at 18:47:06 UTC, Alex wrote: On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote: [...] What happens if you omit the @disable line? Compiles ok then. So... is this a valid workaround? ;)
Re: What does auto std.stdio.File.ByChunkImpl byChunk (ulong chunkSize ); mean?
On Friday, 3 August 2018 at 16:58:26 UTC, kdevel wrote: What does auto std.stdio.File.ByChunkImpl byChunk ( ulong chunkSize ); on https://dlang.org/library/std/stdio/file.by_chunk.html mean? Is that a (forward) declaration of a function named byChunk taking a single ulong argument name chunkSize. But what does that function return? The help page you cited says: "Returns an input range set up to read from the file handle a chunk at a time."
Compiler build error
I'm a little bit confused by following situation: I have code, say around 8000 lines. Now, I'm facing a build error which just says dmd failed with exit code -11, (same for ldc2, with some lines of stack information, which do not belong to my code) 0 ldc2 0x000106fcc4e7 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37 1 ldc2 0x000106fcb9ea llvm::sys::RunSignalHandlers() + 83 2 ldc2 0x000106fcc90e SignalHandler(int) + 239 3 libsystem_platform.dylib 0x7fff5992af5a _sigtramp + 26 4 libsystem_platform.dylib 0x00015fcde600 _sigtramp + 104543936 ldc2 failed with exit code -11. As I'm compiling rather often, I know exactly which line in my code causes this error. As the compiler refuses to exit normally, I'm not sure, if the line is buggy (so, whether I'm trying to compile, something, what is not compilable) or, I'm facing an ICE. In both cases, I'm ready to rewrite my code a little bit to get around the error, as I need a solution quite fast. My assumption is, that I built a kind of loop, which the compiler does not know how to get along. But in order to rewrite it, I have to know, what I have to rewrite... So, despite I know exactly the culprit line in my code, I don't have any information about how to solve the problem. What I'm trying now is to use dustmite. But this, lasts for about 8 hours now and is already at depth 20. Lacking experience with this tool, I'm not sure, if this is normal... The last time I tried to use it elsewhere, I got a final depth of 13, but also an empty file as its analysis result. The command for dustmite was dub dustmite ../dust --compiler-status=-11 --combined Yes... the builds were also done with dub. So, dub build and dub build --compiler=ldc2 respectively. Any help is appreciated :) Alex
Re: Compiler build error
On Saturday, 4 August 2018 at 12:21:36 UTC, Alex wrote: Ok. Dustmite finished. But the result is again an empty file... :(
Re: Compiler build error
On Saturday, 4 August 2018 at 13:26:01 UTC, Nicholas Wilson wrote: 0 ldc2 0x000106fcc4e7 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37 1 ldc2 0x000106fcb9ea llvm::sys::RunSignalHandlers() + 83 2 ldc2 0x000106fcc90e SignalHandler(int) + 239 3 libsystem_platform.dylib 0x7fff5992af5a _sigtramp + 26 4 libsystem_platform.dylib 0x00015fcde600 _sigtramp + 104543936 ldc2 failed with exit code -11. Is this the entire stack trace? If dmd is also affected chances it is a frontend bug. Well, on MacOs - yes. On a Linux, it is longer: /snap/ldc2/78/bin/ldc2(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x2a)[0x22914fa] /snap/ldc2/78/bin/ldc2(_ZN4llvm3sys17RunSignalHandlersEv+0x3e)[0x228f5be] /snap/ldc2/78/bin/ldc2[0x228f70c] /snap/core/current/lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fdb8258e390] /snap/ldc2/78/bin/ldc2(_D3dmd13expressionsem18functionParametersFS3dmd7globals3LocPS3dmd6dscope5ScopeC3dmd5mtype12TypeFunctionC3dmd5mtype4TypePS3dmd4root5array40__T5ArrayTC3dmd10expression10ExpressionZ5ArrayC3dmd4func15FuncDeclarationPC3dmd5mtype4TypePC3dmd10expression10ExpressionZb+0xbf3)[0xa636d3] /snap/ldc2/78/bin/ldc2(_ZN25ExpressionSemanticVisitor5visitEP7CallExp+0x35e4)[0xa6fdb4] /snap/ldc2/78/bin/ldc2(_D3dmd13expressionsem18resolvePropertiesXFPS3dmd6dscope5ScopeC3dmd10expression10ExpressionC3dmd10expression10ExpressionZC3dmd10expression10Expression+0xecc)[0xa625cc] /snap/ldc2/78/bin/ldc2(_Z17resolvePropertiesP5ScopeP10Expression+0x11)[0x917511] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP12ExpStatement+0x6d)[0xa4903d] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP14DebugStatement+0x5a)[0xa5c0fa] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6c)[0xa493cc] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xdf)[0xa4a04f] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP11IfStatement+0x686)[0xa53546] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6c)[0xa493cc] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xdf)[0xa4a04f] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP11IfStatement+0x686)[0xa53546] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6c)[0xa493cc] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP12ForStatement+0x502)[0xa4afe2] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6c)[0xa493cc] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xdf)[0xa4a04f] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP12ForStatement+0xee)[0xa4abce] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP16ForeachStatement+0x59ef)[0xa50c1f] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6c)[0xa493cc] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xdf)[0xa4a04f] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP21UnrolledLoopStatement+0x7b)[0xa49dfb] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP16ForeachStatement+0x71d)[0xa4b94d] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6c)[0xa493cc] /snap/ldc2/78/bin/ldc2(_ZN16Semantic3Visitor5visitEP15FuncDeclaration+0x1618)[0x906328] /snap/ldc2/78/bin/ldc2(_ZN15FuncDeclaration17functionSemantic3Ev+0xea)[0x98602a] /snap/ldc2/78/bin/ldc2(_ZN15FuncDeclaration16functionSemanticEv+0x27d)[0x8cd34d] /snap/ldc2/78/bin/ldc2(_D3dmd10expression7resolveFKxS3dmd7globals3LocPS3dmd6dscope5ScopeC3dmd7dsymbol7DsymbolbZC3dmd10expression10Expression+0x5fe)[0x8db2ee] /snap/ldc2/78/bin/ldc2(_ZN25ExpressionSemanticVisitor5visitEP13IdentifierExp+0x877)[0xa66a17] /snap/ldc2/78/bin/ldc2(_ZN25ExpressionSemanticVisitor5visitEP7CallExp+0xc0f)[0xa6d3df] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP12ExpStatement+0x5b)[0xa4902b] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6c)[0xa493cc] /snap/ldc2/78/bin/ldc2(_ZN16Semantic3Visitor5visitEP15FuncDeclaration+0x1618)[0x906328] /snap/ldc2/78/bin/ldc2(_ZN15FuncDeclaration17functionSemantic3Ev+0xea)[0x98602a] /snap/ldc2/78/bin/ldc2(_ZN15FuncDeclaration16functionSemanticEv+0x27d)[0x8cd34d] /snap/ldc2/78/bin/ldc2(_D3dmd10expression7resolveFKxS3dmd7globals3LocPS3dmd6dscope5ScopeC3dmd7dsymbol7DsymbolbZC3dmd10expression10Expression+0x5fe)[0x8db2ee] /snap/ldc2/78/bin/ldc2(_ZN25ExpressionSemanticVisitor5visitEP13IdentifierExp+0x877)[0xa66a17] /snap/ldc2/78/bin/ldc2(_ZN25ExpressionSemanticVisitor5visitEP7CallExp+0xc0f)[0xa6d3df] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP12ExpStatement+0x5b)[0xa4902b] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6c)[0xa493cc] /snap/ldc2/78/bin/ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xdf)[0xa4a
Re: Compiler build error
On Saturday, 4 August 2018 at 13:29:36 UTC, kinke wrote: You're most likely hitting an ICE in the front-end (as both compilers crash). What you can always do is invoke the compiler in a GDB session. That's especially useful with an LDC CI build (download: https://github.com/ldc-developers/ldc/releases/tag/CI), as it features debuginfos and enabled LLVM/LDC assertions. Please file an issue once you narrowed it down a little, ideally with a small reproducible test case. Ok... the longest part was: how to get the compilation string from dub :) so, got the equivalent to dub build (with dmd) started with gdb under Ubuntu and received after 10-20 seconds: Program received signal SIGSEGV, Segmentation fault. 0x006045ce in _D3dmd13expressionsem18functionParametersFSQBp7globals3LocPSQCg6dscope5ScopeCQCx5mtype12TypeFunctionCQDvQy4TypePSQEh4root5array__T5ArrayTCQFg10expression10ExpressionZQBkCQGm4func15FuncDeclarationPQDsPQClZb () I'm not sure, how to shorten my code at this moment... So, if the traces don't help, let me know, I would spend some more time on this...
Re: Compiler build error
On Saturday, 4 August 2018 at 22:50:49 UTC, kinke wrote: On Saturday, 4 August 2018 at 18:12:05 UTC, Alex wrote: /snap/ldc2/78/bin/ldc2(_start+0x29)[0x8b7ee9] You haven't specified the DMD version you are using. Your LDC is 'outdated', so make sure to first check whether it still fails with an up-to-date version before potentially wasting time. DMD64 D Compiler v2.081.1 and the output for LDC - the LLVM D compiler (1.8.0): based on DMD v2.078.3 and LLVM 5.0.1 built with LDC - the LLVM D compiler (0.17.5) is: /usr/lib/x86_64-linux-gnu/libLLVM-5.0.so.1(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x2a)[0x7fb1945551fa] /usr/lib/x86_64-linux-gnu/libLLVM-5.0.so.1(_ZN4llvm3sys17RunSignalHandlersEv+0x56)[0x7fb194553416] /usr/lib/x86_64-linux-gnu/libLLVM-5.0.so.1(+0x7a754b)[0x7fb19455354b] /lib/x86_64-linux-gnu/libpthread.so.0(+0x12890)[0x7fb193997890] ldc2(_D3dmd13expressionsem18functionParametersFS3dmd7globals3LocPS3dmd6dscope5ScopeC3dmd5mtype12TypeFunctionC3dmd5mtype4TypePS3dmd4root5array40__T5ArrayTC3dmd10expression10ExpressionZ5ArrayC3dmd4func15FuncDeclarationPC3dmd5mtype4TypePC3dmd10expression10ExpressionZb+0xd1e)[0x560e820d100e] ldc2(_ZN25ExpressionSemanticVisitor5visitEP7CallExp+0x338b)[0x560e820dd2fb] ldc2(_D3dmd13expressionsem18resolvePropertiesXFPS3dmd6dscope5ScopeC3dmd10expression10ExpressionC3dmd10expression10ExpressionZC3dmd10expression10Expression+0xcaa)[0x560e820cfb5a] ldc2(_Z17resolvePropertiesP5ScopeP10Expression+0x11)[0x560e81fe5201] ldc2(_ZN24StatementSemanticVisitor5visitEP12ExpStatement+0x6e)[0x560e8219cd3e] ldc2(_ZN24StatementSemanticVisitor5visitEP14DebugStatement+0x5d)[0x560e821b0d6d] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xf2)[0x560e8219ded2] ldc2(_ZN24StatementSemanticVisitor5visitEP11IfStatement+0x81d)[0x560e821a818d] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xf2)[0x560e8219ded2] ldc2(_ZN24StatementSemanticVisitor5visitEP11IfStatement+0x81d)[0x560e821a818d] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN24StatementSemanticVisitor5visitEP12ForStatement+0x707)[0x560e8219f197] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xf2)[0x560e8219ded2] ldc2(_ZN24StatementSemanticVisitor5visitEP12ForStatement+0xfd)[0x560e8219eb8d] ldc2(_ZN24StatementSemanticVisitor5visitEP16ForeachStatement+0x5eb2)[0x560e821a5302] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xf2)[0x560e8219ded2] ldc2(_ZN24StatementSemanticVisitor5visitEP21UnrolledLoopStatement+0x87)[0x560e8219dc77] ldc2(_ZN24StatementSemanticVisitor5visitEP16ForeachStatement+0x781)[0x560e8219fbd1] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN16Semantic3Visitor5visitEP15FuncDeclaration+0x1779)[0x560e8207e399] ldc2(_ZN15FuncDeclaration17functionSemantic3Ev+0xf1)[0x560e82042c21] ldc2(_ZN15FuncDeclaration16functionSemanticEv+0x28d)[0x560e81ffd29d] ldc2(_D3dmd10expression7resolveFS3dmd7globals3LocPS3dmd6dscope5ScopeC3dmd7dsymbol7DsymbolbZC3dmd10expression10Expression+0x45b)[0x560e82084feb] ldc2(_ZN25ExpressionSemanticVisitor5visitEP13IdentifierExp+0x898)[0x560e820d3e08] ldc2(_ZN25ExpressionSemanticVisitor5visitEP7CallExp+0x160f)[0x560e820db57f] ldc2(_ZN24StatementSemanticVisitor5visitEP12ExpStatement+0x5c)[0x560e8219cd2c] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN16Semantic3Visitor5visitEP15FuncDeclaration+0x1779)[0x560e8207e399] ldc2(_ZN15FuncDeclaration17functionSemantic3Ev+0xf1)[0x560e82042c21] ldc2(_ZN15FuncDeclaration16functionSemanticEv+0x28d)[0x560e81ffd29d] ldc2(_D3dmd10expression7resolveFS3dmd7globals3LocPS3dmd6dscope5ScopeC3dmd7dsymbol7DsymbolbZC3dmd10expression10Expression+0x45b)[0x560e82084feb] ldc2(_ZN25ExpressionSemanticVisitor5visitEP13IdentifierExp+0x898)[0x560e820d3e08] ldc2(_ZN25ExpressionSemanticVisitor5visitEP7CallExp+0x160f)[0x560e820db57f] ldc2(_ZN24StatementSemanticVisitor5visitEP12ExpStatement+0x5c)[0x560e8219cd2c] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN24StatementSemanticVisitor5visitEP14ScopeStatement+0xf2)[0x560e8219ded2] ldc2(_ZN24StatementSemanticVisitor5visitEP11IfStatement+0x81d)[0x560e821a818d] ldc2(_ZN24StatementSemanticVisitor5visitEP17CompoundStatement+0x6f)[0x560e8219d1ff] ldc2(_ZN16Semantic3Visitor5visitEP15FuncDeclaration+0x1779)[0x560e8207e399] ldc2(_ZN16Semantic3Visitor5visitEP16TemplateInstance+0x122)[0x560e8207c352] ldc2(_D3dmd10dsymbolsem24templateInstanceSemanticFC3dmd9dtemplate16TemplateInstancePS3dmd6dscope5ScopePS3dmd4root5array40__T5ArrayTC3dmd10expression10ExpressionZ5ArrayZv+0xc83)[0x560e8209123
Re: Compiler build error
On Sunday, 5 August 2018 at 01:15:07 UTC, Nicholas Wilson wrote: On Saturday, 4 August 2018 at 18:12:05 UTC, Alex wrote: On Saturday, 4 August 2018 at 13:26:01 UTC, Nicholas Wilson That is a very long stacks trace and combined with the very short stack trace on OSX, this is probably a stack overflow. 1) Do you have any very deeply nested types/templates somewhere or somehow created a cyclic dependency in semantic analysis? 2) Can you try with a bigger stack (ulimit -s)? If it still fails then its probably 1. :) I assumed this at the beginning too... The structures are not very deep, say 3-4 levels. But yes, I do have something like a loop you mentioned. I'm trying to get rid of this right now. I hoped, if the compiler has problems with my construct, it would help me to find a better start place for this... However, if I take your description: Is there a general way, to solve a cyclic dependency during the semantic analysis step? I mean, I'm trying to lowering logic in my code somehow, but the loop I need won't go away per se...
Re: @nogc closures
On Sunday, 5 August 2018 at 09:20:21 UTC, vit wrote: It's possible create something like this without errors? void main()@nogc{ //Error: function `app.main` is `@nogc` // yet allocates closures with the GC import std.experimental.all; const int j = 2; int i = 0; const int[3] tmp = [1, 2, 3]; tmp[] .filter!((x)scope => x == j)///main.__lambda1 closes over variable j .each!((x)scope => i = x); } No, at least as I understand it. https://issues.dlang.org/show_bug.cgi?id=17841 But you can define a struct, with the needed j and i are stored, and some functions within, which performs map reduce logic you need.
Re: foreach on a tuple using aliases
On Sunday, 5 August 2018 at 14:07:30 UTC, Steven Schveighoffer wrote: I have found something that looks like a bug to me, but also looks like it could simply be a limitation of the foreach construct. Consider this code: struct Foo {} enum isFoo(alias x) = is(typeof(x) == Foo); void main() { Foo foo; assert(isFoo!foo); static struct X { int i; Foo foo; } X x; foreach(i, ref item; x.tupleof) static if(is(typeof(item) == Foo)) // line A static assert(isFoo!item); // line B else static assert(!isFoo!item); } Consider just the two lines A and B. If you saw those lines anywhere, given the isFoo definition, you would expect the assert to pass. But in this case, it fails. What is happening is that the first time through the loop, we are considering x.i. This is an int, and not a Foo, so it assigns false to the template isFoo!item. The second time through the loop on x.foo, the compiler decides that it ALREADY FIGURED OUT isFoo!item, and so it just substitutes false, even though the item in question is a different item. So is this a bug? Is it expected? Is it too difficult to fix? The workaround of course is to use x.tupleof[i] when instantiating isFoo. But it's a bit ugly. I can also see other issues cropping up if you use `item` for other meta things. -Steve Another workaround would be ´´´ void main() { Foo foo; assert(isFoo!foo); static struct X { int i; Foo foo; } X x; static foreach(i, item; typeof(x).tupleof) static if(is(typeof(item) == Foo)) // line A static assert(isFoo!item); // line B else static assert(!isFoo!item); } ´´´ wouldn't it?