Re: Connecting python to D on socket of localhost : target machine actively refuses connection
On Friday, 22 September 2017 at 05:43:24 UTC, Nicholas Wilson wrote: On Friday, 22 September 2017 at 04:37:44 UTC, Enjoys Math wrote: On Friday, 22 September 2017 at 04:25:00 UTC, Enjoys Math wrote: I've tried opening the port for TCP with windows 10 firewall settings. Same result. What tool would best help me debug this? Wireshark or is that too low level? I've used Hercules: http://www.hw-group.com/products/hercules/index_en.html I set up a TCP server with it, and it got the message sent from python. Therefore there is something wrong with the D server. Could it be that you need to call `super();` at the end of your constructor, after your data initialisation? Nope, the run() method gets called.
Re: Connecting python to D on socket of localhost : target machine actively refuses connection
On Friday, 22 September 2017 at 04:37:44 UTC, Enjoys Math wrote: On Friday, 22 September 2017 at 04:25:00 UTC, Enjoys Math wrote: I've tried opening the port for TCP with windows 10 firewall settings. Same result. What tool would best help me debug this? Wireshark or is that too low level? I've used Hercules: http://www.hw-group.com/products/hercules/index_en.html I set up a TCP server with it, and it got the message sent from python. Therefore there is something wrong with the D server. Could it be that you need to call `super();` at the end of your constructor, after your data initialisation?
Re: Connecting python to D on socket of localhost : target machine actively refuses connection
On Friday, 22 September 2017 at 04:25:00 UTC, Enjoys Math wrote: I've tried opening the port for TCP with windows 10 firewall settings. Same result. What tool would best help me debug this? Wireshark or is that too low level? I've used Hercules: http://www.hw-group.com/products/hercules/index_en.html I set up a TCP server with it, and it got the message sent from python. Therefore there is something wrong with the D server.
Re: Problems with function as parameter
On Friday, 22 September 2017 at 03:26:36 UTC, Mike Parker wrote: On Friday, 22 September 2017 at 02:22:46 UTC, Josh wrote: src\mixer.d(80,22): Error: function pointer Mix_ChannelFinished (extern (C) void function(int channel)) is not callable using argument types (extern (C) void delegate(int channel)) Code: void unmuteAfterPlaySound() { Mix_ChannelFinished(); } extern (C) void channelDone(int channel) { unmuteMusic(); } The error message indicates that `channelDone` is a member of a class or a struct. A pointer to a member function is a delegate (or closure), not a function pointer. Free functions, static nested functions, and static member functions all produce function pointer. Non-static member functions and non-static nested functions all produce delegates/closures. See the docs: https://dlang.org/spec/function.html#closures If you need to manipulate instance members from a C callback, you'll need a way to implement a mechanism to work out which instance you need. Perfect, that's the info I needed. As these functions were in a class, setting channelDone and unmuteMusic to static worked. As an aside, in that doc it says "The .funcptr property of a delegate will return the function pointer value as a function type". So I also tried Mix_ChannelFinished(().funcptr); and this compiled, but caused a segfault when the callback ran. What would have caused this? Is it because it's a C function?
Re: Connecting python to D on socket of localhost : target machine actively refuses connection
I've tried opening the port for TCP with windows 10 firewall settings. Same result. What tool would best help me debug this? Wireshark or is that too low level?
Connecting python to D on socket of localhost : target machine actively refuses connection
Here's my minimal D code (server.d): module server; import core.thread; import std.socket; import std.experimental.logger; class Server : Thread { private: Socket listener; int backlog; string address; ushort port; SocketSet sockSet; Socket[] clients; bool running; public: this(ushort port, string address="") { super(& run); if (address == "") address = "DESKTOP-T49RGUJ"; this.port = port; this.address = address; backlog = int.max; listener = null; running = false; } bool setupSocket() { try { listener = new Socket(AddressFamily.INET, SocketType.STREAM); listener.bind(new InternetAddress(address, port)); sockSet = new SocketSet(); } catch (Exception e) { log(LogLevel.critical, e.toString()); return false; } return true; } void start() { if (listener is null) { if (! setupSocket()) return; } running = true; if (! isRunning) super.start(); } void stop() { running = false; } private: void run() { char[1024] buffer; while(running) { sockSet.reset(); sockSet.add(listener); foreach (client; clients) sockSet.add(client); if (Socket.select(sockSet, null, null)) { foreach (client; clients) { if (sockSet.isSet(client)) { auto got = client.receive(buffer); client.send(buffer[0 .. got]); } } if (sockSet.isSet(listener)) { auto newSocket = listener.accept(); newSocket.send("Hello!\n"); clients ~= newSocket; } } } } } And here's the simple python client (main.py): from PyQt5.QtWidgets import QApplication, QMainWindow import sys import socket import settings if __name__ == "__main__": app = QApplication([]) window = QMainWindow() window.show() host = socket.gethostname() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #sock.bind((host, 0))# have os choose random available port print(host) sock.connect((host, settings.debugPort)) try: # Send data message = 'This is the message. It will be repeated.' print(sys.stderr, 'sending "%s"' % message) sock.sendall(message.encode()) # Look for the response amount_received = 0 amount_expected = len(message) while amount_received < amount_expected: data = sock.recv(16) amount_received += len(data) print(sys.stderr, 'received "%s"' % data) finally: print(sys.stderr, 'closing socket') sock.close() sys.exit(app.exec_()) --- The client throws: builtins.ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it Now, true this is python & D, but the client is generic and minimal so bear with me. Thanks. I've also tried 'localhost' on both sides.
Re: How to get DnD to work in GTKD?
On Friday, 22 September 2017 at 02:57:32 UTC, Joseph wrote: On Saturday, 16 September 2017 at 14:33:53 UTC, Mike Wey wrote: On 16-09-17 06:33, Joseph wrote: I've used null in place of [te]. I'm not sure what target entry is for and if that is the problem or what. I am trying to drag files from windows explorer to a grid or label(I duplicated the code above for the label) and none the callbacks are ever called. I only need the filename of the file being dragged. I will eventually also need to drag one list element to another(virtually so, I just need to know the index that was dragged). Thanks. You will also need to set an TargetList to tell gtk that you want to receive text: ``` TargetList lst = new TargetList([]); lst.addTextTargets(0); w..dragDestSetTargetList(lst); ``` for simple cases only `addOnDragDataReceived` will be needed, `addOnDragDataGet` is only used for the source and `addOnDragDrop` can be used to filter the things that can be droped. List and Treeviews there are funtions like `getDragDestRow` available with the TreeView widget. Any ideas on this? I can drag text in the app itself to the app but I can't drag outside of the app, e.g., a file from windows explorer. This is the code: TargetEntry te = new TargetEntry("audio", GtkTargetFlags.OTHER_APP, 0); TargetList lst = new TargetList([]); lst.addImageTargets(1, false); lst.addTextTargets(0); // Add drag and drop for audio files w.dragDestSet(GtkDestDefaults.ALL, null, GdkDragAction.COPY); w.dragDestSetTargetList(lst); w.addOnDragDataReceived((dragContext, x, y, selectionData, info, time, widget) { // TODO: Add drag and drop writeln("ok2"); }); ok2 is printed only when I drag from inside the app to inside the app(works with text, not sure if anything else as I didn't try it) but can't seem to get anything from the outside to come in ;/ Give that OTHER_APP is set I'd expect at least text outside the app to be draggable in to it, but that is not the case(I get the 'no sign' for that one, while for files I get the drag icon). Ok, I had to use the following auto tel = [new TargetEntry("text/plain", GtkTargetFlags.OTHER_APP, 0),new TargetEntry("text/uri-list", GtkTargetFlags.OTHER_APP, 1), new TargetEntry("image/jpeg", GtkTargetFlags.OTHER_APP, 2),new TargetEntry("text/csv", GtkTargetFlags.OTHER_APP, 3)]; The file entries are passed as text/uri-list. I cannot drag text to the app but luckily I don't really need that.
Re: Problems with function as parameter
On Friday, 22 September 2017 at 02:32:56 UTC, Josh wrote: Why should the binding force nothrow? I don't understand why you HAVE to not throw exceptions. Is it because of the C -> D aspect? Yes, it's because D exceptions are not guaranteed to propagate through the C callstack. It works on some compiler/platforms, but not others. I wrote an article at Gamedev.net (which apparently no longer picks up the site's stylesheets) which shows one way of dealing with it. I've modified my approach since then (and should write a better article about it), but the basic idea still holds. https://www.gamedev.net/articles/programming/general-and-gameplay-programming/d-exceptions-and-c-callbacks-r3323/
Re: Problems with function as parameter
On Friday, 22 September 2017 at 02:32:56 UTC, Josh wrote: Why should the binding force nothrow? I don't understand why you HAVE to not throw exceptions. Is it because of the C -> D aspect? Yes, it's because D exceptions are not guaranteed to propagate through the C callstack. It works on some compiler/platforms, but not others. I wrote an article at Gamedev.net (which apparently no longer picks up the site's stylesheets) which shows one way of dealing with it. I've modified my approach since then (and should write a better article about it), but the basic idea still holds.
Re: Problems with function as parameter
On Friday, 22 September 2017 at 02:22:46 UTC, Josh wrote: src\mixer.d(80,22): Error: function pointer Mix_ChannelFinished (extern (C) void function(int channel)) is not callable using argument types (extern (C) void delegate(int channel)) Code: void unmuteAfterPlaySound() { Mix_ChannelFinished(); } extern (C) void channelDone(int channel) { unmuteMusic(); } The error message indicates that `channelDone` is a member of a class or a struct. A pointer to a member function is a delegate (or closure), not a function pointer. Free functions, static nested functions, and static member functions all produce function pointer. Non-static member functions and non-static nested functions all produce delegates/closures. See the docs: https://dlang.org/spec/function.html#closures If you need to manipulate instance members from a C callback, you'll need a way to implement a mechanism to work out which instance you need.
Re: How to get DnD to work in GTKD?
On Saturday, 16 September 2017 at 14:33:53 UTC, Mike Wey wrote: On 16-09-17 06:33, Joseph wrote: I've used null in place of [te]. I'm not sure what target entry is for and if that is the problem or what. I am trying to drag files from windows explorer to a grid or label(I duplicated the code above for the label) and none the callbacks are ever called. I only need the filename of the file being dragged. I will eventually also need to drag one list element to another(virtually so, I just need to know the index that was dragged). Thanks. You will also need to set an TargetList to tell gtk that you want to receive text: ``` TargetList lst = new TargetList([]); lst.addTextTargets(0); w..dragDestSetTargetList(lst); ``` for simple cases only `addOnDragDataReceived` will be needed, `addOnDragDataGet` is only used for the source and `addOnDragDrop` can be used to filter the things that can be droped. List and Treeviews there are funtions like `getDragDestRow` available with the TreeView widget. Any ideas on this? I can drag text in the app itself to the app but I can't drag outside of the app, e.g., a file from windows explorer. This is the code: TargetEntry te = new TargetEntry("audio", GtkTargetFlags.OTHER_APP, 0); TargetList lst = new TargetList([]); lst.addImageTargets(1, false); lst.addTextTargets(0); // Add drag and drop for audio files w.dragDestSet(GtkDestDefaults.ALL, null, GdkDragAction.COPY); w.dragDestSetTargetList(lst); w.addOnDragDataReceived((dragContext, x, y, selectionData, info, time, widget) { // TODO: Add drag and drop writeln("ok2"); }); ok2 is printed only when I drag from inside the app to inside the app(works with text, not sure if anything else as I didn't try it) but can't seem to get anything from the outside to come in ;/ Give that OTHER_APP is set I'd expect at least text outside the app to be draggable in to it, but that is not the case(I get the 'no sign' for that one, while for files I get the drag icon).
Re: Problems with function as parameter
On Friday, 22 September 2017 at 02:18:34 UTC, Mike Parker wrote: On Thursday, 21 September 2017 at 22:05:22 UTC, Matt Jones wrote: On Thursday, 21 September 2017 at 20:21:58 UTC, Josh wrote: I'm trying to write a callback function for SDL_mixer through Derelict, but this is the first time I've tried to use a function as a parameter, and so I think I'm just making a minor mistake somewhere. [...] Make it a C function, not a D function: extern (C) void channelDone(int channel) { unmuteMusic(); } and use & to reference the function instead of calling it: Mix_ChannelFinished(); It should be extern(C) and, ideally, nothrow. The binding should be enforcing nothrow, but currently doesn't. I'll change that now. Why should the binding force nothrow? I don't understand why you HAVE to not throw exceptions. Is it because of the C -> D aspect?
Re: Problems with function as parameter
On Thursday, 21 September 2017 at 22:05:22 UTC, Matt Jones wrote: On Thursday, 21 September 2017 at 20:21:58 UTC, Josh wrote: I'm trying to write a callback function for SDL_mixer through Derelict, but this is the first time I've tried to use a function as a parameter, and so I think I'm just making a minor mistake somewhere. [...] Make it a C function, not a D function: extern (C) void channelDone(int channel) { unmuteMusic(); } and use & to reference the function instead of calling it: Mix_ChannelFinished(); Thanks for the help, but when I try that, I get: src\mixer.d(80,22): Error: function pointer Mix_ChannelFinished (extern (C) void function(int channel)) is not callable using argument types (extern (C) void delegate(int channel)) Code: void unmuteAfterPlaySound() { Mix_ChannelFinished(); } extern (C) void channelDone(int channel) { unmuteMusic(); }
Re: Problems with function as parameter
On Friday, 22 September 2017 at 02:18:34 UTC, Mike Parker wrote: and use & to reference the function instead of calling it: Mix_ChannelFinished(); To expand on this, D allows functions to be called without parentheses. `channelDone` is actually a function call, whereas in C, it's treated as a function pointer. In D, you have to take the address of a function just as you would any other type, hence ``.
Re: Problems with function as parameter
On Thursday, 21 September 2017 at 22:05:22 UTC, Matt Jones wrote: On Thursday, 21 September 2017 at 20:21:58 UTC, Josh wrote: I'm trying to write a callback function for SDL_mixer through Derelict, but this is the first time I've tried to use a function as a parameter, and so I think I'm just making a minor mistake somewhere. [...] Make it a C function, not a D function: extern (C) void channelDone(int channel) { unmuteMusic(); } and use & to reference the function instead of calling it: Mix_ChannelFinished(); It should be extern(C) and, ideally, nothrow. The binding should be enforcing nothrow, but currently doesn't. I'll change that now.
Re: Problems with function as parameter
On Thursday, 21 September 2017 at 20:21:58 UTC, Josh wrote: I'm trying to write a callback function for SDL_mixer through Derelict, but this is the first time I've tried to use a function as a parameter, and so I think I'm just making a minor mistake somewhere. [...] Make it a C function, not a D function: extern (C) void channelDone(int channel) { unmuteMusic(); } and use & to reference the function instead of calling it: Mix_ChannelFinished();
Re: How to check if string is available at compile time
On Thursday, 21 September 2017 at 13:52:25 UTC, Meta wrote: On Thursday, 21 September 2017 at 12:30:15 UTC, David Bennett wrote: On Thursday, 21 September 2017 at 11:42:36 UTC, David Bennett wrote: enum isCTstring(alias arg) = (!isAssignable!(typeof(arg)) || __traits(compiles, mixin(` "foo" ~ `~__traits(identifier, arg; [snip] But this seems quite hackish... any better ideas? Try __traits(compiles, { enum _ = arg; }). Creating an enum necessarily requires that its value is available at compile time. Ahh, warping it in {} seems to change the timing of the execution, this is starting to make a lot of sense to me now. (also explains why int[arg] works). Thats much cleaner and I'll use that from now on. Thanks a lot! David
Re: Getting the size of a type tuple
On 09/21/2017 09:59 PM, H. S. Teoh wrote: On Thu, Sep 21, 2017 at 09:49:14PM +0200, ag0aep6g via Digitalmars-d-learn wrote: [...] 3) Declaring a packed struct in a function literal that gets immediately called: enum size_so_very_clever(Types ...) = () { struct S { align(1) Types fields; } return S.sizeof; } (); I'd just do: template sizeofStruct(Types...) { struct S { align(1) Types fields; } enum sizeofStruct = S.sizeof; } Skip the CTFE implied by the function literal, the compiler already knows the size very well. Yup. That's better.
Problems with function as parameter
I'm trying to write a callback function for SDL_mixer through Derelict, but this is the first time I've tried to use a function as a parameter, and so I think I'm just making a minor mistake somewhere. The C SDL docs say: // make a channelDone function void channelDone(int channel) { printf("channel %d finished playing.\n", channel); } ... // set the callback for when a channel stops playing Mix_ChannelFinished(channelDone); And my D code is: void unmuteAfterPlaySound() { Mix_ChannelFinished(channelDone); } void channelDone(int channel) { unmuteMusic(); } But DMD seems to be trying to run channelDone() i.e. with no parameters and parentheses omitted, and is giving this error: Error: function Mixer.channelDone (int channel) is not callable using argument types () Error: function pointer Mix_ChannelFinished (extern (C) void function(int channel)) is not callable using argument types (_error_) Is anyone able to see what I've done wrong? Any help would be appreciated, thanks.
Re: Getting the size of a type tuple
On Thu, Sep 21, 2017 at 09:49:14PM +0200, ag0aep6g via Digitalmars-d-learn wrote: [...] > 3) Declaring a packed struct in a function literal that gets > immediately called: > > enum size_so_very_clever(Types ...) = () { > struct S { align(1) Types fields; } > return S.sizeof; > } (); > I'd just do: template sizeofStruct(Types...) { struct S { align(1) Types fields; } enum sizeofStruct = S.sizeof; } Skip the CTFE implied by the function literal, the compiler already knows the size very well. T -- What are you when you run out of Monet? Baroque.
Re: [OT] Converting booleans to numbers
On 9/21/17 3:24 PM, Timon Gehr wrote: This is a good alternative, maybe arrange it like this: dfs(a + 1, b); dfs(a, b + 1); dfs(a - 1, b); dfs(a, b - 1); Yes, better! Just need to make sure no code is duplicated. (For example, there could be more work to do in each loop iteration, and then you'd need to use a local function.) Hm... I suppose you would do that work at the beginning of dfs, like you check the limits? -Steve
Re: Getting the size of a type tuple
On Thursday, 21 September 2017 at 19:49:14 UTC, ag0aep6g wrote: I don't have a one-liner, but here are some other solutions that might be interesting. None of them is particularly pretty, though. 1) Recursive template: 2) Using the std library: 3) Declaring a packed struct in a function literal that gets immediately called: I think the recursive one looks best, but I agree. None of them look particularly good.
Re: Getting the size of a type tuple
On 09/21/2017 08:44 PM, David Zhang wrote: Given the function F, where: F(Args...)(Args args) { ... } How can I statically determine the size of the argument list in bytes? Preferably, I would like a one-liner. However, std.algorithm doesn't seem to support tuples, or `Args.each!(T => T.sizeof).sum` would work. For the moment, I've settled on using a helper function: size_t size(Args...)() { size_t size; foreach(Arg; Args) size += Arg.sizeof; return size; } But it's a bit clunky. Is there a more idiomatic way to do this? I don't have a one-liner, but here are some other solutions that might be interesting. None of them is particularly pretty, though. 1) Recursive template: template size_recur(Types ...) { static if (Types.length == 0) enum size_recur = 0; else enum size_recur = Types[0].sizeof + size_recur!(Types[1 .. $]); } 2) Using the std library: template size_std(Types ...) { import std.algorithm: sum; import std.range: only; import std.meta: staticMap; enum sizeOf(T) = T.sizeof; enum size_std = staticMap!(sizeOf, Types).only.sum; } 3) Declaring a packed struct in a function literal that gets immediately called: enum size_so_very_clever(Types ...) = () { struct S { align(1) Types fields; } return S.sizeof; } ();
Re: [OT] Converting booleans to numbers
On 21.09.2017 17:53, Steven Schveighoffer wrote: On 9/21/17 11:48 AM, Steven Schveighoffer wrote: On 9/21/17 11:06 AM, Timon Gehr wrote: foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } So am I, but I wasn't commenting on trade-offs, only the view that there are no good uses. This seems way easier for me to grok, and is how I would write it. dfs(a + 1, 0); dfs(a - 1, 0); dfs(0, b + 1); dfs(0, b - 1); Of course, without bugs :) ... It was the same bug in every copy. Impressive! ;) dfs(a + 1, b); dfs(a - 1, b); dfs(a, b + 1); dfs(a, b - 1); -Steve This is a good alternative, maybe arrange it like this: dfs(a + 1, b); dfs(a, b + 1); dfs(a - 1, b); dfs(a, b - 1); Just need to make sure no code is duplicated. (For example, there could be more work to do in each loop iteration, and then you'd need to use a local function.)
Getting the size of a type tuple
Given the function F, where: F(Args...)(Args args) { ... } How can I statically determine the size of the argument list in bytes? Preferably, I would like a one-liner. However, std.algorithm doesn't seem to support tuples, or `Args.each!(T => T.sizeof).sum` would work. For the moment, I've settled on using a helper function: size_t size(Args...)() { size_t size; foreach(Arg; Args) size += Arg.sizeof; return size; } But it's a bit clunky. Is there a more idiomatic way to do this? Thanks
Re: [OT] Converting booleans to numbers
On Wednesday, 20 September 2017 at 19:25:58 UTC, Timon Gehr wrote: Actually, it is useful enough to have a Wikipedia page: https://en.wikipedia.org/wiki/Iverson_bracket Example of a good use: void floodFill(dchar[][] data,dchar c,int i,int j) { void dfs(int a, int b) { if (a<0 || a >= data.length) return; if (b<0 || b >= data[a].length) return; if (data[a][b] == c) return; data[a][b] = c; foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } } dfs(i, j); } I would rather use an explicit function for such use cases: int delta(bool x) { return x == true ? 1 : 0; }
Re: [OT] Converting booleans to numbers
On 9/21/17 11:48 AM, Steven Schveighoffer wrote: On 9/21/17 11:06 AM, Timon Gehr wrote: foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } So am I, but I wasn't commenting on trade-offs, only the view that there are no good uses. This seems way easier for me to grok, and is how I would write it. dfs(a + 1, 0); dfs(a - 1, 0); dfs(0, b + 1); dfs(0, b - 1); Of course, without bugs :) dfs(a + 1, b); dfs(a - 1, b); dfs(a, b + 1); dfs(a, b - 1); -Steve
Re: [OT] Converting booleans to numbers
On 9/21/17 11:06 AM, Timon Gehr wrote: foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } ... So am I, but I wasn't commenting on trade-offs, only the view that there are no good uses. This seems way easier for me to grok, and is how I would write it. dfs(a + 1, 0); dfs(a - 1, 0); dfs(0, b + 1); dfs(0, b - 1); -Steve
Re: [OT] Converting booleans to numbers
On 20.09.2017 23:13, nkm1 wrote: Example of a good use: void floodFill(dchar[][] data,dchar c,int i,int j) { void dfs(int a, int b) { Example of a good use: void floodFill(dchar[][] data,dchar c,int i,int j) { void dfs(int a, int b) { if (a<0 || a >= data.length) return; if (b<0 || b >= data[a].length) return; if (data[a][b] == c) return; data[a][b] = c; foreach(i; 0 .. 4){ dfs(a + (i==0) - (i==1), b + (i==2) - (i==3)); } } dfs(i, j); } I don't agree it's a good use. Well, you can trust me that it is. ;) Actually, that seems quite obfuscated to me. It's actually straightforward. This C code is obfuscated: #define C , #define S(X) "Fizz"X"Buzz" int main(){ char j[]="00",*k=j+1,*g[]={k,S(C),S()}; while(':'-*j) ++*k>'9'&&++*j&&(1<:*g=j:>='0'), puts(g[!((*j+*k)%3)|2*(3==*k%5)]); return 0; } (And yet, you are probably able to guess what it does.) Consider: (I had considered that.) foreach (point; [[1, 0], [-1, 0], [0, 1], [0, -1]]) { dfs(a + point[0], b + point[1]); } void floodFill(dchar[][] data,dchar c,int i,int j) @nogc { I.e., I'd possibly call this a bad use of array literals. ;) (The fix is to initialize a static array of static arrays.) Also, it's not really a point, rather, it's a delta. Finds some random 10 programmers and ask them what's easier to understand... Personally, I think it is a tie as both are obvious. Also, in my experience (in C and C++) it is extremely rare for programmers to use booleans in arithmetic. So even if in some situation you would have to replace this thing with more verbose (i == 0 ? 1 : 0), it's no big deal. I didn't say it was. OTOH, booleans being numbers is a source of some bugs (just like other cases of weak typing). Not a ton of bugs, but the utility of implicit conversion to numbers is so unnoticeable that I'm sure it's just not worth it. So am I, but I wasn't commenting on trade-offs, only the view that there are no good uses.
Re: How to check if string is available at compile time
On Thursday, 21 September 2017 at 12:30:15 UTC, David Bennett wrote: On Thursday, 21 September 2017 at 11:42:36 UTC, David Bennett wrote: [snip] ``` string[] escapeCTFE(Args...)(){ static foreach (arg; Args){ static if(__traits(compiles, ###WHATDOIPUTHERE###)){ [snip] So far the best I've come up with is : ``` enum isCTstring(alias arg) = (!isAssignable!(typeof(arg)) || __traits(compiles, mixin(` "foo" ~ `~__traits(identifier, arg; string[] escapeCTFE(Args...)(){ static foreach (arg; Args){ static if(isCTstring!(arg)){ pragma(msg, "Do work on string: ", arg); }else{ pragma(msg, __traits(identifier, arg), " can only be read at runtime"); } } return new string[32]; } ``` But this seems quite hackish... any better ideas? Try __traits(compiles, { enum _ = arg; }). Creating an enum necessarily requires that its value is available at compile time.
Re: How to check if string is available at compile time
On Thursday, 21 September 2017 at 11:42:36 UTC, David Bennett wrote: [snip] ``` string[] escapeCTFE(Args...)(){ static foreach (arg; Args){ static if(__traits(compiles, ###WHATDOIPUTHERE###)){ [snip] So far the best I've come up with is : ``` enum isCTstring(alias arg) = (!isAssignable!(typeof(arg)) || __traits(compiles, mixin(` "foo" ~ `~__traits(identifier, arg; string[] escapeCTFE(Args...)(){ static foreach (arg; Args){ static if(isCTstring!(arg)){ pragma(msg, "Do work on string: ", arg); }else{ pragma(msg, __traits(identifier, arg), " can only be read at runtime"); } } return new string[32]; } ``` But this seems quite hackish... any better ideas?
How to check if string is available at compile time
Hi Guys, Is there an easy way to check if the value of string passed to a template is available at compile time? Here is a cut down example of that I'm doing: ``` string[] escapeCTFE(Args...)(){ static foreach (arg; Args){ static if(__traits(compiles, ###WHATDOIPUTHERE###)){ pragma(msg, "Do work on string: ", arg); }else{ pragma(msg, __traits(identifier, arg), " can only be read at runtime"); } } } void main(){ string a = "a"; static string b = "b"; enum string c = "c"; immutable string d = "d"; const string e = "e"; enum escape_as_much_as_possible = escapeCTFE!(a,b,c,d,e,"f"); } ``` I know for ints I can use __traits(compiles, int[arg]) but I'm not sure about strings. I believe only a and b should be hidden from pragma right? Thanks, David.