Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 18:37:45 UTC, wjoe wrote: I have some similar functions: void register(C: IFoo)() { _insert!C(); } void register(C)() if (behavesLikeFoo!C) { _insert!C(); } There are more overloads with parameters so I want to merge them void register(C, ARGS...)(ARGS args) if (behavesLikeFoo!C || isInstanceOf!(C, IFoo)) { _insert!C(args); } I found a lot of information on how to do this at runtime but not at compile time. std.traits: isInstanceOf doesn't work. Neither did anything I tried with typeid etc. The behavesLikeFoo constraint works as expected but it accepts any class no matter whether or not it implements the interface. see if "import std.traits: isImplicitlyConvertible" helps you.
Re: Why is "delete" unsafe?
On Wednesday, 23 September 2020 at 04:15:51 UTC, mw wrote: On Saturday, 27 October 2012 at 01:08:12 UTC, Jonathan M Davis wrote: Yes. But using core.memory.GC.free is unsafe for the same reasons that delete is. It's just that it's a druntime function instead of a part of the language, so it's less likely for someone to free GC memory without knowing what they're doing. It's there because there _are_ times when it makes sense and is useful, but it's definitely not safe, so you have to be careful and know what you're doing. What do you mean by saying "it's definitely not safe" here? I mean: if I'm careful and know what I'm doing, e.g. remove all the reference to any part of the `object` before call core.memory.GC.free(object), is there still any inherit "unsafe" side of `free` I should be aware of? FYI: I just described my use case here: https://forum.dlang.org/post/hzryuifoixwwywwif...@forum.dlang.org The logic is: @safe code isn't allowed to have access to dangling pointers, because you're allowed to dereference pointers in @safe code, and dereferencing a dangling pointer is undefined behavior. Since manually freeing memory can create dangling pointers, you're not allowed to do it in @safe code. If you can prove with 100% certainty that you're not going to create a dangling pointer, you can wrap the call to `free` in a @trusted lambda: () @trusted { free(ptr); ptr = null; }();
Re: Timeout around function call
On Wednesday, 23 September 2020 at 20:54:51 UTC, Imperatorn wrote: On Wednesday, 23 September 2020 at 20:44:51 UTC, Ali Çehreli wrote: On 9/23/20 1:19 PM, Imperatorn wrote: > [...] send a > [...] with timeout. [...] Sorry, I can't see the problem. Could you be more specific about what you want to achieve? Oops, I meant to reply to drathier
Re: Timeout around function call
On Wednesday, 23 September 2020 at 20:44:51 UTC, Ali Çehreli wrote: On 9/23/20 1:19 PM, Imperatorn wrote: > [...] send a > [...] with timeout. [...] Sorry, I can't see the problem. Could you be more specific about what you want to achieve?
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 20:19:04 UTC, data pulverizer wrote: This has prompted me to write a data structure that I thought would be impossible until now False alarm: ``` writeln("typeof(x.next): ", typeof(x.next).stringof); ``` gives: ``` typeof(x.next): const(Node) ``` Oh well.
Re: Timeout around function call
On 9/23/20 1:19 PM, Imperatorn wrote: > No. You should not share anything. Personally I would just send a > message to request termination or use the solution provided with timeout. std.concurrency does not allow "mutable thread-local data"; so one needs to cast to shared (assuming copying is not desired e.g. because it's expensive). I am modifying my second program[1] with these changes: The worker's receive() call mentions an element with shared ints: receive( // .. same as before // New message type: (shared(int)[] arr) { ownerTid.send(arr[0]); } ); The sender casts to shared and receives a shared(int): auto arr = new int[100]; worker.send(cast(shared)arr); writefln!"Received array result: %s"(receiveOnly!(shared(int))()); It is unfortunate that receiveOnly!int does not work because the returned int is just a copy. Well, at least we have a way of distinguishing int from shared(int). Is it useful? Ali [1] https://forum.dlang.org/post/rkdrql$2uht$1...@digitalmars.com
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 20:19:04 UTC, data pulverizer wrote: This has prompted me to write a data structure that I thought would be impossible until now. [...SNIP...] Here is the function with the correct template constraint: ``` auto makeChain(Args...)(Args args) if(Args.length > 2 && is(Args[0] == Start) && is(Args[Args.length - 1] == End)) { args[0].next = args[1]; static foreach(i; 1..(Args.length - 1)) { args[i].prev = args[i - 1]; args[i].next = args[i + 1]; } args[$ - 1].prev = args[$ - 2]; return args[0]; } ```
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 19:27:13 UTC, wjoe wrote: Appologies if you took offense. Your replies are very much appreciated. No offense taken.
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 19:16:13 UTC, H. S. Teoh wrote: Of course the compiler knows. And of course it can use this information for static dispatch. That's why D is so awesome at metaprogramming. ;-) What the compiler *doesn't* know is whether a variable of some supertype of Foo (say Object) implements IFoo, because that's something that can only be determined at runtime (effectively, you need to downcast to Foo / IFoo and test if it's null). But that's not what the OP is asking for in this case. T This has prompted me to write a data structure that I thought would be impossible until now. It's a data structure with a Start node with a link to next, then any number of Middle nodes with previous and next links, and an End node with a previous link all inheriting from a common interface Node. This is of course possible using runtime polymorphism, but I wanted it available for static dispatch rather than everything being listed as "Node" static type. The implementation is below and works. Interestingly when I wrote it down with a pen and paper I thought that it would lead to infinitely recursive unwriteable data type and so didn't even bother trying to implement it. But D actually forms the correct static type, it prints the gobbledygook type I expect at compile time but the actual static type at runtime. Amazing! I have been using structs with tuples because I thought this data structure was impossible! ``` import std.stdio: writeln; interface Node{} class Start: Node { Node next; } class Middle: Node { Node prev; Node next; } class End: Node { Node prev; } auto makeChain(Args...)(Args args) if(Args.length > 3) { args[0].next = args[1]; static foreach(i; 1..(Args.length - 1)) { args[i].prev = args[i - 1]; args[i].next = args[i + 1]; } args[$ - 1].prev = args[$ - 2]; return args[0]; } void main() { static const x = makeChain(new Start(), new Middle(), new Middle(), new Middle(), new Middle(), new End()); pragma(msg, "x.next: ", x.next, "\n"); writeln("x.next: ", x.next); } ``` output: ``` x.next: Middle(Start(Middle()), Middle(Middle(Start(Middle()), Middle()), Middle(Middle(Middle(Start(Middle()), Middle()), Middle()), Middle(Middle(Middle(Middle(Start(Middle()), Middle()), Middle()), Middle()), End(Middle(Middle(Middle(Middle(Start(Middle()), Middle()), Middle()), Middle()), End())) x.next: node.Middle ```
Re: Timeout around function call
On Wednesday, 23 September 2020 at 17:33:50 UTC, drathier wrote: On Tuesday, 22 September 2020 at 21:55:51 UTC, Imperatorn wrote: [...] Blocking is perfectly fine. I'm wondering if I need things to be shared now or something? Not used to programming with threads. Adding a shared modifier recursively onto every piece of data that needs it is a ton of work though. I don't want to copy the data around since it's many gigabytes, but I'm sure there won't be any data races; main thread will start 2 threads, one for running the timer and one running the function call. The main thread doesn't access the data until both the timer and function call threads have stopped completely. No. You should not share anything. Personally I would just send a message to request termination or use the solution provided with timeout.
Re: How to implement fastcall ?
On Wednesday, 23 September 2020 at 19:50:13 UTC, Denis Feklushkin wrote: On Monday, 21 September 2020 at 11:14:06 UTC, Виталий Фадеев wrote: How to implement fastcall ? ( stdcall is calling convention for pass function arguments via registers ) Hypothesis: it is possible what LLVM + Link Time Optimization does by this way. ~All modern ABIs use registers; __fastcall was one of the special 32-bit x86 ABIs AFAIK (using up to 2 GP registers) and isn't supported directly. The D ABI for 32-bit x86 uses one GP register (and is somewhat similar to __thiscall for member functions).
Re: Is it possible to "overload" based on visibility?
On Wednesday, 23 September 2020 at 19:26:43 UTC, aliak wrote: Yeah, you can make a property setter: private void x(int newValue) { _x = newValue } I'm aware of this, but it does not achieve what I asked for. It only allows me to assign to _x, it doesn't give me a reference to x, so I cannot use it with say += or any other function that takes int by mutable reference.
Re: How to implement fastcall ?
On Monday, 21 September 2020 at 11:14:06 UTC, Виталий Фадеев wrote: How to implement fastcall ? ( stdcall is calling convention for pass function arguments via registers ) Hypothesis: it is possible what LLVM + Link Time Optimization does by this way.
Re: Is it possible to "overload" based on visibility?
On 9/23/20 2:38 PM, 60rntogo wrote: So my questions are: 1. Can I achieve my original goal of being able to refer to _x by one name, so that I have read only access from outside the module and read/write access from inside? I would guess no. You have to use different names. 2. Is the behavior that allows me to call the private method intended? This is such a blatant violation of encapsulation that it feels like a bug either in the language or the implementation. This is a bug in the language. Either varying ONLY by visibility of an overload should be disallowed, or you shouldn't have access to the private x. I don't know which one the answer is, but certainly the current behavior is erroneous. -Steve
Re: Is it possible to "overload" based on visibility?
On Wednesday, 23 September 2020 at 19:27:13 UTC, Steven Schveighoffer wrote: This is a bug in the language. 🤯😆
Re: Is it possible to "overload" based on visibility?
On Wednesday, 23 September 2020 at 18:38:53 UTC, 60rntogo wrote: There are really two questions here, one that I intended to ask and one that came out while I was trying to figure out the answer. Consider this simple code: [...] Yeah, you can make a property setter: private void x(int newValue) { _x = newValue } 2. Is the behavior that allows me to call the private method intended? This is such a blatant violation of encapsulation that it feels like a bug either in the language or the implementation. Definitely sounds like a bug! Feels like this has got to be a regression because I just tried this: struct Foo { private void f() {} void f(int i) {} } And Foo.f() is callable from outside the module: https://run.dlang.io/is/FVyw7u
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 19:08:47 UTC, data pulverizer wrote: On Wednesday, 23 September 2020 at 18:56:33 UTC, wjoe wrote: [...] Didn't think that the compiler didn't know but wasn't aware that you could use that information to statically dispatch. My mistake, I'll shut up now! Appologies if you took offense. Your replies are very much appreciated.
Re: How can I test at compile time whether T is an instance of an interface ?
On Wed, Sep 23, 2020 at 07:08:47PM +, data pulverizer via Digitalmars-d-learn wrote: > On Wednesday, 23 September 2020 at 18:56:33 UTC, wjoe wrote: > > > > It doesn't occur to me that the compiler doesn't know at compile > > time that > > > > interface IFoo{} > > class Foo: IFoo {} > > > > class Foo implements interface IFoo. > > Didn't think that the compiler didn't know but wasn't aware that you > could use that information to statically dispatch. My mistake, I'll > shut up now! Of course the compiler knows. And of course it can use this information for static dispatch. That's why D is so awesome at metaprogramming. ;-) What the compiler *doesn't* know is whether a variable of some supertype of Foo (say Object) implements IFoo, because that's something that can only be determined at runtime (effectively, you need to downcast to Foo / IFoo and test if it's null). But that's not what the OP is asking for in this case. T -- Error: Keyboard not attached. Press F1 to continue. -- Yoon Ha Lee, CONLANG
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 18:56:33 UTC, wjoe wrote: It doesn't occur to me that the compiler doesn't know at compile time that interface IFoo{} class Foo: IFoo {} class Foo implements interface IFoo. Didn't think that the compiler didn't know but wasn't aware that you could use that information to statically dispatch. My mistake, I'll shut up now!
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 18:49:28 UTC, data pulverizer wrote: On Wednesday, 23 September 2020 at 18:37:45 UTC, wjoe wrote: [...] A class at compile time is it's own static type, OOP polymorphism is a runtime feature not compile time. You have to write your own traits for specific objects to get them to relate to each other using static overloading. It doesn't occur to me that the compiler doesn't know at compile time that interface IFoo{} class Foo: IFoo {} class Foo implements interface IFoo.
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 18:50:28 UTC, H. S. Teoh wrote: Try this: interface I {} class C : I {} class D {} struct S {} pragma(msg, is(C : I)); // true pragma(msg, is(D : I)); // false pragma(msg, is(S : I)); // false So probably what you want is something like this: void register(C, ARGS...)(ARGS args) if (behavesLikeFoo!C || is(C : IFoo)) ... T Yes, that's it. Thanks :)
Re: How can I test at compile time whether T is an instance of an interface ?
Try this: interface I {} class C : I {} class D {} struct S {} pragma(msg, is(C : I)); // true pragma(msg, is(D : I)); // false pragma(msg, is(S : I)); // false So probably what you want is something like this: void register(C, ARGS...)(ARGS args) if (behavesLikeFoo!C || is(C : IFoo)) ... T -- Change is inevitable, except from a vending machine.
Re: How can I test at compile time whether T is an instance of an interface ?
On Wednesday, 23 September 2020 at 18:37:45 UTC, wjoe wrote: I have some similar functions: void register(C: IFoo)() { _insert!C(); } void register(C)() if (behavesLikeFoo!C) { _insert!C(); } There are more overloads with parameters so I want to merge them void register(C, ARGS...)(ARGS args) if (behavesLikeFoo!C || isInstanceOf!(C, IFoo)) { _insert!C(args); } I found a lot of information on how to do this at runtime but not at compile time. std.traits: isInstanceOf doesn't work. Neither did anything I tried with typeid etc. The behavesLikeFoo constraint works as expected but it accepts any class no matter whether or not it implements the interface. A class at compile time is it's own static type, OOP polymorphism is a runtime feature not compile time. You have to write your own traits for specific objects to get them to relate to each other using static overloading.
Is it possible to "overload" based on visibility?
There are really two questions here, one that I intended to ask and one that came out while I was trying to figure out the answer. Consider this simple code: --- module foo; struct Foo { private int _x; int x() const { return _x; } } --- If I have an instance of Foo outside of the module I can read the value of _x using the property method x, but I can only modify it from inside the module using the name _x. This is exactly the kind of encapsulation that I often want, but I'm wondering if this could be improved a little. It would be nice if I didn't have to remember if I need to use _x or x depending on the context. Instead I would like to use only one name, say x, from both inside and outside of the module and have compiler complain if I'm trying to modify it from the outside. My naive attempt was this: --- import std : writeln; private int _x; private ref int x() return { writeln("ref int"); return _x; } int x() const { writeln("int"); return _x; } --- At first I didn't even expect this to compile, but it does and I can call these methods. I believe an overload is chosen based on the type qualifier of a Foo instance. What is truly unexpected is that if I call x on a mutable object even outside of the module, then the first overload is called! So my questions are: 1. Can I achieve my original goal of being able to refer to _x by one name, so that I have read only access from outside the module and read/write access from inside? 2. Is the behavior that allows me to call the private method intended? This is such a blatant violation of encapsulation that it feels like a bug either in the language or the implementation.
How can I test at compile time whether T is an instance of an interface ?
I have some similar functions: void register(C: IFoo)() { _insert!C(); } void register(C)() if (behavesLikeFoo!C) { _insert!C(); } There are more overloads with parameters so I want to merge them void register(C, ARGS...)(ARGS args) if (behavesLikeFoo!C || isInstanceOf!(C, IFoo)) { _insert!C(args); } I found a lot of information on how to do this at runtime but not at compile time. std.traits: isInstanceOf doesn't work. Neither did anything I tried with typeid etc. The behavesLikeFoo constraint works as expected but it accepts any class no matter whether or not it implements the interface.
Re: Timeout around function call
On Tuesday, 22 September 2020 at 21:55:51 UTC, Imperatorn wrote: On Tuesday, 22 September 2020 at 09:32:13 UTC, drathier wrote: What's the obvious way to put a timeout around a function call? I'm thinking a 5 or 30 second timeout, and I'm expecting it to pretty much never time out. You have several options. Either you use the actor model (spawn[Linked]) and send a termination message after a specified time. Or you use a task and check for yourTask.done(). Or you could create a Thread and check isRunning. (You didn't specify what you wanted to happen and if blocking was allowed or not) Blocking is perfectly fine. I'm wondering if I need things to be shared now or something? Not used to programming with threads. Adding a shared modifier recursively onto every piece of data that needs it is a ton of work though. I don't want to copy the data around since it's many gigabytes, but I'm sure there won't be any data races; main thread will start 2 threads, one for running the timer and one running the function call. The main thread doesn't access the data until both the timer and function call threads have stopped completely.
Re: Escape this in pure members
On 23.09.20 02:06, DlangUser38 wrote: The following analysis might be wrong but I think that `scope` as a **member** function attribute is not supposed to be used as that is not even documented. It's documented here: https://dlang.org/spec/memory-safe-d.html#scope-return-params Quote: "[`scope` and `return`] may appear after the formal parameter list, in which case they apply either to a method's this parameter, or [... irrelevant ...]." It's less than ideal that the documentation of `scope` is spread over two pages.
Re: Escape this in pure members
On Wednesday, 23 September 2020 at 00:06:38 UTC, DlangUser38 wrote: Hmm, why would `b` have longer lifetime? Isn't the lifetime of `b` throughout `bar`? The following analysis might be wrong but I think that `scope` as a **member** function attribute is not supposed to be used as that is not even documented. Where's the other scope analysis documented? So it would works "by default". The compiler thinks that `this` is a scope variable that will stop living after `bar()`. So are you saying that this code should compile with and without the member being `scope`? Also as `b` is not `ref` this is clearly a wrong diagnostic. There's a special case missing in the compiler.
Re: Building LDC runtime for a microcontroller
On Wednesday, 23 September 2020 at 10:02:58 UTC, Dylan Graham wrote: On Friday, 18 September 2020 at 07:44:50 UTC, Dylan Graham wrote: On Monday, 7 September 2020 at 19:12:59 UTC, aberba wrote: On Monday, 7 September 2020 at 16:18:00 UTC, IGotD- wrote: On Monday, 7 September 2020 at 15:23:28 UTC, Severin Teona wrote: [...] Use betterC, which is much better suited for microcontrollers than the full D. The disadvantage is that many great features are disabled in betterC. [...] How about an alternative runtime + standard library for embedded systems...with a least bare minimum. I've seen a number of efforts to get D to run in those environments but almost none of them is packaged for others to consume. [...] A lot of embedded stuff is done with RTOSs now that provide memory management and threading support, so having a flexible lightweight runtime with a generic backend (mem allocation, threads) that I can hook to the RTOS' libraries would be great. I'm starting work on a small runtime according to this specification. I can't promise a whole lot; it will be barebones. I'm targeting the STM32 series (ARM Cortex M0-4). So far I have been able to get a class and heap allocated struct to allocate and deallocate manually on an STM32F407 MCU. Array bounds checking works but so far just logs the error in my IDE and hangs. Abstract classes work too. Interfaces are giving me trouble for some reason - they crash LDC2 1.23.0. Going to add some proper support for D's assert(...) and array bounds checking to make things a little easier.
Re: Building LDC runtime for a microcontroller
Wow, I have just received a link to this topic from my colleague. Here is also another thread about druntime for MCUs: https://forum.dlang.org/post/cwtkntyjhrwvpahfk...@forum.dlang.org
Re: Building LDC runtime for a microcontroller
On Friday, 18 September 2020 at 07:44:50 UTC, Dylan Graham wrote: On Monday, 7 September 2020 at 19:12:59 UTC, aberba wrote: On Monday, 7 September 2020 at 16:18:00 UTC, IGotD- wrote: On Monday, 7 September 2020 at 15:23:28 UTC, Severin Teona wrote: [...] Use betterC, which is much better suited for microcontrollers than the full D. The disadvantage is that many great features are disabled in betterC. [...] How about an alternative runtime + standard library for embedded systems...with a least bare minimum. I've seen a number of efforts to get D to run in those environments but almost none of them is packaged for others to consume. [...] A lot of embedded stuff is done with RTOSs now that provide memory management and threading support, so having a flexible lightweight runtime with a generic backend (mem allocation, threads) that I can hook to the RTOS' libraries would be great. I'm starting work on a small runtime according to this specification. I can't promise a whole lot; it will be barebones. I'm targeting the STM32 series (ARM Cortex M0-4).
Re: Why private methods cant be virtual?
On Tuesday, 22 September 2020 at 11:39:31 UTC, Daniel Kozak wrote: On Tue, Sep 22, 2020 at 1:30 PM ShadoLight via Digitalmars-d-learn < digitalmars-d-learn@puremagic.com> wrote: This is not really "overriding", it is more akin to "overloading" No it is not overloading, overloading is when you have more methods with same name and differents params. It is overriding Which is why I said it is "is more akin to "overloading"" i.e. what I meant is that the behaviour is kind-of "similar" to overloading in your example. I did not mean it was classical overloading. The thing is that, if the base class method is non-virtual, calling it "overriding" is confusing and somewhat misleading - all the derived class does is hide (or "shadow" if you like) the base class method. It is also not polymorphic I did not say otherwise :-) Granted, but your example is confusing in the light that the OP specially asked about virtual and polymorphic behaviour.
Re: Why is "delete" unsafe?
On Wednesday, 23 September 2020 at 04:15:51 UTC, mw wrote: What do you mean by saying "it's definitely not safe" here? I mean: if I'm careful and know what I'm doing, e.g. remove all the reference to any part of the `object` before call core.memory.GC.free(object), is there still any inherit "unsafe" side of `free` I should be aware of? '"delete" is unsafe' doesn't mean 'any program which uses "delete" is unsafe'. What it means is, in a language that has 'delete', /some/ programs will be unsafe. If your language has delete, you cannot guarantee that programs will be safe. Now, D is not safe by default ('delete' would definitely be disallowed in @safe code), but it still wants to have features that /encourage/ safety (fat pointers are a great example of this). 'delete' and 'free' are both equally unsafe; however, if you have verified that your usage of them is safe, it is fine to use them.