Re: std.string.assumeUTF() silently casting mutable to immutable?
On Wednesday, 14 February 2024 at 11:56:29 UTC, Forest wrote: On Wednesday, 14 February 2024 at 10:57:42 UTC, RazvanN wrote: This has already been fixed, you just need to use -preview=fixImmutableConv. This was put behind a preview flag as it introduces a breaking change. I just tried that flag on run.dlang.org, and although it fixes the case I posted earlier, it doesn't fix this one: ```d string test(const(ubyte)[] arr) { import std.string; return arr.assumeUTF; } ``` Shouldn't this be rejected as well? Indeed, that should be rejected as well, otherwise you can modify immutable table. This code currently happily compiles: ```d string test(const(ubyte)[] arr) { import std.string; return arr.assumeUTF; } void main() { import std.stdio; ubyte[] arr = ['a', 'b', 'c']; auto t = test(arr); writeln(t); arr[0] = 'x'; writeln(t); } ``` And prints: ``` abc xbc ``` However, this seems to be a different issue.
Re: Is it possible to do this with a template?
On Friday, 17 December 2021 at 07:52:18 UTC, rempas wrote: I want to use an expression and put it in place inside the `if` parentheses. The expression is: `is(typeof(val) == type)`. I want to use a template called "is_same" that will take the value and a type to place them to the respective places. I have tried the following but it doesn't seem to work: ``` mixin template is_same(val, type) { is(typeof(val) == type) } void main() { int val = 10; static if (is_same!(val, int)) {} } ``` When trying to compile, I'm taking the following error message: ``` Error: declaration expected, not `is` ``` Is this a limitation of templates in D or is there a way to bypass this? There is also a compiler trait [1] which can do that for you: ```d void main() { int val = 10; static if (__traits(isSame, typeof(val), int)) {} } ``` [1] https://dlang.org/spec/traits.html#isSame
Re: template ctor overload Segmentation fault
On Sunday, 12 December 2021 at 11:57:43 UTC, vit wrote: Hello, why does this code fail to compile? ```d struct Foo(T){ this(Rhs, this This)(scope Rhs rhs){ } this(ref scope typeof(this) rhs){ } } struct Bar{ Foo!int foo; } void main(){ } ``` error: Segmentation fault (core dumped) PR: https://github.com/dlang/dmd/pull/13427
Re: template ctor overload Segmentation fault
On Tuesday, 14 December 2021 at 13:02:16 UTC, Tejas wrote: On Tuesday, 14 December 2021 at 12:04:36 UTC, RazvanN wrote: [...] Then why did my modification work? ```d struct Foo(T){ this(Rhs, this This)(scope Rhs rhs){ } this(scope Foo!(T)* rhs){ //replaced typeof(this) with Foo!T and ref with pointer. Code still works if I retain typeof(this) } } struct Bar{ Foo!int foo; } void main(){ import std.stdio:writeln; Bar bar = Bar(); auto BAR = new Bar(); writeln(bar, "\t", BAR, "\t", *BAR); } ``` Did my modifications ensure that this is not treated as a copy constructor? Yes, the copy constructor needs to be explicitly defined by passing a ref parameter. Since you are expecting an explicit pointer, the compiler does not see it as a copy constructor and therefore does not try to generate one for Bar.
Re: template ctor overload Segmentation fault
On Sunday, 12 December 2021 at 11:57:43 UTC, vit wrote: Hello, why does this code fail to compile? ```d struct Foo(T){ this(Rhs, this This)(scope Rhs rhs){ } this(ref scope typeof(this) rhs){ } } struct Bar{ Foo!int foo; } void main(){ } ``` error: Segmentation fault (core dumped) The problem is that the compiler will try to generate an inout copy constructor for Bar that looks roughly like this: ``` this(ref scope inout(Bar) p) inout { this.foo = p; } ``` The idea behind this lowering is to try and call the copy constructor for Foo object if possible. One issue here is that copy constructors have the same symbol name as constructors (__ctor), so `this.foo = p` gets lowered to `foo.__ctor(p)`. Since both the instance and the parameter are inout, the copy constructor of Foo cannot be called, so the templated constructor is called. After generating the template instance of the constructor, you end up with `this(scope inout(Foo)) inout` ; that is basically an rvalue constructor. This is not valid code; if you write: ``` struct Foo(T){ //this(Rhs, this This)(scope Rhs rhs){} this(scope inout(Foo!int) rhs) inout {} this(ref scope typeof(this) rhs){ } } ``` You will get an error stating that you cannot define both an rvalue constructor and a copy constructor. However, since the constructor is templated it is impossible for the compiler to issue this error before actually instantiating the constructor. I see 2 possible fixes for this: (1) either we rename the copy constructor symbol to __cpCtor so that it does not clash with the normal constructor overload set or (2) when a templated constructor is instantiated, we can check whether it is an rvalue constructor and issue an error if a copy constructor exists. When I implemented the copy constructor I thought that it would better to have the copy constructor on a different overload set than the normal constructors, however, Walter insisted that they have the same name. So, I guess (2) is the way to go. Cheers, RazvanN
Re: No rdmd.exe in /bin64 on Windows - is this an issue?
On Monday, 12 July 2021 at 23:57:37 UTC, Scotpip wrote: Hi guys Just installed the DMD 2.097.0 .exe download for Windows on my 64 bit Win 10 workstation. [...] PR: https://github.com/dlang/installer/pull/484
Re: Cannot call find with haystack elements having a explicit copy constructors
On Thursday, 15 July 2021 at 11:08:25 UTC, Per Nordlöw wrote: The adding of copy construtors to `Service` defined as ```d @safe struct Service { this(ref return scope typeof(this) rhs) {} this(const ref return scope typeof(this) rhs) const {} } @safe struct Session { void openAndGetService(in string key) scope { import std.algorithm.searching : find; auto hit = _pairs.find!((x) => x.key == key)(); } private Pair[] _pairs; private struct Pair { string key; Service service; } } ``` struct Pair will have an inout(inout) copy constructor defined the following way: this(inout ref return scope typeof(this) rhs) inout { key = rhs.key; service = rhs.service; } `service = rhs.service` will be rewritten to service.__cpctor(rhs.service), but since Service does not define an inout copy constructor it will fail to typecheck and the compiler will annotate it with @disable. Therefore, Pair will become uncopyable. This will result in isInputRange failing on Pair[] (more specifically, this constraints from isInputRange: is(typeof((return ref R r) => r.front)). If the copy constructor of Service is inout(inout), the generated copy constructor of Pair will be succesfully typechecked and everything will work. For more context, please see this issue [1] and more specifically, this comment [2]. Cheers, RazvanN [1] https://issues.dlang.org/show_bug.cgi?id=20876 [2] https://issues.dlang.org/show_bug.cgi?id=20876#c4
Re: Bug?
On Tuesday, 5 May 2020 at 05:37:08 UTC, Simen Kjærås wrote: On Tuesday, 5 May 2020 at 04:02:06 UTC, RazvanN wrote: [...] Surely the above code, which silently discards the exception, does not print "hello"? Regardless, I ran your code with writeln inside the catch(), and without the try-catch entirely, with and without nothrow on K's destructor. I am unable to replicate the issue on my computer with DMD 2.091.0, as well as on run.dlang.io. Is something missing in your code here? -- Simen Ah sorry! I was on a branch were I had some other modifications. Indeed in git master the issue does not manifest.
Bug?
truct K { ~this() nothrow {} } void main() { static class C { this(K, int) {} } static int foo(bool flag) { if (flag) throw new Exception("hello"); return 1; } try { new C(K(), foo(true)); } catch(Exception) { } } Result: object.Exception@test.d(18): hello If the destructor of K is not marked nothrow the code does not throw an exception. Is this a bug or am I missing something?
Re: std.container.rbtree as Interval Tree?
On Monday, 4 February 2019 at 22:54:01 UTC, James Blachly wrote: I tried to implement an interval tree backed by std.container.rbtree today and fell flat. [...] You can use alias this [1] in your interval element type: struct IntervalElem { size_t start, end; /* ... other declarations */ alias start this; } [1] https://dlang.org/spec/class.html#AliasThis Q2: Would replacing "Elem" with a generic type "T" in the function signatures for upperBound, lowerBound, and various related fns like _firstGreater / _firstGreaterEqual solve this problem? [...] Elem is already a generic type. I don't know how you can make it more generic without adding other template parameters to the class declaration (which means reimplementing RBTree from std.container); James [1] https://dlang.org/spec/operatoroverloading.html#eqcmp ("For example ... x and y are disjoint sets, then neither x < y nor y < x holds, but that does not imply that x == y. Thus, it is insufficient to determine equality purely based on opCmp alone. ")
Re: Segfault when adding a static destructor in druntime/src/rt/sections_elf_shared.d
On Thursday, 10 January 2019 at 23:04:37 UTC, Steven Schveighoffer wrote: On 1/10/19 5:12 PM, RazvanN wrote: On Thursday, 10 January 2019 at 15:04:25 UTC, Steven Schveighoffer wrote: On 1/8/19 7:54 AM, RazvanN wrote: [...] That is a thread-local static destructor. Are any shared static destructors accessing the array? No, there aren't. Indeed, the problem is as Johan as said: the loadedDSOs should not be wrapped in an array with a destructor because it is manually destroyed. Hm... is this a sign of how things will be once the (necessary IMO) change to destroying globals is deployed? -Steve At least for this specific situation, yes.
Re: Segfault when adding a static destructor in druntime/src/rt/sections_elf_shared.d
On Thursday, 10 January 2019 at 15:04:25 UTC, Steven Schveighoffer wrote: On 1/8/19 7:54 AM, RazvanN wrote: [...] That is a thread-local static destructor. Are any shared static destructors accessing the array? No, there aren't. Indeed, the problem is as Johan as said: the loadedDSOs should not be wrapped in an array with a destructor because it is manually destroyed. You might be able to determine this by printf debugging between calling unshared and shared destructors. -Steve
Re: Segfault when adding a static destructor in druntime/src/rt/sections_elf_shared.d
On Tuesday, 8 January 2019 at 14:30:24 UTC, Johan Engelen wrote: On Tuesday, 8 January 2019 at 12:54:11 UTC, RazvanN wrote: [...] Great! (I am _extremely_ surprised that dtors are not called for globals.) [...] Thanks! This is really helpful! RazvanN
Segfault when adding a static destructor in druntime/src/rt/sections_elf_shared.d
Hi all, I am working on issue 14650 [1] and I would like to implement a solution where static destructors are destroying global variables. However, I have the following problem in druntime/src/rt/sections_elf_shared: struct ThreadDSO { DSO* _pdso; static if (_pdso.sizeof == 8) uint _refCnt, _addCnt; else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt; else static assert(0, "unimplemented"); void[] _tlsRange; alias _pdso this; // update the _tlsRange for the executing thread void updateTLSRange() nothrow @nogc { _tlsRange = _pdso.tlsRange(); } } Array!(ThreadDSO) _loadedDSOs; For this code, I would have to create the following static destructor: static ~this() { _loadedDSOs.__dtor(); } Because Array defines a destructor which sets its length to 0. However this code leads to segfault when compiling any program with the runtime (betterC code compiles successfully). In my attempt to debug it, I dropped my patch and added the above mentioned static destructor manually in druntime which lead to the same effect. Interestingly, _loadedDSOs.__dtor runs successfully, the segmentation fault comes from somewhere higher in the call path (outside of the _d_run_main function (in rt/dmain2.d)). I'm thinking that the static destructor somehow screws up the object which is later referenced after the main program finished executing. Does someone well versed in druntime has any ideas what's happening? Cheers, RazvanN [1] https://issues.dlang.org/show_bug.cgi?id=14650
Re: Disabling struct destructor illegal?
On Thursday, 19 July 2018 at 09:50:32 UTC, Jim Balter wrote: On Thursday, 19 July 2018 at 08:50:15 UTC, RazvanN wrote: struct A { int a; @disable ~this() {} } void main() { A a = A(2); } Currently, this code yields: Error: destructor `A.~this` cannot be used because it is annotated with @disable I was expecting that disabling the destructor would make it as if the struct does not have a destructor Why? That's not the semantics of @disable. And why would you want that? What are you actually trying to achieve? I just don't understand why you would ever mark the destructor of a struct with @disable. When is that useful? If it's not, why not just forbit it?
Disabling struct destructor illegal?
struct A { int a; @disable ~this() {} } void main() { A a = A(2); } Currently, this code yields: Error: destructor `A.~this` cannot be used because it is annotated with @disable I was expecting that disabling the destructor would make it as if the struct does not have a destructor, instead it makes the program not compile. I find this behavior odd: why not make it illegal to disable the destructor if disabling it will surely result in errors wherever the struct is used. The only situation where the code will compile is A is never used directly. To make matters even more confusing, this code compiles: class A { int a; @disable ~this() {} } void main() { A a = new A(); } So, is this a bug or am I missing something? Yoroshiku onegaishimasu, RazvanN
Re: Class qualifier vs struct qualifier
Honestly, from what I understand of how this works, what I find weird is the struct case. immutable on classes does _not_ make the class itself immutable. It just makes all of its members immutable - hence the error about trying to allocate new Foo instead of new immutable Foo. So, that is exactly what I would expect. And honestly, being able to write Foo and have it imply immutable Foo would get _really_ confusing when reading and debugging code. Maybe it has something to do with structs being value types and classes being reference types. If you declare an immutable struct then you cannot modify it's value, while if you declare a class, the pointer to the class is mutable, while the class fields are not. This kind of makes sense, however the thing is that in both situations you are not able to mutate any of the class/struct fields no matter how you instantiate it, so it is really redundant to use `immutable` when creating the instance. What's bizarre is that marking the struct with immutable would affect anything other than its members. Bar b; should not claim that typeof(b) is immutable(Bar). b was not marked as immutable. It was listed as Bar, not immutable Bar. So, b shouldn't be immutable. - Jonathan M Davis
Class qualifier vs struct qualifier
Hello, I'm having a hard time understanding whether this inconsistency is a bug or intended behavior: immutable class Foo {} immutable struct Bar {} void main() { import std.stdio : writeln; Foo a; Bar b; writeln("typeof(a): ", typeof(a).stringof); writeln("typeof(b): ", typeof(b).stringof); } prints: typeof(Foo): Foo typeof(Bar): immutable(Bar) It seems like the class storage class is not taken into account which leads to some awkward situations like: immutable class Foo { this() {} } void main() { Foo a = new Foo(); // error: immutable method `this` is not callable using a // mutable object } To make it work I have to add immutable to both sides of the expression : immutable Foo a = new immutable Foo(); this is a wonder of redundancy. I already declared the class as immutable so it shouldn't be possible to have mutable instances of it (and it isn't), however I am forced to write the immutable twice even though it is pretty obvious that the class cannot be mutated.
Constructor qualifiers; bug or expected behavior?
Hi all, Let's say we have this code: struct B { int a; this(int a) immutable { this.a = 7; } this(int a) { this.a = 10; } } void main() { B a = immutable B(2); writeln(a.a); a.a = 4; immutable B a2 = immutable B(3); writeln(a2.a); a2.a = 3;// error : cannot modify } Both a and a2 will be constructed using the immutable constructor, however a is not immutable (a.a = 4 will compile fine). Is this the intended behavior? Shouldn't the compiler warn me that I'm trying to create a mutable object using the constructor for an immutable object? I couldn't find any documentation about this.
Re: Understanding the AST...
On Thursday, 22 February 2018 at 13:21:04 UTC, joe wrote: On Monday, 12 February 2018 at 08:47:58 UTC, RazvanN wrote: Hi Joe, /SNIP On Tuesday, 6 February 2018 at 12:03:06 UTC, joe wrote: [...] The FuncDeclaration node contains all the information for that. For example, you can access fd.parent to see if the function is declared at top-level (in which case, the parent is going to be a module declaration ) or if it is a nested function (in a class, in a struct, in a function). Every AST node contains information about the position in the AST, all you have to do is find how to get that information: which field to access or which member function to call. /SNIP Cheers, RazvanN Follow up question... Why is *.parent always null? e.g.: extern(C++) class MyVisitor(AST): ParseTimeTransitiveVisitor!AST { override void visit(AST.Import i) { assert(i.parent is null); // always true } override void visitFuncBody(AST.FuncDeclaration f) { assert(f.parent is null); // always true } } Indeed, @Stefan is right. The ParseTimeVisitor only contains information available at parse time. If you are interested in the parent you have 2 options: either (1) use the ParseTimeVisitor and implement the AST traversal logic yourself or (2) you can use the SemanticTimeTransitiveVisitor in which case the parent is not going to be null. In the case of (2) you need to also do some semantic analysis (so you need the whole dmd library, not just the parsing one). Here's an example on using the dmd library (including semantic) [1]. You can copy paste that example and add a few lines of code where you instantiate your visitor (which will inherit SemanticTimeTransitiveVisitor). [1] https://github.com/dlang/dmd/blob/master/test/dub_package/frontend.d RazvanN
Re: How to check if aggregate member is static templated method?
On Thursday, 15 February 2018 at 13:51:41 UTC, drug wrote: 15.02.2018 16:50, drug пишет: https://run.dlang.io/is/zHT2XZ I can check againts if member is either static function or template. But I failed to check if it both static and templated. The best I could come up with is: struct Foo { static staticMethod() { } static templatedStaticMethod(T)(T t) { } } void main() { static if(__traits(isTemplate, Foo.templatedStaticMethod) && __traits(isStaticFunction, Foo.templatedStaticMethod!int)) { writeln("win"); } } It seems like a templated method can be queried if it is static only after it's instantiation. Hope this helps. Cheers, RazvanN
Re: Understanding the AST...
Hi Joe, I suggest you watch this video which explains how the parse time visitors work: https://www.youtube.com/watch?v=tK072jcoWv4 . On Tuesday, 6 February 2018 at 12:03:06 UTC, joe wrote: Hello everybody! Last week end I found this post ( https://dlang.org/blog/2017/08/01/a-dub-case-study-compiling-dmd-as-a-library/ ) on the Blog and thought to myself awesome. So I built the library and everything went smooth. Thanks for the effort of all the involved people who made that possible! I've had a look at the 2 examples, too, the avg. function lines ( https://github.com/dlang/dmd/blob/master/src/examples/avg.d ) and the import ( https://github.com/dlang/dmd/blob/master/src/examples/impvisitor.d ) ones and for a start I decided to make a program that prints the outline of a module. Turns out I don't really understand how to access the data in the AST. For everything there's a visitor method and overriding a few of them to print return statements and some such works as advertised. However, I have no idea where I am in the tree when any of those methods are called. Like for example in FunctionLengthVisitor(AST).visitFuncBody(AST.FuncDeclaration fd). I have a function declaration object which tells me everything about what's inside the function, but how do I know what or where this function belongs to, where can I get that information ? I don't see anything about UDAs either, nor the doc comment. The FuncDeclaration node contains all the information for that. For example, you can access fd.parent to see if the function is declared at top-level (in which case, the parent is going to be a module declaration ) or if it is a nested function (in a class, in a struct, in a function). Every AST node contains information about the position in the AST, all you have to do is find how to get that information: which field to access or which member function to call. I understand when visitor.getAvgLen is called with the parsed module, the accept function calls a visitor overload for each member. But this sounds to me like I'd have to do a lot of book keeping in my visitor to keep track of things which are already present in the AST. The function average length visitor inherits a transitive visitor which means that the AST traversal logic is already implemented for you. All you have to do is override the visiting methods of interest and do whatever suits you : print stuff, alter the ast, stop the visitation or continue the visitation (by calling super.visit(ASTnode)). Any insight to this would be much appreciated :) I know that my explanations might not be very explicit, but if you have an example please post it and we can work on it. Cheers, RazvanN
Re: ddox empty public methods/interfaces etc
On Thursday, 9 November 2017 at 14:21:52 UTC, Steven Schveighoffer wrote: On 11/8/17 10:45 PM, Andrey wrote: I just added to dub.json this: "-ddoxFilterArgs": [ "--min-protection=Public" ] i.e. without --only-documented option, in this way ddox will generate documentation for all public methods, even if there is no docstring. Interesting. I misunderstood then how ddox works. I thought the json it gets is the output from the ddoc generator, but now I realize it's the output from the parser itself. So sure, this makes sense. Sorry for the misinformation! -Steve I don't want to open a new forum thread for this, but if you guys have more experience with ddox can you please explain me how does it work? I expected you can simply run ddox on a .d file and it will output the documentation in some sort of form (json, html or whatever), but from what I saw, you need to pass it the json if you want to use serve-html/generate-html/filter and you have to use dmd to generate the json. Looking on the source code only passing serve-test actually parses the .d file, but the serve-test doesn't seem to be a public parameter. Thanks in advance, RazvanN
Re: std.concurrency.setMaxMailboxSize
On Wednesday, 11 October 2017 at 11:26:11 UTC, rikki cattermole wrote: On 11/10/2017 12:09 PM, RazvanN wrote: Hi all, I have seen that the concurrency api has this method specified in $title [1] and I was wondering what is the use of it? Enabling threads to modify the message box of other threads doesn't seem to be a good idea and I can't think of any real use case. Best regards, RazvanN [1] https://dlang.org/phobos/std_concurrency.html#.setMaxMailboxSize Main controlling thread setting child threads? Otherwise I don't remember the last time it was mentioned, so I'd say leave it be :) Shouldn't the thread be in charge of its mailbox size? Otherwise, main can pass the max size in the constructor.
std.concurrency.setMaxMailboxSize
Hi all, I have seen that the concurrency api has this method specified in $title [1] and I was wondering what is the use of it? Enabling threads to modify the message box of other threads doesn't seem to be a good idea and I can't think of any real use case. Best regards, RazvanN [1] https://dlang.org/phobos/std_concurrency.html#.setMaxMailboxSize
Re: D bindings for TensorFlow
On Friday, 6 January 2017 at 13:22:28 UTC, llaine wrote: Did anyone used Tensorflow with D ? I would be really interesting to know if some libs allows it right now. I read an old thread about TS on the forum, but since then nothing ... At the moment there is no support in D to use TensorFlow directly (the only way is to create the bindings yourself). There has been a discussion, a month ago, about creating a D library which would be binded to the C++ implementation, but at the moment no conclusion was reached. Hope this answers your question. RazvanN
Re: Swap front for char[] input ranges
On Monday, 19 December 2016 at 20:26:26 UTC, Ali Çehreli wrote: On 12/19/2016 06:09 AM, RazvanN wrote: > [...] wrote: >> [...] InputRanges. >> [...] following > [...] char[] > [...] function, so > [...] http://dlang.org/phobos/std_algorithm_mutation.html#bringToFront [...] No need to mention it. It is an honor to be able contribute to this great language. [...] That is right, I am working on that particular bug. After talking with AndreiA, I submitted this PR [1]. It treats the case of char[], but I am not really sure how the constraints should be applied to the function since it seems there are a lot of combinations (especially if char[] is supported). [1] https://github.com/dlang/phobos/pull/4970
Re: Swap front for char[] input ranges
On Monday, 19 December 2016 at 12:25:02 UTC, Ali Çehreli wrote: On 12/19/2016 02:41 AM, RazvanN wrote: > [...] As your comments make it clear below, they cannot be InputRanges. > [...] swapping code > [...] Obivously, tmp1 and tmp2 are unusued there. :) > [...] passed. > [...] state > [...] is: > [...] input ranges > [...] Not possible... It's ok to use something similar to the following template constraint: void foo(R1, R2)(R1 r1, R2 r2) if ((hasSwappableElements!R1 && hasSwappableElements!R2) || (hasLvalueElements!R1 && hasLvalueElements!R2)) { // ... } Ali In this case, the bringToFront function [1] should not accept char[] as parameters? Or a special path should be added in the function, so that char[] are treated specially? [1] http://dlang.org/phobos/std_algorithm_mutation.html#bringToFront
Swap front for char[] input ranges
Hi, I have a function which accepts 2 input Ranges and swaps the first element in Range1 with the first element in Range2. The swapping code looks something like this : static if (is(typeof(swap(r1.front, r2.front { swap(r1.front, r2.front); } else { auto t1 = moveFront(r1), t2 = moveFront(r2); auto tmp1 = r1.front; auto tmp2 = r2.front; r1.front = move(t2); r2.front = move(t1); } This code works for most cases, except when 2 char[] are passed. In that case, the compilation fails with error messages which state that r1.front and r2.front are not Lvalues. So, my question is: how can I swap the 2 elements since in the case of char[] input ranges the front property does not return a reference?
Range of uncopyable elements
Hi, I am trying to create a range with uncopyable elements. My thought process was the following: 1.I have created a struct : struct S { int a; @disable this(this); } 2. I declared an array : S[] arr = [S(1), S(2), S(3)]; expecting that arr will be a range like, for example, an int[]. I was surprised to see that isInputRange!arr is false. So, is there any possibility to create a range with uncopyable elements?
Re: Char representation
On Tuesday, 22 November 2016 at 14:23:28 UTC, Jonathan M Davis wrote: On Tuesday, November 22, 2016 13:29:47 RazvanN via Digitalmars-d-learn wrote: [...] You misunderstand. char[] is a dynamic array of char, wchar[] is a dynamic array of wchar[], and dchar[] is a dynamic array of dchar. There is nothing funny going on with the internal representation. Rather, the problem is with the range API and the traits that go with it. And it's not a bug; it's a design mistake. [...] Thank you very much for this great explanation. Things are starting to make sense now. Razvan Nitu
Char representation
Given the following code: char[5] a = ['a', 'b', 'c', 'd', 'e']; alias Range = char[]; writeln(is(ElementType!Range == char)); One would expect that the program will print true. In fact, it prints false and I noticed that if Range is char[], wchar[], dchar[], string, wstring, dstring Unqual!(ElementType!Range) is dchar. I find it odd that the internal representation for char and string is dchar. Is this a bug?
Re: The return of std.algorithm.find
On Tuesday, 15 November 2016 at 09:43:27 UTC, RazvanN wrote: The find function which receives an input haystack and a needle returns the haystack advanced to the first occurrence of the needle. For normal ranges this is fine, but for sorted ranges (aka SortedRange) it is a bit odd. For example: find(assumeSorted[1, 2, 4, 5, 6, 7], 4) would return [4, 5, 6, 7]. This is in terms with the general policy of the find function, but is weird. Since we know the range is sorted, shouldn't the result be [1, 2, 4]? The whole function is find!"a <= b"(assumeSorted([1, 2, 4, 5, 6, 7]), 4). And the result is the whole range [1, 2, 4, 5, 6, 7].
The return of std.algorithm.find
The find function which receives an input haystack and a needle returns the haystack advanced to the first occurrence of the needle. For normal ranges this is fine, but for sorted ranges (aka SortedRange) it is a bit odd. For example: find(assumeSorted[1, 2, 4, 5, 6, 7], 4) would return [4, 5, 6, 7]. This is in terms with the general policy of the find function, but is weird. Since we know the range is sorted, shouldn't the result be [1, 2, 4]?
Re: Concatenate 2 ranges
On Friday, 11 November 2016 at 13:33:20 UTC, Vladimir Panteleev wrote: On Friday, 11 November 2016 at 13:30:17 UTC, RazvanN wrote: I know that I can use the .array property, but I think that this iterates through all of my elements. Using assumeSorted(chain(r1, r2).array) will return a SortedRange, but I am not sure what the complexity for this operation is. .array allocates, so it's going to be O(n), but the allocation will probably be more expensive. Is there a way to concatenate 2 ranges (SortedRange in my case) in O(1) time? assumeSorted(chain(a, b)) ? This works for me: auto r = assumeSorted(chain([1, 2, 3].sort(), [1, 2, 3].sort())); It does work, the problem is that [1, 2, 3].sort() is of type SortedRange(int[], "a < b") while r is of type SortedRange(Result, "a < b"). This is a problem if you want to return r in a function which has return type SortedRange(int[], "a < b").
Concatenate 2 ranges
I am trying to concatenate 2 ranges of the same type (SortedRange in my case). I have tried merge, join and chain, but the problem is that the result is not an object of the type of the initial ranges. For example: 1. If I use chain(r1, r2), the result will be an object of type Result which I cannot cast to my specific type (SortedRange). 2. If I use merge(r1, r2), the result will be an object of type Merge!(typeof(r1), typeof(r)). I know that I can use the .array property, but I think that this iterates through all of my elements. Using assumeSorted(chain(r1, r2).array) will return a SortedRange, but I am not sure what the complexity for this operation is. Is there a way to concatenate 2 ranges (SortedRange in my case) in O(1) time?
Re: is operator and SortedRange
On Friday, 11 November 2016 at 12:02:10 UTC, ketmar wrote: On Friday, 11 November 2016 at 11:49:25 UTC, RazvanN wrote: [...] template isSortedRange(T) { private import std.range : SortedRange; static if (is(T : SortedRange!TT, TT)) { enum isSortedRange = true; } else { enum isSortedRange = false; } } void main () { import std.algorithm : sort; int[] a; a ~= [1, 6, 3]; auto b = a.sort; pragma(msg, typeof(b)); pragma(msg, isSortedRange!(typeof(a))); // false pragma(msg, isSortedRange!(typeof(b))); // true } Thank you! Worked like a charm
is operator and SortedRange
I am a bit confused about how the is operator works. I have a function which receives an InputRange and a predicate. Now I need to be able to test if the InputRange is actually a SortedRange. I don't care about how the datatypes behind the SortedRange or the predicate, I just need to see if the object is a SortedRange. I have tried the following test: static if(is(typeof(haystack) == SortedRange!(T, _pred), T, _pred)) where haystack is the InputRange, but the test fails. Is there a way to test if the InputRange is a SortedRange without having to explicitly pass the primitive tupe on top of which the SortedRange is built?
Obtain predicate from SortedRange
Given a SortedRange object, is there a way to obtain the predicate which was used for it to be sorted?
Re: typeof(SortedRange) and is operator
On Tuesday, 8 November 2016 at 13:59:19 UTC, Nicholas Wilson wrote: On Tuesday, 8 November 2016 at 13:22:35 UTC, RazvanN wrote: Sorry, I accidentally posted the above message and I don't know how to erase it. You can't, this is a mailing list not a forum. The following post is the complete one: Given the following code: int[] arr = [1, 2, 9, 4, 10, 6]; auto r= sort(arr); if(is(typeof(r) == SortedRange!(int[], "a expression` lambdas don't work at all in template expressions. `SortedRange!(int[], "a
Re: typeof(SortedRange) and is operator
Sorry, I accidentally posted the above message and I don't know how to erase it. The following post is the complete one: Given the following code: int[] arr = [1, 2, 9, 4, 10, 6]; auto r= sort(arr); if(is(typeof(r) == SortedRange!(int[], "a
typeof(SortedRange) and is operator
Given the following code: int[] arr = [1, 2, 9, 4, 10, 6]; auto r= sort(arr); if(is(typeof(r) == SortedRange!(int[], "a