Re: Implicit conversions through purity
On Tuesday, 15 April 2014 at 18:02:00 UTC, bearophile wrote: Steve Teale: Since this is D-Learn, I can be indignant, and say that D needs to get its act together, and have a clean definition of 'pure'. What you describe is not only undocumented, but also far too complicated - pure weak nothrow dontpiss kissmyass @never, and so on if the direction continues. There is a nice article on D purity that I suggest you to read. Unfortunately I don't remember the link. To design a system language as complex as C++/D you need lot of mathematics and theory. Andrei is good in computer science theory and in complex programming too, but Walter is less mathematically-minded and this could be visible in the design of some parts of D. Anyway, everyone is doing their best, Walter is very good and he has all my respect. And in a real-world system language a clean definition of pure (like the original pure implementation of D) is not very useful. The current definition of pure of D is good enough and it's a part very near to be completely implemented (unlike many other parts of D like synchronized, scope, SIMD, vector operations, operator overloading, dynamic libraries, GC, and more). So please don't be too much indignant, we don't have the research laboratories of Microsoft :-) Nontheless, thank you for your assiduous efforets to make D internally consistent. In the end I am not doing much. At best I can only hope to spot some sharp corners of the language, and ask for them to be smoothed. But it's very hard to make progress. And lately Andrei (perhaps rightfully) has raised the bar regarding the acceptable breaking changes. And people like Kenji have a mind better than mine (able to think about tens of corner cases, able to keep in mind many complex interactions, etc) even when they are sleeping :-) Bye, bearophile Like I said, I allowed myself the luxury of being indignant because we were hidden away on D Learn. I have total respect for Walter. For one thing he is a self-taught programmer like me, though much more advanced, and I've known him on and off since the Zortech days in 1988. I don't much about Andrei and Kenji, except that they are out of my league. I guess that rather than complain that the compiler does not appear to conform to the definition, I should help by trying to improve the documentation. Anyway my view on the original subject is that the implicit conversion should be allowed for the out case, but not the ref. Steve
Re: Implicit conversions through purity
On Monday, 14 April 2014 at 15:16:07 UTC, bearophile wrote: Steven Schveighoffer: For that reason, I would disallow out parameters from casting implicitly. A number of things perplex me here. 1) If I attempt to compile foo2() more or less as presented with 2.065, the compiler tells me: Error: '_adDupT' is not nothrow Error: function 'mu.foo2' is nothrow yet may throw What version is the discussion about? 2) If I have a simple program as follows, the compiler does not complain about me altering the value of global a. import std.stdio; string a = aaa; void foo2(in string s, ref string sOut) pure { auto s2 = s.dup; s2[0] = 'a'; sOut = cast(string) s2; // Error: cannot implicitly convert } void main() { { foo2(xyz, a); writeln(a); } 3) Using a ref parameter for a pure function seems to me to be a clear indication of intended side effect. Wikipedia on pure functions says it's not allowed. Out does seem somehow different to me, since it's initial value is by definition throw-away. Steve
Re: Implicit conversions through purity
On Tuesday, 15 April 2014 at 09:41:57 UTC, bearophile wrote: Yes, foo2 is weakly pure, but main is not tagged as pure, so main is free to use a global reference. If you mark main pure, your code will not compile even if you comment out the writeln. D is working as designed here. 3) Using a ref parameter for a pure function seems to me to be a clear indication of intended side effect. In D you can also have const ref. A mutable ref makes the function weakly pure at best. Wikipedia on pure functions says it's not allowed. D has both strongly pure and weakly pure functions (and later the compiler has added const-ly pure and another category, all invisible. Out does seem somehow different to me, since it's initial value is by definition throw-away. Yes, this is true in theory. I don't know if this is also true in D in practice, because D out has some problems. Bye, bearophile Since this is D-Learn, I can be indignant, and say that D needs to get its act together, and have a clean definition of 'pure'. What you describe is not only undocumented, but also far too complicated - pure weak nothrow dontpiss kissmyass @never, and so on if the direction continues. Nontheless, thank you for your assiduous efforets to make D internally consistent. Steve
Re: How to hand in a closure variable
On Friday, 4 April 2014 at 15:15:55 UTC, bearophile wrote: Bienlein: What I was actually looking for was how to get this to work: immutable int b = if(1 == 1) { return 123; } else { return 456; }; immutable b = (1 == 1) ? 123 : 456; Bye, bearophile You said you did not like ternary expressions ;=) Steve
Check for presence of function
What's the cool/idiomatic D way to test at compile time if a struct has a member function with a particular signature? Along the lines of: struct Unrelated { ... } template isSomething(T) { enum bool isSomething = is(typeof( (inout int = 0) { T???; // has a function void doSomething(Unrelated* up); // etc })); } struct Thingie { ... } static assert(isSomething!(Thingie)); Thanks Steve
Re: Check for presence of function
On Sunday, 23 March 2014 at 13:23:58 UTC, Dicebot wrote: On Sunday, 23 March 2014 at 13:03:07 UTC, Adam D. Ruppe wrote: That won't necessarily work in the presence of overloaded functions since getMember only gets one of them. Yeah, forgot to add this part, will make end result a bit less pretty indeed. Updated version with overloads will be more reliable than proposed duck-typing version as it won't false trigger in presence of alias this or opDispatch. Though Steve may actually want it to trigger, I don't know. DB, In my particular question, I would not have wanted, or cared if alias this was triggered, but that was a narrow view. My primary point is that there should be something in the wiki to help old-fashioned programmers like me to change from an OOP style that is not 100% necessary, to a struct based style that should be quicker, but that allows the compiler to help me, or other contributors to the same project, to write add-on components that are at least checked at compile time. So what I'm after really, is how do you do interfaces outside of OOP. Std.range does that sort of thing in what seem to me to be very simple cases, but there is a lot of scope for different scenarios. Thanks for your answer Steve
Casting an interface to the type that implements it.
This might be equivalent to 'How to do multiple inheritance in D'. I have a class ControlSet, that is just a bunch of widgets. I use it in various places to represent the contents of dialogs that are associated with some class. All such classes have to do is define themselves using the CSTarget interface thus: class Base: CSTarget ... class Whatever: Base ... The ControlSet class has a data member host, of type CSTarget. When I propagate a button-click or whatever, I use host.csNotify(Widget w, int id); // Bam!!! This works fine in my app, and the ControlSet has been a wonderfully reliable and useful part of my armoury. However, when I try to dispatch the same notification across the boundary between my app, and a dynamically loaded plugin module, the app crashes. I can fix the crash by casting host to the base type of the class that contains it: (cast(Base) host).csNotify(Widget w, int id); // Fine ;=) I believe I need some sort of compile-time skullduggery to define this cast information at the point where my ControlSet instances are declared. Either that, or I need to pass a delegate to the constructor that I can somehow use to replace the cast. What is the D way of doing this? Thanks Steve
Re: Linux Dynamic Loading of shared libraries
On Sunday, 9 March 2014 at 14:09:28 UTC, Tolga Cakiroglu wrote: For this, you create an Interface that matches to the method declaration of your class. But notice that instead of defining methods, you will define attributes those types' match to that class's methods. I did this before and it works. At least with Posix dlsym function's help. OK, so then what goes wrong here: module exta; class ExtA { int n; this(int _n) { n = _n; } int foo() { return ++n; } } ExtA getInstance(int n) { return new ExtA(n); } compiled with: dmd exta.d -c -fPIC -shared dmd exta.o -shared -defaultlib=libphobos2.so -L-rpath=. module main; import core.runtime; import std.stdio; extern(C) void* dlsym(void*, const char*); extern(C) void dlclose(void*); interface ExtA { int foo(); } void main() { void* lib = Runtime.loadLibrary(exta.so); if (lib is null) { writeln(library not loaded); return; } writeln(loaded); void* vp = dlsym(lib, _D4exta11getInstanceFiZC4exta4ExtA\0.ptr); if (vp is null) { writeln(symbol not found); return; } writeln(got symbol); ExtA function(int) f = cast(ExtA function(int)) vp; ExtA x = f(42); if (x is null) { writeln(no class object); return; } int n = x.foo(); writefln(n = %d, n); Runtime.unloadLibrary(lib); } compiled with: dmd -c main.d dmd main.o -L-ldl -defaultlib=libphobos2.so -L-rpath=. output: loaded got symbol n = 9 Segmentation fault (core dumped) The answer should be 43. The segfault happens on the Runtime.unloadLibrary(lib); call. Any ideas? Steve
Re: Linux Dynamic Loading of shared libraries
On Sunday, 9 March 2014 at 12:07:22 UTC, Steve Teale wrote: Now suppose that my D shared library contains a class, rather that just module ctors/dtors, how do I go about creating an instance of that class and using its methods? After wandering down several dead-end paths, and help from other contributors, I have finally come up with something that looks like the basis of a plugin pattern for Linux DMD using shared objects (.so files). This is somewhat long for a forum post. You can download this readme and the associated files from britseyeview.com/plugin101.tar.bz2 To get started, you need a base class that provides declarations for all functions that the plugin will be allowed to use externally. Why base class, and not interface? Well I guess because interfaces don't provide any information about data. If you create a shared library based on an interface, then all the shared object methods that reference data in the class that implements the interface fail miserably. I'm sure someone will explain why - probably some obvious thing I have overlooked. OK, so my base class is: module plugin; class Plugin { int n; this(int _n) { n = _n; } int foo() { return int.min; } void bar() {} } The class that implements this base in the shared library is: module exta; import plugin; import std.stdio; import std.math; class ExtA: Plugin { double d; this(int n) { super(n); d = PI; } override int foo() { return ++n; } override void bar() { writefln(Done my thing (%f), d); } } Plugin getInstance(int n) { return new ExtA(n); } shared static this() { writeln(exta.so shared static this); } shared static ~this() { writeln(exta.so shared static ~this); } The module ctor/dtor are included because that has become conventional in discussions about dynamic loading. Otherwise, the so has the class implementation - ExtA, and a shared method to create an instance of same. It includes references to methods in Phobos. The test program is as follows: module main; import core.runtime; import std.stdio; import plugin; extern(C) void* dlsym(void*, const char*); alias Plugin function(int) pfi; Plugin getPlugin(string name) { void* lib = Runtime.loadLibrary(name~.so); if (lib is null) { writeln(failed to load plugin shared object); return null; } void* vp = dlsym(lib, _D4exta11getInstanceFiZC6plugin6Plugin\0.ptr); if (vp is null) { writeln(plugin creator function not found); return null; } pfi f = cast(pfi) vp; Plugin x = f(42); if (x is null) { writeln(creation of plugin failed); return null; } return x; } void main() { Plugin x = getPlugin(exta); int n = x.foo(); writefln(n = %d, n); x.bar(); } The long symbol name used in the dlsym() call is of course from the .map file generated when the .so file is created These can be built using the following primitive makefile, whose main purpose is to spell out the required compiler flags: main : dmd -c plugin.d dmd -c -shared -fPIC exta.d dmd exta.o -shared -defaultlib=libphobos2.so -map dmd -c main.d dmd main.o plugin.o -L-ldl -defaultlib=libphobos2.so -L-rpath=. This assumes that the plugins will be in the same directory as the executable (rpath=.). Note that there is no call to Runtime.unloadLibrary(). The assumption her is that once the plugin has been loaded it will be there for the duration of the program. If you want to unload it you'll probably have to make sure the plugin object is purged from memory first, and I have not discovered how to do that yet ;=( Steve
Linux Dynamic Loading of shared libraries
Martin Nowak's Gihub druntime Page has module main; import core.runtime, core.thread; void main() { auto lib = Runtime.loadLibrary(./liba.so); auto thr = new Thread({ auto lib = Runtime.loadLibrary(./liba.so); Runtime.unloadLibrary(lib); }); thr.start(); thr.join(); Runtime.unloadLibrary(lib); } module liba; import std.stdio; shared static this() { writeln(shared static this()); } shared static ~this() { writeln(shared static ~this()); } static this() { writeln(static this()); } static ~this() { writeln(static ~this()); } Now suppose that my D shared library contains a class, rather that just module ctors/dtors, how do I go about creating an instance of that class and using its methods? Steve
Re: Template mixins - why only declarations
On Thursday, 6 March 2014 at 18:36:12 UTC, Dejan Lekic wrote: Template mixins can't contain statements, only declarations, because they (template mixins) are a way to inject code into the context. Therefore it makes sense to forbid statements, as they can't appear in ANY context. If I side-step slightly, the compiler does not appear to have difficulty coping: import std.stdio; import std.conv; string codeString(string A, string B, int I)() { enum n = I*3; return writeln(\~A~\); writeln(\~B~\); writefln(\%d\,~to!string(n)~);; } void foo() { mixin(codeString!(One, Two, 1)()); writeln(Hello world); } void main() { foo(); }
Re: Compiling D through command line
On Friday, 7 March 2014 at 16:59:30 UTC, Bauss wrote: What arguments would I do to compile a d project through command line. Been trying a few things, but can't get it working. I always get Error: cannot read file x Read around the net and it most says it's an installation error and that reinstalling should fix it, but it works when compiling through a few IDE's so I assume it's mistake of my own. Tried like this: -c c:\testproject\main.d -m32 -ofc:\testd\out.exe Take a step back. Your file is in folder c:\testproject, so do cd \testproject dmd main.d Then look for a file called main.exe in the \testproject folder. I may be off the mark, since I have not used dmd under Windows for quite a long time, but try it.
Re: Nobody understands templates?
On Sunday, 2 March 2014 at 10:05:05 UTC, Dicebot wrote: There is nothing wrong about not using templates. Almost any compile-time design can be moved to run-time and expressed in more common OOP form. And using tool you have mastery of is usually more beneficial in practice than following the hype. Yes DB, we can soldier on happily, but it would not do any harm to understand templates. The documentation examples quickly make your eyes glaze over, looking at the code in Phobos is doubtless instructive, but you can wade through a lot of that without finding what you want. Also I discovered an interesting fact today. the word 'mixin' does not appear in the language reference Templates section of dlang.org. It should be used in at least one example. I just discovered by trial and error that I could use 'mixin' in Templates (as opposed to Template Mixins), and when you know that it seems likely that you can accomplish lots of stuff you couldn't before. While I'm here, has anyone discovered a way to fudge a constructor super(..) call in a mixin template that's included in a class constructor. Since the mixin template is evaluated in the scope of the constructor, it seems like it should be OK. I'm sure I'll get there in time ;=) Steve
Re: Nobody understands templates?
On Sunday, 2 March 2014 at 15:23:03 UTC, H. S. Teoh wrote: This is a pretty good primer to templates: https://semitwist.com/articles/article/view/template-primer-in-d The trouble is with most of these tutorials that they offer examples that are things you would probably never want to do. I can already add an int to an int, or a double to a double, or an int to a double. Perhaps the examples should pick on something like vector operations, but then who would be doing those with int, or some class? It would be doubles or pairs of, as in struct Coord. I believe readers would study documentation and examples much more carefully if they were things they might realistically want to do. And that won't be type conversion - std.conv already does a pretty good job on that. So what? We could really do with a place where template savvy open source contributors could publish interesting examples of template use. Otherwise, Joe Soap, like me, can spend a great deal of time and effort in: a) Determining when the use of a template might be advantageous, b) Hacking at test programs to determine what the documentation means, and what works, and what doesn't. c) After that, deciding whether it would be just as effective to use two or three separate methods. Steve Steve
Re: Nobody understands templates?
On Friday, 28 February 2014 at 19:06:26 UTC, Dicebot wrote: On Friday, 28 February 2014 at 18:42:57 UTC, Steve Teale wrote: Is this typical - libraries use templates, applications don't, or am I just being unimaginative? Steve Also every time you catch yourself doing any sort of copy-paste, it is quite possible that it can be replaced by mixin / template mixin instead. Application that are built in more declarative way benefit more from such tool set than traditional imperative ones. In have a couple of case that always require me to find some other instance of it, and then copy/paste, But then I need to edit the pasted code anyway because in any particular case it needs to deal with different command info, so how can mixins help me? I have already dealt with the yada-yada cases by old-fashioned OOP. From the various answers to this question I have concluded that I should not worry about it. If there's a need for a template I think I am already recognizing it. Thanks!all() Steve
Re: Nobody understands templates?
On Saturday, 1 March 2014 at 22:16:54 UTC, woh wrote: You probably don't have a good understanding of templates if you have only used 2 in your entire codebase. Or you are talking about a very tiny codebase. That's just what us template-blind people want to hear - confirmation that we are in fact stupid. The project I'm talking about is about 3 loc excluding blank lines and comments. What I'd like to see is a tool, or a switch on the compiler that emits the code generated by templates. We - the template-blind - would have it sussed in a heartbeat then. Steve
Re: enum abuse
On Friday, 28 February 2014 at 11:47:45 UTC, Vladimir Panteleev wrote: A const or immutable declaration would declare a constant variable - meaning, unless it is optimized out at a later point, it will end up in the data segment and have its own address. An enum declares a manifest constant - it exists only in the memory of the compiler. Manifest constants make sense when doing metaprogramming. Constant/immutable declarations make sense for values that will be used in multiple places by code at runtime. I'm with Mike - thanks Vlad, that makes it perfectly clear. I just wonder slightly why a language that prides itself so on its metaprogramming capabilities does not have a keyword that makes it obvious Think of an abbreviation for compile-time-constant. But yes, thanks. BTW, why does an immutable integer type need to have an address? Steve
Re: @disable this for structs
On Friday, 28 February 2014 at 16:02:26 UTC, Dicebot wrote: ... Mmm, simple question, complicated answer. But the first one was enough for me at this point.
Nobody understands templates?
All the D aficionados seem to wet their pants over meta-programming, but I struggle to find a place to use it. IIRC, I used it in a couple of places when I was trying to write library stuff for MySQL, but in my current project, I use it only once. That's when I want to stuff something onto my undo stack. For that I have two template functions - push(T)(MybaseClass* p, T t, int ID), and pushC, which is just the same except that it checks the top of the stack to see if the ID there is the same as what it is wanting to push. This has served me very reliably, but I struggle to find other places in the whole application where I would benefit from templates. Is this typical - libraries use templates, applications don't, or am I just being unimaginative? Steve
Re: @disable this for structs
On Thursday, 27 February 2014 at 18:13:43 UTC, Namespace wrote: On Thursday, 27 February 2014 at 18:10:38 UTC, Steve Teale wrote: Could someone please explain what you would use this for to an old man rooted in C++, but who loves D. Where does it fit in relative to 42? ;=( Steve It's for explicit initialization: struct Foo { } Foo f; // no problem struct Bar { @disable this(); } Bar b; // error So it is just a reminder that you need to initialize Bar in some specific way?
@disable this for structs
Could someone please explain what you would use this for to an old man rooted in C++, but who loves D. Where does it fit in relative to 42? ;=( Steve
DUB Error
What does the somewhat cryptic DUB error Trying to append absolute path. mean. By a process of elimination, the offending line in the json file is importPaths: [/usr/local/include/d/gtkd-2] Steve
Re: DUB Error
On Wednesday, 26 February 2014 at 03:33:38 UTC, Jesse Phillips wrote: On Tuesday, 25 February 2014 at 14:32:42 UTC, Steve Teale wrote: What does the somewhat cryptic DUB error Trying to append absolute path. mean. By a process of elimination, the offending line in the json file is importPaths: [/usr/local/include/d/gtkd-2] Steve The path you have provide is an absolute path, I suspect that somewhere in the code it is doing something like: buildPath(curDir, importPath); However, buildPath doesn't have a check for appending absolute path, so probably a custom path library which is basically saying your ignoring the working directory. I guess I was misunderstanding 'importPaths'. I got a little further along when I used dflags: [/usr/local/include/d/gtkd-2] instead. But you'd think that since it is targeting D, importFlags might have that purpose. Steve
Re: Treat memory as a file with a name.
If it's the same librsvg as below, then it looks like it has an API function which can also load a SVG from memory: https://developer.gnome.org/rsvg/2.40/RsvgHandle.html#rsvg-handle-new-from-data To answer your original question, I think the best way to do this is to create a pipe on the filesystem. Once created, you can feed data through it without touching the disk. Thanks Vladimir, My librsvg is 2.36, but rsvg-handle-new-from-data pre-dates that, so it should be good. Thanks for the link - I had clearly been looking at some crap documentation. Thanks for the pipe idea too - it will come in handy one day, and I'd completely forgotten about pipes. Steve
Treat memory as a file with a name.
This is probably not exactly a D question. The library librsvg expects to get an SVG file filename. I have the data of such a file in memory. How do I dress up that memory as a file with a name so that I can pass the name to the librsvg open function. I've looked at std.mmfile, and played with it, giving a name to the constructor, along with the address and size of my memory block. import std.mmfile; import std.stdio; import std.stream; void main() { char[] ca; ca.length = 10; ca[] = 'X'; MmFile mmf = new MmFile(glob, 0, 10UL, ca.ptr); std.stream.File sf = new std.stream.File(glob, FileMode.In); char[] b; b.length = 20; sf.readExact(b.ptr, 20); writefln(%s, b); } But then I just get 'No such file or directory', which is what I'd expect after I'd taken the trouble to read mmfile.d. I had expected it to create a stub entry in the file system or something, and the somehow use fmemopen(), but it just looks for an existing file. At the moment I'm having to write the data to a temporary file, and then pass the name of the temp to rsvg. There must be some elegant way to do this!
Re: 64 bit size_t
Rather than change it to int/ulong, just change it to 'size_t len = parent.children.length+1' (or auto instead of size_t). This way it's proper for both 32-bit and 64-bit and you don't need to worry about architecture. If you do need a signed version, you can use ptrdiff_t. Yup, that's what I did when my head returned to its usual postion ;=)
64 bit size_t
Why is it that with 32 bit compilation, int is 32 bits, but apparently this convention is not followed in 64 bit compilation. I have not installed the 64 bit compiler yet, but apparently int len = parent.children.length+1; provokes the following error acomp.d(782): Error: cannot implicitly convert expression (parent.children.length + 1LU) of type ulong to int parent is just a straightforward array What is size_t for 64 bit? Steve
Re: 64 bit size_t
On Monday, 17 February 2014 at 07:15:20 UTC, Steve Teale wrote: Why is it that with 32 bit compilation, int is 32 bits, but apparently this convention is not followed in 64 bit compilation. I have not installed the 64 bit compiler yet, but apparently int len = parent.children.length+1; provokes the following error acomp.d(782): Error: cannot implicitly convert expression (parent.children.length + 1LU) of type ulong to int parent is just a straightforward array What is size_t for 64 bit? Steve Sorry parent.children is just a straightforward array
Re: 64 bit size_t
On Monday, 17 February 2014 at 07:17:06 UTC, Steve Teale wrote: What is size_t for 64 bit? Steve Sorry parent.children is just a straightforward array Sorry again - forget about it. I'd forgotten that D actually says int is 32 bits, and ulong is 64, and size_t for a 64 bit machine is obviously 64. I'll just go through the code and either change int to ulong or use a cast. ;=(
Re: Ranges, constantly frustrating
On Tuesday, 11 February 2014 at 10:52:40 UTC, Tobias Pankrath wrote: The second naive solution would be to use readText and splitLines. That's the sort of thing I always do because then I understand what's going on, and when there's a bug I can find it easily! But then I'm not writing libraries. Steve
Re: App release build crashes
On Friday, 7 February 2014 at 07:43:05 UTC, Steve Teale wrote: I was attempting to to build my app COMPO using a Makefile this morning, and at first this worked to some extent, but after some fiddling with compiler flags to make a release version that then had problems, I reverted to my original makefile as of yesterday. That builds and links the app, but when I run it I get Fatal Error while loading '/usr/lib/i386-linux-gnu/libphobos2.so.0.64': The module 'std.regex' is already defined in './compo'. My Makefile has: LFLAGS = -L-L/usr/lib/i386-linux-gnu -L-L/usr/local/lib -L-L/home/steve/COMPO -L-lusps4cb -L-lgtkd-2 -L-lrsvg -L-lphobos2 -L-ldl -L-lpthread -L-lm -L-lrt compo: $(OBJFILES) gcc -o compo $(OBJFILES) $(LFLAGS) If I use static phobos2 -L-l:libphobos2.a, it runs OK. Building via CodeBlocks using phobos2 shared library works OK judging by the smaller executable size. What is wrong with my linker flags? Possibly nothing - I was using binutils-gold, and reverting to the Gnu linker fixed that. However the version built with phobos shared crashes in use, and I have to delve into that before I can say where.
App release build crashes
I was attempting to to build my app COMPO using a Makefile this morning, and at first this worked to some extent, but after some fiddling with compiler flags to make a release version that then had problems, I reverted to my original makefile as of yesterday. That builds and links the app, but when I run it I get Fatal Error while loading '/usr/lib/i386-linux-gnu/libphobos2.so.0.64': The module 'std.regex' is already defined in './compo'. My Makefile has: LFLAGS = -L-L/usr/lib/i386-linux-gnu -L-L/usr/local/lib -L-L/home/steve/COMPO -L-lusps4cb -L-lgtkd-2 -L-lrsvg -L-lphobos2 -L-ldl -L-lpthread -L-lm -L-lrt compo: $(OBJFILES) gcc -o compo $(OBJFILES) $(LFLAGS) If I use static phobos2 -L-l:libphobos2.a, it runs OK. Building via CodeBlocks using phobos2 shared library works OK judging by the smaller executable size. What is wrong with my linker flags?
Re: Is this reasonable?
On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale wrote: Here I feel like a beginner, but it seems very unfriendly: import std.stdio; struct ABC { double a; int b; bool c; } ABC[20] aabc; void foo(int n) { writefln(n: %d, aabc.length: %d, n, aabc.length); if (n aabc.length) writeln(A); else writeln(B); } void main(string[] args) { int n = -1; foo(n); } Oh my, what a hornet's nest! I'd settle for an error that said that it's not permissible to compare a negative integer with a size_t. But almost any way you go is ugly. Thank you all. I feel less like a beginner now ;=)
Is this reasonable?
Here I feel like a beginner, but it seems very unfriendly: import std.stdio; struct ABC { double a; int b; bool c; } ABC[20] aabc; void foo(int n) { writefln(n: %d, aabc.length: %d, n, aabc.length); if (n aabc.length) writeln(A); else writeln(B); } void main(string[] args) { int n = -1; foo(n); } This comes back with B. If I change the test to (n cast(int) aabc.length), then all is well. Is this unavoidable, or could the compiler safely make the conversion implicitly?
Passing ref through a template chain
To bind variables, the MySQL api wants their addresses - in my tiny example below, these are represented by the void*[]. If I just use something like setTarget in the example, it works fine, but then when I try to set a bunch of them in one go I'm hosed because I can't get the right addresses through the chain. import std.stdio; void*[2] vpa; void setTarget(T)(ref T t, int i) { vpa[i] = t; } void setSeveral(T...)(ref T args) { foreach (int i, arg; args) setTarget(arg, i); } //ref.d|19|Error: variable i cannot be read at compile time| //ref.d|19|Error: variable i cannot be read at compile time| //ref.d|19|Error: Integer constant expression expected instead of cast(uint)i| /* void setSeveral2(T...)(ref T args) { for (int i = 0; i args.length; i++) setTarget(args[i], i); } */ void main() { bool a; int b; setSeveral(a, b); writefln(orig %x %x, set %x %x, a, b, vpa[0], vpa[1]); // addresses differ } The problem arises I believe in 'foreach (int i, arg; args)' which makes a copy for 'arg'. Usually in a foreach I can get round that by making it 'ref arg'. But in the template function that does not work. I can't use the setSeveral2() form, because that provokes the errors shown in the comments. How can I force the real addresses through the chain? Thanks Steve
Re: Passing ref through a template chain
Works like a charm, and it's so obvious a thing to try that I'm kicking myself. Thanks Steve
Re: std.datetime impenetrable
Oh, so it is difficult after all! I thought it was just me. So I am probably going to have to ask. Then the interesting question will be which way around will offend fewest people. I have installed it as ISO, then have to ask US users if they would prefer Letter Size, or the other way round then all those Euro and Indian users say 'typical American programmer!'. Thanks for the rundown anyway. Steve
std.array.array extended example to supplement that in std.array
import std.array; import std.range; import std.stdio; // A contrived input range struct Sir { string s; int pos; bool empty() { return pos = s.length; } void popFront() { pos++; } int front() { return s[pos]-'0'; } } int[] da = [1,2,3,4,5]; int[5] sa = [1,2,3,4,5]; void main() { auto a1 = array(da); // dynamic array writefln([%s], a1); auto a2 = array(sa[]); // slice (all) of static array writefln([%s], a2); auto a3 = array([1,2,3,4,5][]);// ditto writefln([%s], a3); Sir sir; sir.s = 12345; assert(isInputRange!(Sir)); auto a4 = array(sir); writefln([%s], a4); }
Template instantiation without (...)
Which bit of the spec for template instantiation is it that allows the last two lines of the following to compile and work? import std.stdio; struct A { int a; } template Thingie(T) { static if (is(T == int)) enum Thingie = 1; else enum Thingie = 0; } void main() { writefln(%d, Thingie!(int)); writefln(%d, Thingie!int); writefln(%d, Thingie!A); }
Re: Template instantiation without (...)
I suppose it's the part of the spec you're about to write a patch for. I guess so. It was discussed on one of the forums back in October 2008. I guess it got implemented but never made the documentation.
Re: Template instantiation without (...)
I suppose it's the part of the spec you're about to write a patch for. Twas at: http://www.digitalmars.com/d/archives/digitalmars/D/ Template_instantiation_syntax_77507.html#N77507
Re: Creating a logging library and have questions
sybrandy Wrote: On 02/03/2010 12:03 AM, Rainer Deyke wrote: sybrandy wrote: 1) I use the current core.thread library and put all my messages in a buffer that the thread checks periodically, pulls off a new message, and then writes it to a file. There will be some work to make sure nothing collides with each other, but I think I can manage it. Wouldn't this allow logging messages to be lost before a hard crash? To me, that would greatly reduce the utility of the logging system. If done improperly, yes, it would. My hope is that if I did go with this method, I would try to find a way to ensure no data was lost. Oddly enough, I'm currently having that problem with the single-threaded version for some reason. The test program will stop and some of the logging statements never make it to the file. 3) Something else. I really don't have much experience with threading, so I'm being very careful and really want to understand it. This library looks to be a good way to learn, however if it's not the best way to do things, then what would be? Global mutex associated with the logging system. Lock, output, unlock. There are scalability issues with that approach, but I don't see why it wouldn't work in this situation. (Plus, if you have a message queue, you probably need to protect that queue with a mutex anyway.) Understood. My goal is that if I do put the writing in another thread, I do my best to ensure it will scale. I have a tendency to put a lot of logging statements in code when I'm trying to debug something, so I don't want to slow things down too much nor do I want to lose anything. In short: I want the log writing to be as out of the way as possible. Casey I second Rainer. A logging system should commit (at least) error messages immediately, particularly if the application has multiple threads. Otherwise it is going to make debugging a crashing system a nightmare. When I do it I just stick 'synchronized' in front of the statement that does the write.
Re: Finding out about D - 102
Ary Borenszweig Wrote: Steve Teale wrote: OK, so structs are a different beast in D than they are in C++. This results in one of my most common pitfalls. I'll find myself writing: struct A { int a; int b; } A[] nameTooLong = ...; foreach (whatever; thingie) { nameTooLong[whatever.whatever].a = whatever.x*3; nameTooLong[whatever.whatever].b = whatever.y/3; with(nameTooLong[whatever.whatever]) { a = whatever.x*3; b = whatever.y/3; } Ary, Yes I use with quite often, it's when I have two of the beasts where I want to use with at the same time that I have fallen into this. Now that I've rubbed my nose in it I'm sure I won't do it again.
Re: Finding out about D - 101
Steven Schveighoffer Wrote: This tells me that a string in D is a sequence of characters (whatever that might mean) in memory, prefixed by a size_t length. Of course, that's not to say there is no more to it, but the values for 'xtra' don't give us much clue. If there was some other member of struct S, I'd kind of expect to see bit flags there indicating whether the array of char was invariant, const, or fair game. So I'm left with the question as to how does 'invariant' have teeth? invariant is not a runtime flag, but rather a type modifier. The teeth of invariance only exist during compilation, once you're in runtime, the expectation is that the compiler will have weeded out all your attempts to change the invariant data, so no need to keep track of its invariance. It is not immune to casting. And BTW, string is invariant(char)[], not invariant(char[]), which is a distinct difference. The former is a mutable array of invariant characters, the latter is an invariant array of invariant characters. You can't change the length or reassign an invariant(char[]), but you can reassign/append to an invariant(char)[]. The xtra flags do not exist. You are printing out garbage data on the stack (most likely the pointer field of ca). -Steve Great, so there are experienced D programmers checking on this newsgroup! I'd kind of figured out from the test program that the invariant thing was just compile time, but thanks for pointing out my misconception about the string alias. I should read things more carefully. - Also Steve
Finding out about D - 102
OK, so structs are a different beast in D than they are in C++. This results in one of my most common pitfalls. I'll find myself writing: struct A { int a; int b; } A[] nameTooLong = ...; foreach (whatever; thingie) { nameTooLong[whatever.whatever].a = whatever.x*3; nameTooLong[whatever.whatever].b = whatever.y/3; // more of the same sort of stuff } So I get fed up typing 'nameTooLong[whatever.whatever]', and instead I write foreach (whatever; thingie) { A ntl = nameTooLong[whatever.whatever]; ntl.a = whatever.x*3; ntl.b = whatever.y/3; // more of the same sort of stuff } Then I chase a bug in my program, which compiled OK. After some time, I realize that A ntl = nameTooLong[whatever.whatever]; is doing a copy, which is not what I was thinking about at all - old C++ habits. ntl = ...; has no effect whatsoever on nameTooLong[whatever.whatever]. So then - pissed off by that point - I rewrite it as: foreach (whatever; thingie) { A* ntl = nameTooLong[whatever.whatever]; // This suggests an ambiguity in the language? ntl.a = whatever.x*3; ntl.b = whatever.y/3; // more of the same sort of stuff } This works OK, but it's still not the D way to do things. Try: foreach (whatever; thingie) { alias nameTooLong[whatever.whatever] ntl; ntl.a = whatever.x*3; ntl.b = whatever.y/3; // more of yer same sort of stuff }