Re: User defined type and foreach
On Friday, 19 January 2024 at 18:13:55 UTC, Jonathan M Davis wrote: On Friday, January 19, 2024 3:49:29 AM MST Jim Balter via Digitalmars-d-learn wrote: On Friday, 17 November 2017 at 17:55:30 UTC, Jonathan M Davis wrote: > When you have > > foreach(e; range) > > it gets lowered to something like > > for(auto r = range; !r.empty; r.popFront()) > { > > auto e = r.front; > > } > > So, the range is copied when you use it in a foreach. Indeed, and the language spec says so, but this is quite wrong as it violates the specification and design of ranges ... only forward ranges are copyable and only via their `save` function. I have an input range that can only be iterated once; if you try to do so again it's empty ... but the foreach implementation breaks that. You should be able to break out of the foreach statement, then run it again (or another foreach) and it should continue from where it left off, but copying breaks that. I need to know how many elements of my range were consumed; copying breaks that. I got around this by having a pointer to my state so only the pointer gets copied. I would also note that tutorials such as Ali Çehreli's "Programming in D – Tutorial and Reference" are unaware of this breakage: " Those three member functions must be named as empty, popFront, and front, respectively. The code that is generated by the compiler calls those functions: for ( ; !myObject.empty(); myObject.popFront()) { auto element = myObject.front(); // ... expressions ... } " "No spec is being violated, and the behavior is completely expected." This is not true, and your over-long response that is a lecture I didn't ask for and don't need misses my point and is largely irrelevant. The specification of ranges, which is independent of the D language, says that the way to copy a range is to use save(). Input ranges cannot be copied or restarted; that's the whole point of the difference between input ranges and forward ranges. You go on and on about the semantics of copying, which has nothing to do with what I wrote, which is that `foreach` copies when it shouldn't; the semantics of copying is not relevant to *not copying*. Input ranges are one-shots; they yield values once and that's it. `foreach` should have been implemented to call `save()` when that is available (when it is a forward range), and to do no copying when it is not available. Had that been done, then people wouldn't have written a bunch of ranges with missing save() functions that are reusable when they shouldn't be due to `foreach` making a copy, making `foreach` impossible to fix now. "Basic input ranges cannot be value types (otherwise, they could implement save)" This is not true, and again misses the point. My input range, the one I described in my original message, is a value type (a struct) which, when passed to functions, is passed by reference. It doesn't implement save because it's an input range, not a forward range. It's not supposed to be copied or restartable because it's an input range, not a forward range. Copying it has the wrong consequences because calling popFront on a copy doesn't advance the one-shot input range. It would work just fine if `foreach` didn't copy it. It works fine if I use it without `foreach`, e.g., if I use it in a for loop like in Ali's book: for ( ; !myObject.empty(); myObject.popFront()) { auto element = myObject.front(); // ... expressions ... } That works just fine with an input range, which is a range that is not restartable. The only thing that doesn't work with my input range is `foreach`, which copies the input range--which, by the specification of input ranges, was never intended. I managed to make it usable with a `foreach` loop by having the struct only store a pointer to its state so the `foreach` copy is harmless, in effect turning my value type range into a reference type and introducing unnecessary overhead.
Re: Error "Outer Function Context is Needed" when class declared in unittest
On Thursday, 5 January 2023 at 13:47:24 UTC, Adam D Ruppe wrote: On Thursday, 5 January 2023 at 13:27:23 UTC, Vijay Nayar wrote: Why is this error only found when declaring a class in the unittest? A unittest is just a special function, it can run code and have local variables. classes and structs declared inside it have access to those local contexts, which it calls the outer function context. Make the outer class `static` too to lift it out of this and your error should go away. Why doesn't the compiler just create the instance with the correct context pointer? And if it won't, how does one provide it? I have a template function which creates new instances of a type that is an argument to the template, and it fails miserably when the type is a nested class. How do I create such instances? Dlang is supposed to be "turtles all the way down", but I keep finding that to be far from reality.
Re: User defined type and foreach
On Friday, 17 November 2017 at 17:55:30 UTC, Jonathan M Davis wrote: When you have foreach(e; range) it gets lowered to something like for(auto r = range; !r.empty; r.popFront()) { auto e = r.front; } So, the range is copied when you use it in a foreach. Indeed, and the language spec says so, but this is quite wrong as it violates the specification and design of ranges ... only forward ranges are copyable and only via their `save` function. I have an input range that can only be iterated once; if you try to do so again it's empty ... but the foreach implementation breaks that. You should be able to break out of the foreach statement, then run it again (or another foreach) and it should continue from where it left off, but copying breaks that. I need to know how many elements of my range were consumed; copying breaks that. I got around this by having a pointer to my state so only the pointer gets copied. I would also note that tutorials such as Ali Çehreli's "Programming in D – Tutorial and Reference" are unaware of this breakage: " Those three member functions must be named as empty, popFront, and front, respectively. The code that is generated by the compiler calls those functions: for ( ; !myObject.empty(); myObject.popFront()) { auto element = myObject.front(); // ... expressions ... } "
Re: What's the proper way to add a local file dependence to dub?
On Monday, 12 March 2018 at 10:20:20 UTC, Seb wrote: On Sunday, 4 March 2018 at 16:46:56 UTC, Marc wrote: then copy it to sources folder? let's say I have a small library folder at C:\mylibrary\D where I want to use dir.d from it. How do I add that file dependence to dub? But I do not want to that file be passed directly to dmd, I want to that file be copied to application's source folder (so it's easy to distribuite, with the dependences together as possible) then compiled. So, what I want to some extension is dub work with loca files. Is this possible to do solely with dub? I know I can easily write a script to run before dub which copies the dependence files from C:\mylibrary to application's source but I'm looking for a more elegant approach as possible; I'm afraid of rewriting a makefile-like soon (I find cmake/make/makefiles just ugly). You can also add a simple dub.sdl to your local files and then use `dub add-local` to add the package to your dub environment. Dub will only rebuild the dependency on your local files if they changed (or you use a different compiler / build settings). Why is there no documentation for this? The dub documentation should have a filesystem layout page, with examples of how to structure local libraries, how to register them, how to add them to projects. AFAICT no such documentation exists. I've tried to follow the structure of libraries I've loaded into dub's packages directory, but it seems to treat local packages differently. And dub add-package is useless ... for one thing, it *overwrites* local-packages.json rather than adding to it.
Re: Are properties mature enough?
On Monday, 20 August 2018 at 00:49:02 UTC, Jonathan M Davis wrote: On Sunday, August 19, 2018 12:32:17 PM MDT QueenSvetlana via Digitalmars-d- learn wrote: In the D Style Guide, it says: Properties https://dlang.org/dstyle.html#properties Functions should be property functions whenever appropriate. In particular, getters and setters should generally be avoided in favor of property functions. And in general, whereas functions should be verbs, properties should be nouns, just like if they were member variables. Getter properties should not alter state. In the Properties function section, it says: https://dlang.org/spec/function.html#property-functions WARNING: The definition and usefulness of property functions is being reviewed, and the implementation is currently incomplete. Using property functions is not recommended until the definition is more certain and implementation more mature. So which is it? Feel free to use @property or not, but the main point in the style guide is about naming functions, not about @property. The idea is that functions that wrap or emulate variables should act like variables themselves. So, they should be named as if they were variables and syntactically used as if they were variables rather than prepending their names with get or set and calling them as functions. e.g. struct S { int prop() { return _prop; } int prop(int val) { return _prop = prop; } private int _prop; } with auto r = s.prop; s.prop = 42; instead of struct S { int getProp() { return _prop; } int setProp(int val) { return _prop = prop; } private int _prop; } auto r = s.getProp(); s.setProp(42). Marking property functions with @property is an extremely popular thing to do, but all it really does at this point is document that the programmer intends for it to be used as a property rather than enforce anything. IMHO, the spec words that bit too strongly, and it should be fixed. That bit got added recently, because one of the devs didn't understand the @property situation, and when he found out what it was, he felt that the spec needed to be clarified about it so that folks didn't think that it was what the spec was claiming, but clearly, he's just confused matters in a different way. Here's the deal. Using the property syntax with functions really has nothing to do with @property. It's just based on the signature that a function has. If it's a free function, and it has a return value but no arguments, without using UFCS, it can be used as a getter int prop(); auto r = prop; If it has a single argument, or it returns by ref, then it can be used as a setter. ref int prop(); int prop(int); void prop(int); all work with prop = 42; though the first two can also be used in chained assignment operations, since they also return a value, whereas the third can't be. e.g. auto foo = prop = 19; works with the first two but not the third. All of the same signatures as member functions also work in the same way except that you then get auto r = obj.prop; for the getter and obj.prop = 42; for the setter. And if they're free functions, and you want to use them with UFCS, then they each need one more parameter. e.g. int prop(MyObj); auto r = obj.prop; for the getter and ref int prop(MyObj); int prop(MyObj, int); void prop(MyObj, int); obj.prop = 42; for the setter. All of this works regardless of anything to do with @property and has had since well before @property existed (well, aside from using it with UFCS, since UFCS came later). However, a number of folks thought that it was too messy to allow any old function with the right set of parameters to be used with the property syntax rather than requiring that it be part of the API that it be a property function. Probably the most egregious case is that something like writeln = 42; works just fine, and writeln is clearly a function, not a function emulating a variable (which is what a property function is supposed to be). So, to improve the situation, @property was proposed. The idea was that functions marked with @property and the correct number of parameters would work as property functions and that they would _have_ to use the property syntax when being used, whereas functions that weren't marked with @property were not allowed to use the property syntax. The ad-hoc nature of the whole thing then goes away, and stuff like writeln = 42; is then illegal. It also fixes the problem where the function returns a callable (e.g. a delegate or a functor). If you have the function foo, and it returns a callable, as long as it's legal to call the function with the property syntax - foo - or without - foo() - there's no way to distinguish when the callable that's returned by the function should be called. If foo is treated as a property, then foo() would call the callable that
Re: ushort + ushort = int?
On Monday, 20 August 2018 at 08:34:56 UTC, Andrey wrote: Hello, Here is a code that you can execute using online compiler https://run.dlang.io/: import std.stdio; void main() { ushort first = 5; ushort second = 1000; ushort result = first + second; writeln(result); } I hae this error: onlineapp.d(7): Error: cannot implicitly convert expression cast(int)first + cast(int)second of type int to ushort Why they are "int" when I declared them as "ushort"??? ushort + ushort = ushort, not int. In C++ there aren't any such issues... Only if you make the mistake of compiling without warnings. Otherwise, the C++ compiler will warn that you're converting an int to a ushort.
Re: Auto keyword and when to use it
On Tuesday, 21 August 2018 at 18:18:25 UTC, QueenSvetlana wrote: On Tuesday, 21 August 2018 at 16:15:32 UTC, XavierAP wrote: Only if someone likes "Type x = new Type()" instead of "auto x = new Type()" I would say they're clearly wrong. As you stated it's up to the programmer to decided. I'm in favor of Type x = new Type() There is nothing to recommend such redundancy; don't do it. because when it comes to constructing a class it usually means more code to verify the types Type inference doesn't require more code. for example: Your example has no bearing on any of the above ... it's not an example of it. class Person { auto firstName; auto lastName; // constuctor to set first and last names } That code is meaningless and isn't legal. You need to either provide explicit types, or they need to be inferable from the type of the initializer. The compiler doesn't know know what firstName or lastName is supposed to be and a programmer might make the obvious assumption and use them as strings. The programmer can't make any assumption because the code is not remotely legal. Doing this also means you have reject any type that isn't a string which means a private function to check the type that was pass to the constructor before initializing it. Where as if you declared it as a string to start of with, all you have to ensure is that it's not blank or contain illegal characters. This is all incoherent. D is a statically typed language. As the answer stated above doing what I showed in my example isn't allowed and this is where Python gets frustrating, because at any point the types could change. They introduced type hints, but it's not enforced, it just makes it more readable, you still have to write code to ensure the proper types were passed. Python is not statically typed; D is. Why are you talking about Python? You asked whether D's auto is like C#'s var ... it is, but it doesn't have C#'s pointless restriction of not being allowed for non-local declarations.
Re: Disabling struct destructor illegal?
On Thursday, 19 July 2018 at 10:04:34 UTC, RazvanN wrote: 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? I don't know, but that doesn't mean there's no possible reason to. If it's not, We haven't established that it's never useful. When you pose a conditional like that, it's a logical mistake to just assume that the condition is met. why not just forbit it? Because the compiler shouldn't be littered with pointless special case restrictions that have to be maintained and might interfere with a valid use case that you haven't thought of. The fact is that you disabled the destructor, then invoked the destructor, and got a clear, informative error at the point of invocation, rather than at the @disable. This is, IMO, a cleaner, better design than the one you're asking for. And it's not true that you "just" don't understand why one would ever @disable the destructor ... in your original post you asked "why not make it illegal to disable the destructor if disabling it will surely result in errors wherever the struct is used" -- it was pointed out that it *doesn't* "surely result in errors wherever the struct is used" -- it only results in an error if the destructor is invoked, exactly as one would expect. In your original post you claimed "The only situation where the code will compile is A is never used directly" -- it was pointed out that this isn't true, as your own example showed. In your original post you said that it was confusing that code that you had just erroneously stated wouldn't compile does compile, and it was pointed out that there's no reason why it shouldn't compile and there's no apparent reason to find it confusing. In your original post you asked if that's a bug, and it has been pointed out that it's not a bug. I hope everything is clear now and all your questions have been answered.
Re: Disabling struct destructor illegal?
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? , 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. Because it won't surely result in errors wherever the struct is used ... you yourself provide an example below where it doesn't. The only situation where the code will compile is A is never used directly. Eh? You immediately give a contrary example: To make matters even more confusing, this code compiles: class A { int a; @disable ~this() {} } void main() { A a = new A(); } Why is that confusing? Why shouldn't it compile? The A that you created is on the heap, so its destructor is never invoked, so what would cause it not to compile? So, is this a bug or am I missing something? Yoroshiku onegaishimasu, RazvanN