Re: Request assistance initializing struct instance at global scope
On 12/7/20 10:56 PM, Adam D. Ruppe wrote: On Monday, 7 December 2020 at 04:13:16 UTC, Andrew Edwards wrote: Given: === extern(C): char*[] hldr; Why is this extern(C)? A D array ere is probably wrong. To stay as close to the original implementation as possible. This will all change when the entire code base compiles in D. In C, a `char*[] hldr = {...}` is actually represented in D as a static length array, like `char*[1] = [null];` Thanks. Because I was having issues I didn't know how to resolve, I actually defined it as `string ft` instead and passed around `ft.ptr` when calling It should also generally be __gshared if it was declared in C (C defaults to global, D defaults to thread-local), and if declared in C, an additional extern may be required. Noted. I'll keep that in mind when trying to link to C in the future. So, if you are trying to *link* to C code that has this: I'm porting it. All of the code is available from the D source file. You'd bind to it in D with --- // D extern(C) extern __gshared char*[1] hldr; // matches the C. Make sure the length matches too Ok, got it. S[] s = [S(cast(char*) "c", [0])]; // that cast is super iffy though. Should S have `const(char)* ft` instead? Probably. I just did a direct port. They had char* so I just kept it that way. I'll change it to string once the initial port is complete. But I'll remember that when I come across it in the future. In that thing: extern(C) - tells it it has a C name. extern - tells it the actual variable is declared externally. This second one makes the linker pull the variable's address from the C code instead of declaring a new variable in D that can be used from C. __gshared - turn off D's thread local default to match C's global. Learning has occurred. Thanks. Now if you are translating C code to D, that might be different, certainly the second extern is wrong then, and you need to copy over the initial value but the rest still works: This. ``` // no more second extern, D is now creating a new variable, then it needs to know the value too extern(C) __gshared char*[1] hldr = [null]; Okay. I'll need to be mindful of this in the future. But to resolve the issue this time around, I just used a string[] since that's the end state anyway. // rest is the same // including S[] s = [S(cast(char*) "c", [0])]; // since it is a gshared static array, this still works ``` Yup... got this to compile with main() and static this() in the correct location. But there's a few other contexts that might change this, then you probably do want the static constructor, or maybe you can make some things immutable and make it work that way. All depends on a bit more information than your code gives on its own Thanks for the lesson... I've learned quite a lot.
Re: Request assistance initializing struct instance at global scope
On 12/7/20 10:12 PM, Jacob Carlborg wrote: On Monday, 7 December 2020 at 04:13:16 UTC, Andrew Edwards wrote: You can either use `extern(C) char*[] hldr` to make only `hldr` have C linkage. Use `extern(C) {}` to group several symbols which should have C linkage or rearrange the code so that `static this` is above `extern(C):`. -- /Jacob Carlborg Thanks Jacob. The extern(C) is temporary. I'm doing a direct port of the code to D using -betterC. Wanted to keep it as close to the original as possible until everything compiles. I noticed that static this() does not work if either it or main() (or both) is marked extern(C). To fix the issue, I simply moved the static this() and main() above the extern(C) and the deprecation error disappears. Andrew
Request assistance initializing struct instance at global scope
Given: === extern(C): char*[] hldr; enum I = (1<<0); struct S { char* ft; char** fm; int f; } void main(){} === How do I initialize an instance of S at global scope? // Not sure how to do this... so try to keep as close to original as possible // Nope, does not work S[] s = [ { cast(char*)"c", [0], I }, ] // Error: static variable C_HL_extensions cannot be read at compile time S[] s = [ S(cast(char*)"c", [0], I) ]; // Error Deprecation: static constructor can only be of D linkage S[] s; static this() { s = [ S(cast(char*)"c", [0], I) ]; } Thanks, Andrew
Re: Interfacing to C++: Cannot access value from namespace
On Saturday, 7 September 2019 at 12:39:25 UTC, Ali Çehreli wrote: On 09/07/2019 03:26 AM, Andrew Edwards wrote: > [1] I did not declare any of the other member variables from the struct, > don't know if this is a source of the problem. Yes, it definitely is a problem. The members are accessed as byte offsets into their objects. Without defining the other members, your D-side member is read from offset 0, which is not the case on the C++ side. However, I'm still not sure whether that would solve the problem due to the following differences between C++ and D: That was it, and yes it solves the problem. There are far too many variables to define at the moment so I found the offsetof() and defined a "void[offset] pad" to take care of the issue for right now. Thanks, Andrew
Re: Interfacing to C++: Cannot access value from namespace
On Saturday, 7 September 2019 at 12:30:53 UTC, Andrew Edwards wrote: On Saturday, 7 September 2019 at 12:24:49 UTC, Ali Çehreli wrote: On 09/07/2019 03:26 AM, Andrew Edwards wrote: > float continuallyUpdatedValue; > float continuallyChangingValue; // [1] They mean the same thing for an English speaker but compilers don't know that (yet?). :) Ali LOL. Sorry about that, I decided to change the variable name in the middle of writing the post and missed one. Andrew The problem existed prior to this naming mishap and remains after correcting it.
Re: Interfacing to C++: Cannot access value from namespace
On Saturday, 7 September 2019 at 12:24:49 UTC, Ali Çehreli wrote: On 09/07/2019 03:26 AM, Andrew Edwards wrote: > float continuallyUpdatedValue; > float continuallyChangingValue; // [1] They mean the same thing for an English speaker but compilers don't know that (yet?). :) Ali LOL. Sorry about that, I decided to change the variable name in the middle of writing the post and missed one. Andrew
Interfacing to C++: Cannot access value from namespace
I'm running into the following issue when attempting to interface with C++: // C++ namespace MySpace { MyType& GetData(); } struct MyType { // ... float continuallyUpdatedValue; // ... }; // call site MySpace::GetData().continuallyUpdatedValue; // D extern (C++, MySpace) MyType* GetData(); struct MyType { float continuallyChangingValue; // [1] } // call site MySpace.GetData().continuallyUpdatedValue; // <--- This is not being updated by C++ [1] I did not declare any of the other member variables from the struct, don't know if this is a source of the problem.
Re: C++ vs D: Default param values and struct to array casting
On Friday, 6 September 2019 at 18:31:29 UTC, Ali Çehreli wrote: On 09/06/2019 02:14 AM, Andrew Edwards wrote: > I'm seeking some pointers on how to define these in D Here is my attempt: Ali, this is awesome. It solves all 4 problems in on shot. I definitely don't intend on using the undefined aspect in the future but it is welcomed at the moment. Much appreciated. Andrew
Re: C++ vs D: Default param values and struct to array casting
On Friday, 6 September 2019 at 11:35:59 UTC, a11e99z wrote: https://dlang.org/spec/simd.html This didn't work two well because I wont be able to access the members by name as C++ library expects. Will consider during refactoring. also probably u can do https://run.dlang.io/is/WMQE93 Ended up using this since it provides for named access and solves the overloading requirement. Thanks, Andrew
Re: C++ vs D: Default param values and struct to array casting
On Friday, 6 September 2019 at 09:49:33 UTC, Johan Engelen wrote: On Friday, 6 September 2019 at 09:14:31 UTC, Andrew Edwards wrote: C++ allows the for following: struct Demo { float a, b, c, d; Demo() { a = b = c = d = 0.0f; } Demo(float _a, float _b, float _c, float _d) { a = _a; b = _b; c = _c; d = _d; } float operator[] (size_t i) const { return ()[i]; } //[3] "()[i]" is undefined behavior in C++. You cannot index into struct members like that. Of course it may work in certain cases, but UB is UB. Don't do it! I found a more detailed explanation for you: https://stackoverflow.com/questions/40590216/is-it-legal-to-index-into-a-struct -Johan Thanks for the clarification and link. This is a example taken from a popular library I’m trying to port to D. I’m not trying to do it in C++ myself, just to understand how to interface to the code so that I can get a reference example compiled in D. Andrew
Re: C++ vs D: Default param values and struct to array casting
On Friday, 6 September 2019 at 09:14:31 UTC, Andrew Edwards wrote: C++ allows the for following: struct Demo { float a, b, c, d; Demo() { a = b = c = d = 0.0f; } Demo(float _a, float _b, float _c, float _d) { a = _a; b = _b; c = _c; d = _d; } float operator[] (size_t i) const { return ()[i]; } //[3] float& operator[] (size_t i) { return ()[i]; } //[4] } This is my thought on how to accomplish op overloading: struct Test { float a, b, c, d; float opIndex(size_t i) in(i >= 0 && i <= 3) { final switch(i) { case 0: return a; case 1: return b; case 2: return c; case 3: return b; } } void opIndexAssign(float val, size_t i) in(i >= 0 && i <= 3) { final switch(i) { case 0: a = val; break; case 1: b = val; break; case 2: c = val; break; case 3: d = val; break; } } } Please advise if I've gone off the beaten path. It seems overkill for the two lines of code C++ requires so any suggestion is greatly appreciated.
C++ vs D: Default param values and struct to array casting
C++ allows the for following: struct Demo { float a, b, c, d; Demo() { a = b = c = d = 0.0f; } Demo(float _a, float _b, float _c, float _d) { a = _a; b = _b; c = _c; d = _d; } float operator[] (size_t i) const { return ()[i]; } //[3] float& operator[] (size_t i) { return ()[i]; } //[4] } void fun(float col[3]) { // do fun stuff } void moreFun(const Demo& d = Demo(0.1f, 0.3f, 7.5f, 1.5f)) // [1] { // you guessed it... more fun stuff } int main(int argv, const char** argc) { Demo inst = Demo(0.1f, 0.3f, 7.5f, 1.5f); fun((float*)); // [2] moreFun(); return 0; } I'm seeking some pointers on how to define these in D so that I can instantiate them in D while still linking to the associated C++ library or object file for the implementation. The main points of contention are at [1] and [2] because I have no idea how to accomplish these. I assume that I can accomplish [3] and [4] with opIndex() and opIndexAssign(), however I'm not understanding the slicing of the memory address at the first member variable. I know that by indexing the memory address at the member variable we are able treat the struct as an array but i do not understand how to implement it in D. I read the documentation at https://dlang.org/spec/cpp_interface.html and https://dlang.org/articles/cpptod.html but it was not clear "to me" how to overcome these issues. Andrew
Re: Linking to -framework on MacOS
On Thursday, 5 September 2019 at 18:26:41 UTC, DanielG wrote: And depending on the version of macOS / which framework you're linking to, you might need to specify a search path as well (-F): lflags "-framework" "SomeFramework" "-framework" "AnotherFramework" "-F/Library/Frameworks" IIRC I didn't need that -F parameter on 10.9, but now I do with 10.14. But it's for my own frameworks, not system ones. I am on 10.14 as well and Adam's solutions works well with the system provided frameworks. Thanks.
Re: Linking to -framework on MacOS
On Thursday, 5 September 2019 at 12:30:33 UTC, Jacob Carlborg wrote: On 2019-09-04 17:12, Andrew Edwards wrote: Worked like a charm: -L/System/Library/Frameworks/Cocoa.framework/Cocoa This probably not a good idea. It relies on how a framework is structured internally. Adam's solution is the correct one. Thanks. That is the one I went with because it was not dependent on the file structure and it was quite a bit shorter.
Re: getting rid of immutable (or const)
On Thursday, 5 September 2019 at 08:16:08 UTC, Daniel Kozak wrote: On Thu, Sep 5, 2019 at 9:55 AM berni via Digitalmars-d-learn wrote: I still struggle with the concept of immutable and const: > import std.stdio; > > void main() > { > auto p = Point(3); > auto q = p.x; > writeln(typeof(q).stringof); > } > > struct Point > { > @property immutable long x; > } The type of q is immutable(long). But I need a mutable q. I found two ways: a) long q = p.x; b) auto q = cast(long)p.x; Either way I've to specify the type "long" which I dislike (here it's not a real burdon, but with more complicated types it might be). Is there a way, to make q mutable without having to write the type explicitly? in this case you can just use: auto q = cast()p.x; or: auto q = p.x + 0;
Re: Linking to -framework on MacOS
On Wednesday, 4 September 2019 at 15:22:51 UTC, Adam D. Ruppe wrote: On Wednesday, 4 September 2019 at 15:00:52 UTC, Andrew Edwards wrote: Could someone point me in the right direction please? You can also add `-L-framework -LCocoa` to dmd to pass the two arguments to the linker (they need to be separate -L things for the two pieces, which is kinda weird but it works) That's perfect. Thanks.
Re: Linking to -framework on MacOS
On Wednesday, 4 September 2019 at 15:05:46 UTC, rikki cattermole wrote: Four years ago, I was linking against Cocoa via: "lflags-osx": ["/System/Library/Frameworks/Cocoa.framework/Cocoa"], I don't know if this will help you or not. Worked like a charm: -L/System/Library/Frameworks/Cocoa.framework/Cocoa Thank you so much.
Linking to -framework on MacOS
Hello, I'm trying to link to "-framework OpenGL" on MacOS and finding any clues on how to accomplish this. If I pass that switch to clang and use clang to create the executable, it works perfectly but I would like to use dmd to create the executable. Here is the list of errors I'm trying to resolve: dmd dmain main.o imgui_impl_glfw.o imgui_impl_opengl3.o imgui.o imgui_demo.o imgui_draw.o imgui_widgets.o gl3w.o -L-lstdc++ -L-lglfw Undefined symbols for architecture x86_64: "_CFBundleCreate", referenced from: _open_libgl in gl3w.o "_CFBundleGetFunctionPointerForName", referenced from: _get_proc in gl3w.o "_CFRelease", referenced from: _close_libgl in gl3w.o _get_proc in gl3w.o "_CFStringCreateWithCString", referenced from: _get_proc in gl3w.o "_CFURLCreateWithFileSystemPath", referenced from: _open_libgl in gl3w.o "___CFConstantStringClassReference", referenced from: CFString in gl3w.o "_kCFAllocatorDefault", referenced from: _open_libgl in gl3w.o _get_proc in gl3w.o ld: symbol(s) not found for architecture x86_64 Could someone point me in the right direction please?
Re: Basic Linear Algebra and D's Array Operation
On Sunday, 19 May 2019 at 17:13:11 UTC, Alex wrote: The operation itself is, however, a simple one. To implement a basic version I would cite http://rosettacode.org/wiki/Matrix_multiplication#D This is awesome. Thank you very much. Andrew
Re: Basic Linear Algebra and D's Array Operation
On Sunday, 19 May 2019 at 10:07:35 UTC, Alex wrote: On Sunday, 19 May 2019 at 06:34:18 UTC, Andrew Edwards wrote: So the question is, how do I pull this off in D using just builtin arrays and phobos? Any assistance is appreciated. Slice operations exist, but they are defined mainly for arrays and not for arrays of arrays. Some basic operations (like setting) are possible, but as you see, even multiplication fails. You could reinvent something like ´´´ import std; void main() { int[][] M = [[1,2,3],[1,2,3],[1,2,3]]; M.recursiveMultiplier(4); writeln(M); } void recursiveMultiplier(T, V)(T arr, V val) @nogc { static if(isArray!(ElementType!T)) arr.each!(el => el.recursiveMultiplier(val)); else arr[] = arr[] * val; } ´´´ Can you do me a favor and extend it to cover the cases where V is either an array or multidimensional array? The text I'm using has exercise to implement a bunch of matrix operations so that would help out a lot. BUT: As I saw, in the talk, NDarrays are referenced. The common (widely used and recommended) way to use this functionality in D is by using mir.ndslices. http://docs.algorithm.dlang.io/latest/mir_ndslice.html Yes, I'm aware. I'm actually am using Lubeck to accomplish much of this stuff but when it comes to the implementation exercises, I have to ditch the library and stick with vanilla D.
Basic Linear Algebra and D's Array Operation
Sooo... I'm trying to learn this stuff so that I can fully grasp the content of Jens Mueller's 2019 DConf talk and its applications in financial sector (forex and options/futures trading). Unfortunately, I'm doing so using python but I'd like to accomplish the same in D. Here goes: Array (Vector) Algebra auto V = [1, 2, 3]; auto v = V[] * 4; // v == [4, 8, 12] Output: Error: array operation V[] * 4 without destination memory not allowed Huh? What? That makes no sense, but okay... whatever. int[3] v = V[] * 4; // v == [4, 8, 12] v[] = v[] + v[]; // v == [8, 16, 24] v[] = v[] / 2; // v == [4, 8, 12] v[] = v[] - v[]; // v = [0, 0, 0] so far so good. On to the fun stuff. Multidimensional Array (Matrix) Algebra auto M = [[1, 2, 3], [1, 2, 3], [1,2,3]]; int[3][3] m = M[] * 4; Output: Error: incompatible types for (M[]) * (4): int[][] and int Okay, I'm lost on that one. But let's press on. int[3][3] m = M[] * [[4]]; Output: Error: cannot implicitly convert expression M[] * [[4]] of type int[][] to int[] int[3][3] m = M[] * [[4,4,4], [4,4,4], [4,4,4]]; Output: Error: cannot implicitly convert expression M[] * [[4, 4, 4], [4, 4, 4], [4, 4, 4]] of type int[][] to int[] I'm so confused. Maybe it's the way I'm accessing M? int[3][3] m = M[][] * 4; Output: Error: incompatible types for (M[]) * (4): int[][] and int And... it begins again!!! So the question is, how do I pull this off in D using just builtin arrays and phobos? Any assistance is appreciated. Thanks, Andrew P.S. Why do we still have two sets of documentations ([1],[2]) for the language? Which is the official one and when can we get rid of the other? [1] https://dlang.org/library/std/array.html [2] https://dlang.org/phobos/std_array.html
Re: Request some GtkD Assistance
On Wednesday, 27 March 2019 at 19:18:17 UTC, Mike Wey wrote: That because of the way the dmd and the linker interpret the arguments. -L tell dmd to pass the command that follows to the linker. To tell the linker to link with a library in a known location you would use the -l flag. For the value passed to -l the linker will prefix `lib` and postfix `.so` `.a`. So the following should work properly: `dmd -de -w -L-lgtkd-3 nufsaid' Thank you very much Mike. Works like a charm. Also found out that pragma(lib, "gtlkd-3") does the trick as well. --Andrew
Re: Request some GtkD Assistance
On Wednesday, 27 March 2019 at 09:07:37 UTC, Nicholas Wilson wrote: On Wednesday, 27 March 2019 at 06:55:53 UTC, Andrew Edwards wrote: dmd -de -w -Llibgtkd-3.a nufsaid try dmd -de -w -lgtkd-3 nufsaid No. That did not work. dmd -de -w -L/path/to/lib nufsaid This would is already included in dlang.conf no? Yes furnishing an explicit path works. dmd -de -w -L/Users/edwarac/dlang/dmd-2.085.0/osx/lib/libgtkd-3.a nufsaid But why do I need to do that if it's sitting right next to phobos and DMD is already searching that directory for libraries? dlopen(libgdk-3.0.dylib, 258): image not found it that a typo? gdk not gtk? No. This i correct. Regardless gtkD is bindings to gtk which are separate, make sure you have gtk installed and in your path. gtk was the first think I installed, no issues there. I have found a solution to this. brew install gdk+3 does the trick. Thank you.
Request some GtkD Assistance
Good day all, I've installed Gtk+ and GtkD on my MacBookPro which is running macOS Mojave but am having some issues linking to and using it. Any assistance to resolve this is appreciated. Steps taken: 1. Install Gtk+ brew install gtk+ 2. Build and install GtkD-3.8.5 unzip GtkD-3.8.5.zip copy gtkd folder to dmd/osx/src/ make copy libgtkd-3.a to dmd/osx/lib/ 3. Update dmd.conf add -I%@P%/../../src/gtkd to DFLAGS Problems encountered: 1. Unable to find the lib (dmd-2.085.0)BMP:model edwarac$ dmd -de -w -Llibgtkd-3.a nufsaid ld: file not found: libgtkd-3.a clang: error: linker command failed with exit code 1 (use -v to see invocation) Error: linker exited with status 1 Not sure why I'm receiving this first error since the file is stored alongside the libphobos2.a which the linker doesn't have any issues locating. If copy the file to the local directory, linking completes without any further errors. 2. Unable to find libgtkd-3.dylib (dmd-2.085.0)Andrews-MBP:model edwarac$ ./nufsaid object.Exception@generated/gtkd/gtkd/Loader.d(125): Library load failed (libgdk-3.0.dylib): dlopen(libgdk-3.0.dylib, 258): image not found Not sure what's going on here at all. This file was not created when I built GtkD. Where do I find it, or how do I create it? --Andrew
Re: std.functional.compose compilation error
On Thursday, 9 November 2017 at 05:07:33 UTC, Andrew Edwards wrote: On Thursday, 9 November 2017 at 04:58:19 UTC, Chuck Allison wrote: Chuck Allison Sorry to hijack this thread but it shan't be helped. Chuck, how is it going? Curious about the status of "Thinking in D". How do I go about participating in the draft review? -- Andrew And before I forget, where do I pre-order my copy?
Re: std.functional.compose compilation error
On Thursday, 9 November 2017 at 04:58:19 UTC, Chuck Allison wrote: Chuck Allison Sorry to hijack this thread but it shan't be helped. Chuck, how is it going? Curious about the status of "Thinking in D". How do I go about participating in the draft review? -- Andrew
Re: Request Assistance Calling D from C++: weird visibility issue inside struct and namespace
On Wednesday, 8 November 2017 at 08:42:01 UTC, Petar Kirov [ZombineDev] wrote: Walter has recently been working on improving the C++ mangling, so be sure to test the latest dmd nightly build and if that doesn't work be sure to file bug report(s). https://github.com/dlang/dmd/pull/7250 https://github.com/dlang/dmd/pull/7259 https://github.com/dlang/dmd/pull/7272 Done: https://issues.dlang.org/show_bug.cgi?id=17975
Re: Request Assistance Calling D from C++: weird visibility issue inside struct and namespace
On Wednesday, 8 November 2017 at 15:12:05 UTC, MGW wrote: The useful material. https://www.youtube.com/watch?v=HTgJaRRfLPk Useful indeed, thank you.
Re: Request Assistance Calling D from C++: weird visibility issue inside struct and namespace
On Wednesday, 8 November 2017 at 07:30:34 UTC, evilrat wrote: On Wednesday, 8 November 2017 at 06:34:27 UTC, Andrew Edwards just using fully qualified name didn't make it? void call_cpp() { ::foo("do great things"); // calling global foo return; } No, it did not. Are you sure you put it in a namespace in C++ too? Yes. That wasn't the issue otherwise there might be some name mangling incompatibility that probably worth filling a bug report That's the one. Thanks to the hint form, Nicholas Wilson, I was able to track it down and resolve it with a call to pragma(mangle). -Andrew
Re: Request Assistance Calling D from C++: weird visibility issue inside struct and namespace
On Wednesday, 8 November 2017 at 07:06:39 UTC, Nicholas Wilson wrote: On Wednesday, 8 November 2017 at 06:34:27 UTC, Andrew Edwards wrote: I'm having a little bit of problem calling D code from C++ and would appreciate some assistance. First, given the following C++ program wich compiles, links, and runs without any problem: Try using `nm` on the C++ object to find out what it thinks the mangling should be. Check that against the mangling DMD produces. Tried it, and it works. Solution: nm dexample | grep foo -> returns the __C++__mangling Use it to define the function as such: pragma(mangle, "__C++__mangling") extern (C++) void foo(const char* str) { // doing great things; } Thank you so much. -Andrew
Request Assistance Calling D from C++: weird visibility issue inside struct and namespace
I'm having a little bit of problem calling D code from C++ and would appreciate some assistance. First, given the following C++ program wich compiles, links, and runs without any problem: == // example.h SOME_API void foo(const char* str); // example.cpp #include "example.h" namespace SomeApi {} struct SomeStruct {} int main() { foo("do great things"); return 0; } void foo(const char* str) { // doing great things; } == Modify example.cpp to: == // example.cpp #include "example.h" namespace SomeApi {} struct SomeStruct {} void call_cpp() { foo("do great things"); return; } == Then create example.d: == void main() { call_cpp(); } extern (C++) void foo(const char* str) { // doing great things; } == Compile and link and you have D program calling, calling C++, which in turn calls D. My problem is that I've encountered an issue where this does not work: when the function is being called from a namespace or local scope in C++, the linker cannot find the definition. For example: void SomeApi::CallFromNamespace() { foo("do great things"); } or void SomeStruct::CallFromStruct() { foo("do great things"); } In a last-ditch effort, I placed all of these definitions into dexample.d and, it compiled, but still filed to linking: extern (C) void foo(const char* str) { // doing great things; } extern (C++) void foo(const char* str) { // doing great things; } extern (C++, SOME_API) void foo(const char* str) { // doing great things; } extern (D) void foo(const char* str) { // doing great things; } extern void foo(const char* str) { // doing great things; } void foo(const char* str) { // doing great things; } === Linker error returned: === Undefined symbols for architecture x86_64: "foo()", referenced from: SomeStruct::CallFromStruct() in example.o SomeApi::CallFromNamespace() in example.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [dexample] Error 1 Using DMD v2.077.0 on macOS High Sierra -Andrew
Generating DDOX documentation
Given a documented source file (eg. process.d), I can generate the DDOC version of the documentation with the -D switch of DMD as such: $ dmd -Dfprocess.html process.d What do I modify on that line to get the DDOX version of the same file? Thanks, Andrew
Re: What's the best way to programmatically detect the most recent release of DMD and others?
On Monday, 16 October 2017 at 18:21:46 UTC, Jacob Carlborg wrote: On 2017-10-16 17:13, Andrew Edwards wrote: Is there a better way? The official download script [1] is using the following: You're a godsend. Thank you very much.
What's the best way to programmatically detect the most recent release of DMD and others?
The best way I know to determine the latest DMD release is http://ftp.digitalmars.com/LATEST. I'm not aware that such a file exists for LDC and GDC so I'm currently doing: string latest(string url) { return executeShell("git ls-remote --tags " ~ url ~ " | cut -d 'v' -f 2 | cut -d '-' -f 1 | cut -d '^' -f 1 | uniq | tail -n 1").output.strip; } Is there a better way? Thanks, Andrew
Re: What is the best way to use requests and iopipe on gzipped JSON file
On Friday, 13 October 2017 at 22:29:39 UTC, Steven Schveighoffer wrote: It might be tough to do it right, but moot point now, since it's not necessary anyway :) -Steve Yup. Thanks again. Andrew
Re: What is the best way to use requests and iopipe on gzipped JSON file
On Friday, 13 October 2017 at 21:53:12 UTC, Steven Schveighoffer wrote: On 10/13/17 4:27 PM, Andrew Edwards wrote: On Friday, 13 October 2017 at 19:17:54 UTC, Steven Schveighoffer wrote: On 10/13/17 2:47 PM, Andrew Edwards wrote: A bit of advice, please. I'm trying to parse a gzipped JSON file retrieved from the internet. The following naive implementation accomplishes the task: auto url = "http://api.syosetu.com/novelapi/api/?out=json=500=5;; getContent(url) .data .unzip .runEncoded!((input) { ubyte[] content; foreach (line; input.byLineRange!true) { content ~= cast(ubyte[])line; } auto json = (cast(string)content).parseJSON; input is an iopipe of char, wchar, or dchar. There is no need to cast it around. In this particular case, all three types (char[], wchar[], and dchar[]) are being returned at different points in the loop. I don't know of any other way to generate a unified buffer than casting it to ubyte[]. This has to be a misunderstanding. The point of runEncoded is to figure out the correct type (based on the BOM), and run your lambda function with the correct type for the whole thing. Maybe I'm just not finding the correct words to express my thoughts. This is what I mean: // === void main() { auto url = "http://api.syosetu.com/novelapi/api/?out=json=500=5;; getContent(url) .data .unzip .runEncoded!((input) { char[] content; // Line 20 foreach (line; input.byLineRange!true) { content ~= line; } }); } output: source/app.d(20,13): Error: cannot append type wchar[] to type char[] Changing line 20 to wchar yields: source/app.d(20,13): Error: cannot append type char[] to type wchar[] And changing it to dchar[] yields: source/app.d(20,13): Error: cannot append type char[] to type dchar[] I'm not sure actually this is even needed, as the data could be coming through without a BOM. Without a BOM, it assumes UTF8. Note also that getContent returns a complete body, but unzip may not be so forgiving. But there definitely isn't a reason to create your own buffer here. this should work (something like this really should be in iopipe): while(input.extend(0) != 0) {} // get data until EOF This!!! This is what I was looking for. Thank you. I incorrectly assumed that if I didn't process the content of input.window, it would be overwritten on each .extend() so my implementation was: ubyte[] json; while(input.extend(0) != 0) { json ~= input.window; } This didn't work because it invalidated the Unicode data so I ended up splitting by line instead. Sure enough, this is trivial once one knows how to use it correctly, but I think it would be better to put this in the library as extendAll(). ensureElems(size_t.max) should be equivalent, though I see you responded cryptically with something about JSON there :) :) I'll have to blame it on my Security+ training. Switching out the while loop with ensureElements() in the following results in an error: void main() { auto url = "http://api.syosetu.com/novelapi/api/?out=json=500=5;; getContent(url) .data .unzip .runEncoded!((input) { // while(input.extend(0) != 0){} // this works input.ensureElems(size_t.max); // this doesn't auto json = input.window.parseJSON; foreach (size_t ndx, _; json) { if (ndx == 0) continue; auto title = json[ndx]["title"].str; auto author = json[ndx]["writer"].str; writefln("title: %s", title); writefln("author: %s\n", author); } }); } output: Running ./uhost std.json.JSONException@std/json.d(1400): Unexpected end of data. (Line 1:8192) 4 uhost 0x00010b671112 pure @safe void std.json.parseJSON!(char[]).parseJSON(char[], int, std.json.JSONOptions).error(immutable(char)[]) + 86 [etc]
Re: What is the best way to use requests and iopipe on gzipped JSON file
On Friday, 13 October 2017 at 20:17:50 UTC, Steven Schveighoffer wrote: On 10/13/17 3:17 PM, Steven Schveighoffer wrote: this should work (something like this really should be in iopipe): while(input.extend(0) != 0) {} // get data until EOF This should work today, actually. Didn't think about it before. input.ensureElems(size_t.max); -Steve No, it errored out: std.json.JSONException@std/json.d(1400): Unexpected end of data. (Line 1:8192)
Re: What is the best way to use requests and iopipe on gzipped JSON file
On Friday, 13 October 2017 at 19:17:54 UTC, Steven Schveighoffer wrote: On 10/13/17 2:47 PM, Andrew Edwards wrote: A bit of advice, please. I'm trying to parse a gzipped JSON file retrieved from the internet. The following naive implementation accomplishes the task: auto url = "http://api.syosetu.com/novelapi/api/?out=json=500=5;; getContent(url) .data .unzip .runEncoded!((input) { ubyte[] content; foreach (line; input.byLineRange!true) { content ~= cast(ubyte[])line; } auto json = (cast(string)content).parseJSON; input is an iopipe of char, wchar, or dchar. There is no need to cast it around. In this particular case, all three types (char[], wchar[], and dchar[]) are being returned at different points in the loop. I don't know of any other way to generate a unified buffer than casting it to ubyte[]. Also, there is no need to split it by line, json doesn't care. I thought as much but my mind was not open enough to see the solution. Note also that getContent returns a complete body, but unzip may not be so forgiving. But there definitely isn't a reason to create your own buffer here. this should work (something like this really should be in iopipe): while(input.extend(0) != 0) {} // get data until EOF This!!! This is what I was looking for. Thank you. I incorrectly assumed that if I didn't process the content of input.window, it would be overwritten on each .extend() so my implementation was: ubyte[] json; while(input.extend(0) != 0) { json ~= input.window; } This didn't work because it invalidated the Unicode data so I ended up splitting by line instead. Sure enough, this is trivial once one knows how to use it correctly, but I think it would be better to put this in the library as extendAll(). And then: Eventually, something like this will be possible with jsoniopipe (I need to update and release this too, it's probably broken with some of the changes I just put into iopipe). Hopefully combined with some sort of networking library you could process a JSON stream without reading the whole thing into memory. That would be awesome. Again, thank you very much. Andrew
What is the best way to use requests and iopipe on gzipped JSON file
A bit of advice, please. I'm trying to parse a gzipped JSON file retrieved from the internet. The following naive implementation accomplishes the task: auto url = "http://api.syosetu.com/novelapi/api/?out=json=500=5;; getContent(url) .data .unzip .runEncoded!((input) { ubyte[] content; foreach (line; input.byLineRange!true) { content ~= cast(ubyte[])line; } auto json = (cast(string)content).parseJSON; foreach (size_t ndx, record; json) { if (ndx == 0) continue; auto title = json[ndx]["title"].str; auto author = json[ndx]["writer"].str; writefln("title: %s", title); writefln("author: %s\n", author); } }); However, I'm sure there is a much better way to accomplish this. Is there any way to accomplish something akin to: auto url = "http://api.syosetu.com/novelapi/api/?out=json=500=5;; getContent(url) .data .unzip .runEncoded!((input) { foreach (record; input.data.parseJSON[1 .. $]) { // use or update record as desired } }); Thanks, Andrew
Re: DUB dependency issue
On Wednesday, 4 October 2017 at 01:59:48 UTC, Andrew Edwards wrote: Attempting to use iopipe but not sure what I'm doing incorrectly Finally figured it out. For some reason, the init find the local dependency to load but simply adding it to the dub.json afterward resolves the issue.
DUB dependency issue
Attempting to use iopipe but not sure what I'm doing incorrectly I've cloned the repository in /Users/edwarac/git.repo.dir/ then added the path to dub: edwarac-pc:.dub edwarac$ dub add-path /Users/edwarac/git.repo.dir edwarac-pc:.dub edwarac$ dub list Packages present in the system and known to dub: iopipe ~master: /Users/edwarac/git.repo.dir/iopipe/ iopipe:byline ~master: /Users/edwarac/git.repo.dir/iopipe/ iopipe:convert ~master: /Users/edwarac/git.repo.dir/iopipe/ iopipe:unzip ~master: /Users/edwarac/git.repo.dir/iopipe/ iopipe:zip ~master: /Users/edwarac/git.repo.dir/iopipe/ Now I'm trying to init a project with iopipe as a dependency but am receiving the following error: Package recipe format (sdl/json) [json]: Name [syosetsu]: Description [A minimal D application.]: Author name [edwarac]: License [proprietary]: Copyright string [Copyright © 2017, edwarac]: Add dependency (leave empty to skip) []: requests Added dependency requests ~>0.5.3 Add dependency (leave empty to skip) []: iopipe Could not find package 'iopipe'.
Re: OT: What causes the Segfault in the following?
Steven Schveighoffer wrote: On 8/3/17 10:14 PM, Andrew Edwards wrote: I certainly can, but the problem is completely in C, I'm not having any problems in D. In this case, I've simply copied the two functions to test.c and inserted main(). Oh. Then Ali is correct. I assumed that char *s was initialized to null because it was D, and maybe you were passing s by reference incorrectly. But actually, you are in c, so s can point anywhere. Yeah, you need to declare an array instead of just a pointer. char s[20] should work. -Steve Much appreciated.
Re: OT: What causes the Segfault in the following?
Ali Çehreli wrote: On 08/03/2017 06:02 PM, Andrew Edwards wrote: char *s; That's an uninitialized C string. OK, I was is indeed the problem. I was thinking for some reason that s gets initialized inside nk_color_hex_rgb() but it's expecting to an array to work with. I actually noticed that couldn't, for the life of me, associate it to the cause of the resulting issue. nk_color_hex_rgb(s, str); That function is expecting it to have at least 7 chars when doing things like output[1] = (char)NK_TO_HEX((col.r & 0x0F)); So you have to have a proper pointer to the first element of an array to pass to nk_color_hex_rgb. The following may work but you shouldn't be needing to use magic constants like 7: char[7] s; nk_color_hex_rgb(s.ptr, str); // ... printf("%s\n", s.ptr); got you... this makes sense, but I'm doing it differently in D. See my response to Steven. I was only experiencing this issue in C. There's probably the proper C macro that defines it so that you can do char[BLAH_LENGTH] s: Ali Much appreciated.
Re: OT: What causes the Segfault in the following?
Ali Çehreli wrote: On 08/03/2017 06:02 PM, Andrew Edwards wrote: char *s; That's an uninitialized C string. OK, I was is indeed the problem. I was thinking for some reason that s gets initialized inside nk_color_hex_rgb() but it's expecting to an array to work with. I actually noticed that couldn't, for the life of me, associate it to the cause of the resulting issue. nk_color_hex_rgb(s, str); That function is expecting it to have at least 7 chars when doing things like output[1] = (char)NK_TO_HEX((col.r & 0x0F)); So you have to have a proper pointer to the first element of an array to pass to nk_color_hex_rgb. The following may work but you shouldn't be needing to use magic constants like 7: char[7] s; nk_color_hex_rgb(s.ptr, str); // ... printf("%s\n", s.ptr); There's probably the proper C macro that defines it so that you can do char[BLAH_LENGTH] s: Ali
Re: OT: What causes the Segfault in the following?
Steven Schveighoffer wrote: On 8/3/17 9:12 PM, Andrew Edwards wrote: Andrew Edwards wrote: Just in case... here are the two functions being called in main(): https://github.com/vurtun/nuklear/blob/master/nuklear.h#L5695-L5722 Can you show how you declared these in D? It's important. I think what's happening is that the nk_color_hex_rgb is incorrectly defined. I think you should *always* get segfault, with or without any of those arrays. -Steve I certainly can, but the problem is completely in C, I'm not having any problems in D. In this case, I've simply copied the two functions to test.c and inserted main(). Here are my implementations though: nk_color nk_rgb_hex(string rgb) { if (rgb[0] == '#') rgb = rgb[1..$]; return nk_color(cast(nk_byte)nk_parse_hex(rgb[0 .. 2]), cast(nk_byte)nk_parse_hex(rgb[2 .. 4]), cast(nk_byte)nk_parse_hex(rgb[4 .. $]), 255); } private void nk_color_hex_impl(int n)(out char[] output, nk_color col) { output.reserve(n); alias NK_TO_HEX = (i) => i <= 9 ? '0' + i : 'A' - 10 + i; foreach(color; col.tupleof) { output ~= to!char(NK_TO_HEX((color & 0xF0) >> 4)); output ~= to!char(NK_TO_HEX(color & 0x0F)); } } void nk_color_hex_rgba(out char[] output, nk_color col) { nk_color_hex_impl!8(output, col); } void nk_color_hex_rgb(out char[] output, nk_color col) { nk_color_hex_impl!6(output, col); } Not to happy with nk_color_hex_impl and family yet because I'm convinced there is a better way but for now that's what I've got.
Re: OT: What causes the Segfault in the following?
Andrew Edwards wrote: int main() { //int wierd[4]; struct nk_color str = nk_rgba_hex("#deadbeef"); //int wierd[4]; char *s; //int wierd[4]; nk_color_hex_rgb(s, str); //int wierd[4]; printf("(%d,%d,%d)\n",str.r, str.g, str.b); //int wierd[4]; printf("%s\n", s); //int wierd[4]; return 0; } The above produces as its output: (222,173,190) DEADBE but if I introduce an int array on any of the commented lines, it results in a runtime Segmentation fault: 11. Basically I'm just trying to port Nuklear[1] to D as a first project after reading Ali and Mike's awesome books. Moving one function at a time to an independent C file, compiling it to observe the result and then from the understanding gained, re-implementing it in D. The int array here is introduced to prepare for port of the next function and has nothing to do with the current content of main(), but I'm completely confused because I don't see anything wrong with the code that is causing the error. By the way, the program responds differently based on the type of the array: double => Bus error: 10 char => no error short => Segmentation fault: 11 long => Bus error: 10 Obviously I'm missing something... please enlighten me. Thanks, Andrew [1] Yes, I know there is already a port and bindings available... this is purely for learning. My goal is actually to port imgui for a project I committed myself to at DConf2017 but in the process of doing so, I realized how woefully inadequate my knowledge of programming is. This is my attempt at rectifying the situation. Just in case... here are the two functions being called in main(): https://github.com/vurtun/nuklear/blob/master/nuklear.h#L5695-L5722
OT: What causes the Segfault in the following?
int main() { //int wierd[4]; struct nk_color str = nk_rgba_hex("#deadbeef"); //int wierd[4]; char *s; //int wierd[4]; nk_color_hex_rgb(s, str); //int wierd[4]; printf("(%d,%d,%d)\n",str.r, str.g, str.b); //int wierd[4]; printf("%s\n", s); //int wierd[4]; return 0; } The above produces as its output: (222,173,190) DEADBE but if I introduce an int array on any of the commented lines, it results in a runtime Segmentation fault: 11. Basically I'm just trying to port Nuklear[1] to D as a first project after reading Ali and Mike's awesome books. Moving one function at a time to an independent C file, compiling it to observe the result and then from the understanding gained, re-implementing it in D. The int array here is introduced to prepare for port of the next function and has nothing to do with the current content of main(), but I'm completely confused because I don't see anything wrong with the code that is causing the error. By the way, the program responds differently based on the type of the array: double => Bus error: 10 char => no error short => Segmentation fault: 11 long => Bus error: 10 Obviously I'm missing something... please enlighten me. Thanks, Andrew [1] Yes, I know there is already a port and bindings available... this is purely for learning. My goal is actually to port imgui for a project I committed myself to at DConf2017 but in the process of doing so, I realized how woefully inadequate my knowledge of programming is. This is my attempt at rectifying the situation.
Re: How does one determine the UDAs of all symbols contained in a given module?
On Wednesday, 19 July 2017 at 14:23:25 UTC, Jacob Carlborg wrote: Here's an example: Thanks... Minus the AliasSeq bit, this is pretty much what I've been working with since talking to Brain. The main problem I'm facing is that it fails to compileif any of the symbols in the imported module is marked private. findudas.d-mixin-17(17): Error: ScopeDsymbol findudas.getModuleSymbols!"somepackage.mod1".__anonymous.__anonymous variable somepackage.mod1.workhorse is private findudas.d-mixin-17(17): Deprecation: somepackage.mod1.workhorse is not visible from module findudas findudas.d-mixin-21(21): Error: ScopeDsymbol findudas.getModuleSymbols!"somepackage.mod1".__anonymous.__anonymous variable somepackage.mod1.workhorse is private findudas.d-mixin-21(21): Deprecation: somepackage.mod1.workhorse is not visible from module findudas findudas.d(34): Error: template instance findudas.getModuleSymbols!"somepackage.mod1".getModuleSymbols.printUDAs!(mod1) error instantiating findudas.d(43):instantiated from here: getModuleSymbols!"somepackage.mod1"
Re: How does one determine the UDAs of all symbols contained in a given module?
On Wednesday, 19 July 2017 at 11:28:30 UTC, Jacob Carlborg wrote: On 2017-07-19 11:25, Nicholas Wilson wrote: You'll want to use https://dlang.org/spec/traits.html#getMember in conjunction with https://dlang.org/spec/traits.html#getAttributes. Have a look some of the projects on github e.g. https://github.com/kaleidicassociates/excel-d/blob/master/source/xlld/wrap.d#L686 And https://dlang.org/spec/traits.html#allMembers to iterate all members in a module. Thanks Jacob and Nicholas... Brian Schott helped me out a bit on IRC earlier. I'm still not getting exactly what I'm looking for though so wanted to experiment a bit more before posting an update here. I'll check out the warp.d examples Nicholas linked to above. Andrew
How does one determine the UDAs of all symbols contained in a given module?
Given a module (somepackage.somemodule) how does one programmatically determine the symbols contained therein and associated UDAs? Where symbol is a variable, function, UDT, etc... is this possible? foreach (symbol; somepackage.somemodule) { writeln(symbol.name, " attributes :") foreach(attribute; symbol) { writeln("\t", attribute); } } I've looked at std.traits but for the most part the functionality I saw there only allowed me to grab attributes I already know of from symbols I already know... for instance: @("bold") string boldText; getUDAs!(boldText, "bold"); This also does not allow retrieving attributes from functions with void return-type. So this wouldn't work: @("bold") void decorateText(ref string data); getUDAs!(decorateText, "bold"); // Error: cannot deduce function from arguments types !()(void, string); What I'd like to do is open a module and evaluate each variable, instance variable, member variable, function, member function, etc... to see what UDAs they carry. Please provide code sample or point me toward the appropriate documentation. Again, I've looked at std.traits (https://dlang.org/phobos/std_traits.html) and the related implementation (https://github.com/dlang/phobos/blob/master/std/traits.d#L7378-L7760) but found nothing that would help me toward this end... or maybe I've missed something? Thanks, Andrew
Re: Help me fix my compiler
On Wednesday, 12 July 2017 at 12:05:17 UTC, Namal wrote: Hello, I used the Install Script command line to install the newest dmd compiler (Ubuntu 16.04.2 LTS). Now I have to type 'source ~/dlang/dmd-2.074.1/activate' before I can use it and it is also not show in the software center like it used to be. How can I fix it or how can I remove it? Thx You are using the script directly from dlang.org, as such you can manipulate (manage) your installed compilers directly from the shell. And not just DMD, it also manages LDC and GDC. dmd|gdc|ldc latest version of a compiler dmd|gdc|ldc- specific version of a compiler (e.g. dmd-2.071.1, ldc-1.1.0-beta2) dmd|ldc-beta latest beta version of a compiler dmd-nightly latest dmd nightly dmd-2016-08-08specific dmd nightly To uninstall any compiler previously installed via this script simply type ~/dlang/install.sh uninstall install.sh uninstall dmd install.sh uninstall dmd-2.071.1 install.sh uninstall ldc-1.1.0-beta2 To install a different version of the compiler type ~/dlang/install.sh uninstall install.sh install dmd install.sh install dmd-2.071.1 install.sh install ldc-1.1.0-beta2 To make the 'source ~/dlang/dmd-2.074.1/activate' persistent, simply store it in ~/.bash_profile. If this file does not already exist, simply create it. Best of luck. Andrew
Re: rdmd vs dmd WRT static constructors
On Sunday, 9 July 2017 at 03:11:17 UTC, Mike Parker wrote: On Sunday, 9 July 2017 at 02:57:54 UTC, Andrew Edwards wrote: To include stat1.d and stat2.d in the compilation, you'll either have to import them in statmain.d or use the --extra-file command line switch: rdmd --extra-file=stat1.d --extra-file=stat2.d statmain.d Okay, got it... thanks Mike.
rdmd vs dmd WRT static constructors
RDMD does not behave the same as DMD WRT static constructors. The following example, extracted form Mike Parker's "Learning D", does not produce the same result: // stat1.d module stat1; import std.stdio; static this() { writeln("stat1 constructor"); } // stat2.d module stat2; import std.stdio; static this() { writeln("stat2 constructor"); } // statmain.d void main() { } $ rdmd statmain.d stat1.d stat2.d // outputs nothing... $ dmd statmain.d stat1 stat2 $ ./statmain // outputs... stat1 constructor stat2 constructor Bug or intended behaviour? Thanks, Andrew
Re: Is it possible to call a delegate at compile time?
On Friday, 23 June 2017 at 04:58:07 UTC, ketmar wrote: Andrew Edwards wrote: so no, even if you'll remove `ref`, it will not work. sorry. Okay, got it. Much appreciated.
Is it possible to call a delegate at compile time?
auto foo(Args...)(ref Args args) { with (Module!"std.conv") with (Module!"std.stdio") { return () => { string[] s; foreach (i, arg; args) { static if (is(Args[i] == string)) { s ~= arg; } else { s ~= to!string(arg); } } debug writeln(fmt()); return cast(immutable)s; }(); } } template Module(string name) { mixin("import Module = " ~ name ~ ";"); } void main() { static immutable i = 7; static immutable s = "teen"; static immutable res = foo(i, s)(); writeln(res); } I desire to call foo() at compile... As implemented it does not happen, but it's not immediately clear what I am missing. Or is this simply not possible as yet? What is the proper way to redesign this template so that it will execute at compile time? Thanks, Andrew
Re: .sort vs sort(): std.algorithm not up to the task?
On Thursday, 8 June 2017 at 07:23:27 UTC, Jonathan M Davis wrote: release is a member of SortedRange. You don't have to import it separately. You have it automatically by virtue of the fact that sort returns a SortedRange. And unlike calling array, it doesn't copy the entire range or allocate. sorry, I missed that after accidentally making the change in on file and compiled another. having it return SortedRange is beneficial overall, and calling release to get the original out is as short as passing a template argument like you're suggesting. a point I missed do to the aforementioned mistake. Thanks for the assist, Andrew
Re: .sort vs sort(): std.algorithm not up to the task?
On Thursday, 8 June 2017 at 04:15:12 UTC, Stanislav Blinov wrote: Earns you nothing? How about not performing an allocation and copy? Seen through the eyes of a complete beginner, this means absolutely nothing. Those are the eyes I am using as I'm reading a book and simply following the instructions provided. I took care of the problem with the first thing that came to mind, because that all that's required. aa.keys.sort().release; somehow, I missed the point that actually came as a byproduct of importing sort. When I tried it in the original code it "ostensibly" did not work because, i recompiled the edited version posed here. No need to import anything but std.algorithm : sort. But it doesn't, it decides what i'm gonna get like it or not. But the fact, a lot of times I just want to work with the underlying data after the operation is performed. And it should be noted that this applies to Ranges in general not just sort. A crucial point of any good design is to *not rob the caller of useful information*. sort() follows that philosophy. If you don't need the extra information, you're free to get rid of it. The other way around that you seem to be proposing would require having a ton of overloads for sort() for any imaginable use case. No I'm not proposing that at all, if the predicate is initialized such that it functions the exact same way it does now, then only in instances where necessary would the user need to specify anything. Anyway, the functionality I'm asking for is the one forded by release so i'm satisfied. Thank you.
Re: .sort vs sort(): std.algorithm not up to the task?
On Thursday, 8 June 2017 at 03:40:08 UTC, Jonathan M Davis wrote: On Thursday, June 08, 2017 03:15:11 Andrew Edwards via Digitalmars-d-learn wrote: I completely understand the differences between ranges and arrays... the thing is, I wasn't working with ranges but arrays instead. If sort understands a string or array as a sort of range, then given one of those entities, it should manipulate it internally and return it in it's original flavor. Given an array, return an array unless specifically told to do otherwise. sort() returns a SortedRange so that other algorithms can know that the range is sorted and take advantage of that. If sort() returned the original range type, it would be detrimental for other algorithms. But you can just use the array directly again after calling sort or call release() on the SortedRange to get the array out of it. - Jonathan M Davis Yes, I understand that. Again, using "std.range: release" earns me nothing more than I already get from "std.array: array" or if you prefer "std.range: array". I can understand if sort returns Range by default but can be instructed to return the original representation. aa.keys.sort!returnOriginalRepresentation; // or something to that effect But it doesn't, it decides what i'm gonna get like it or not. But the fact, a lot of times I just want to work with the underlying data after the operation is performed. And it should be noted that this applies to Ranges in general not just sort.
Re: .sort vs sort(): std.algorithm not up to the task?
On Thursday, 8 June 2017 at 02:31:43 UTC, Stanislav Blinov wrote: On Thursday, 8 June 2017 at 02:25:17 UTC, Jonathan M Davis wrote: Oh I see, the was error related to iteration, not sorting. Ranges do not support iterating with an index. The workaround if you want to have an index with ranges and foreach, then you should use lockstep: http://dlang.org/phobos/std_range.html#lockstep e.g. foreach(i, v; lockstep(iota!size_t(0), s)) {} or foreach(i, v; lockstep(iota(0), s)) {} There's an enumerate(): https://dlang.org/phobos/std_range.html#enumerate import std.algorithm : sort; import std.range : enumerate; foreach(i, k; aa.keys.sort().enumerate) { /* ... */ } Note that I already demonstrated the same functionality by importing "std.array: array" to get the job done. Neither lockstep nor enumerate gets me more benefit in this particular situation that array doesn't already get me. My question here is not whether the job can get done or not, it's simply why the extra work? I still have to import two modules, when before I didn't have to import any. I completely understand the differences between ranges and arrays... the thing is, I wasn't working with ranges but arrays instead. If sort understands a string or array as a sort of range, then given one of those entities, it should manipulate it internally and return it in it's original flavor. Given an array, return an array unless specifically told to do otherwise.
Re: .sort vs sort(): std.algorithm not up to the task?
On Thursday, 8 June 2017 at 02:21:03 UTC, Stanislav Blinov wrote: aa.keys.sort() should just work as is: aa.keys returns a string[], and that's a random access range that can be sorted. What exactly is the error? It does not ... I provided the code and related error message. See the line right above "import std.algorith: sort;".
Re: .sort vs sort(): std.algorithm not up to the task?
On Thursday, 8 June 2017 at 02:19:15 UTC, Andrew Edwards wrote: Pretty funny. But seriously, this is something that just work. There is now to layers of indirection to achieve what I used to do quite naturally in the language. *should just work
Re: .sort vs sort(): std.algorithm not up to the task?
On Thursday, 8 June 2017 at 02:07:07 UTC, Mike B Johnson wrote: On Thursday, 8 June 2017 at 01:57:47 UTC, Andrew Edwards wrote: If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua? Because is like a poodle and unless you get your hair cut in a special way you won't be considered for the job! The wizard only exists to balance the symmetric arrangement of the interplanetary forces, don't fear him, he does his job in a very predictable way. Pretty funny. But seriously, this is something that just work. There is now to layers of indirection to achieve what I used to do quite naturally in the language.
.sort vs sort(): std.algorithm not up to the task?
Ranges may be finite or infinite but, while the destination may be unreachable, we can definitely tell how far we've traveled. So why doesn't this work? import std.traits; import std.range; void main() { string[string] aa; // what others have referred to as // standard sort works but is deprecated //auto keys = aa.keys.sort; // Error: cannot infer argument types, expected 1 argument, not 2 import std.algorithm: sort; auto keys = aa.keys.sort(); // this works but why should I have to? //import std.array: array; //auto keys = aa.keys.sort().array; foreach (i, v; keys){} } If I hand you a chihuahua for grooming, why am I getting back a pit bull? I simply want a groomed chihuahua. Why do I need to consult a wizard to get back a groomed chihuahua?
Re: Error: func(const(A) a) is not callable using argument types (const(A)
On Tuesday, 30 May 2017 at 10:37:58 UTC, Biotronic wrote: On Tuesday, 30 May 2017 at 10:31:24 UTC, Daniel Kozak wrote: import std.traits : fqn = fullyQualifiedName; Darnit. I just googled the template and got a result talking about fqn!T. So yeah - this code: import std.traits; pragma(msg, fullyQualifiedName!ImVec2); pragma(msg, fullyQualifiedName!(typeof(CalcTextSize(label.ptr, null, true; -- Biotronic This is exactly the cause. Output is follows: internal.ImVec2 types.ImVec2 I'm leveraging types as I try to do my own port of the lib so CalcTextSize is returning an instance of ImVec2 as defined types and I'm trying to assign to one I have declared in internal. Thanks.
Re: Error: func(const(A) a) is not callable using argument types (const(A)
Sorry, rough day. Could someone please explain what this means and how do go about resolving it? Thanks, Andrew
Error: func(const(A) a) is not callable using argument types (const(A)
What does that even mean? Scenario: bool func(const ImVec2 label_size) { return true; } void main() { //first attempt: const ImVec2 label_size = CalcTextSize(label.ptr, null, true); //Error: cannot implicitly convert expression (CalcTextSize(cast(immutable(char)*)label, null, true, -1F)) of type ImVec2 to const(ImVec2) //second attempt const ImVec2 label_size = cast(const)CalcTextSize(label.ptr, null, true); // Error: cannot implicitly convert expression (CalcTextSize(cast(immutable(char)*)label, null, true, -1F)) of type const(ImVec2) to const(ImVec2) //third attempt const auto label_size = CalcTextSize(label.ptr, null, true); //Okay: don't know why the other two didn't work but I can keep going for now func(label_size); //Error: function imgui_d.func (const(ImVec2) label_size) is not callable using argument types (const(ImVec2)) }
Re: [OT] #define
On Tuesday, 23 May 2017 at 00:14:43 UTC, Mike Parker wrote: On Monday, 22 May 2017 at 18:44:10 UTC, Andrew Edwards wrote: There isn't any Windows specific section. Every function pointer in the library is decorated in one of the following two forms void (APIENTRY *NAME)(PARAMS) or void (APIENTRYP NAME)(PARAMS) Sorry, I worded that poorly. APIENTRY is defined somewhere in the Win32 headers. IIRC, it's an alias for WINAPI, which is also defined in the Win32 headers to declare the standard call calling convention (which is __stdcall on the MS compiler and something else, I think, on GCC). OpenGL includes windows.h on Windows, so the Win32-specific stuff is there. The functions aren't in any Win32-specific sections. [] Much appreciated Mike and everyone else. I was able to make a good deal of progress today because of your input. Andrew
Re: [OT] #define
On Monday, 22 May 2017 at 18:48:44 UTC, Adam D. Ruppe wrote: On Monday, 22 May 2017 at 18:44:10 UTC, Andrew Edwards wrote: Both happen to be the exact same. So does mean that for every function pointer in the file, I need to duplicate as such? You can use `extern(System)` or that case in D. It will be extern(Windows) on win an extern(C) elsewhere - just like what the C is doing. Okay... got it. Thanks.
Re: [OT] #define
On Monday, 22 May 2017 at 16:56:10 UTC, Mike Parker wrote: On Monday, 22 May 2017 at 16:37:51 UTC, Andrew Edwards wrote: Specific context at the following links: https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L24-L48 Generally, any functions in the Windows-specific sections with APIENTRY in their declarations need to be declared in D as extern(Windows). APIENTRY itself can be left out of the D binding. There isn't any Windows specific section. Every function pointer in the library is decorated in one of the following two forms void (APIENTRY *NAME)(PARAMS) or void (APIENTRYP NAME)(PARAMS) Both happen to be the exact same. So does mean that for every function pointer in the file, I need to duplicate as such? version (Windows) { extern(Windows) { alias NAME = void function(PARAMS); } } else { extern(C) { alias NAME = void function(PARAMS); } } https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L57-L81 Again, GLAPI is a Windows-specific thing. [...] You can safely ignore this one, unless you're planning to do a pure D port (not binding) of the library and intend to compile as a shared lib. It tells you which functions need to be exported from the shared lib to match the C API. So if I'm understanding correctly, on Windows platforms this: typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap); GLAPI PFNGLDISABLEPROC glad_glDisable; #define glDisable glad_glDisable is technically: typedef void (__syscall* PFNGLDISABLEPROC)(GLenum cap); extern "C" PFNGLDISABLEPROC glad_glDisable; #define glDisable glad_glDisable which in D is: // extern (Windows) obviated by the fact that the following line exports to the C API? extern (C) alias glad_glDisable = void function(GLenum cap); glad_glDisable glDisable; https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L88-L124 [...] This one can also be ignored on the D side. Got it.
Re: [OT] #define
On Monday, 22 May 2017 at 13:52:35 UTC, Dukc wrote: On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote: Sorry if this is a stupid question but it eludes me. In the following, what is THING? What is SOME_THING? [...] I assume you know that the above part is c/c++ preprocessor, which is not normally used at d? Yes, I am aware. THING is nothing there. If you use it at code, I'm not sure how it behaves. Either it does not compile at all, or it behaves as nothing (think whitespace). If it's the latter, SOME_THING would be a lone asterix. Can be used as operator both unarily and binarily. #IFNDEF regonizes all preprocessor declarations, empty or not. The closest D equivalent to #DEFINE is a string mixin. The equivalent to above is: static if (!is(typeof(thing))) enum thing = ""; static if (!is(typeof(someThing))) enum someThing = thing ~ " *"; [...] ...you have to explicitly mix the text in: @safe void main() { import std.stdio; mixin("writeln(5 " ~ someThing ~ " 6);"); //30 } That's really ugly... Hope I'll never have to resort to that. The specific idiom does have it's uses though, as in the case of self-important lookups. [...] -If the symbol is an empty declaration used only for #IFNDEFS, version statements are a cood canditate for replacing it. Perhaps that's what you're looking for? Not exactly but I get the point. This list is golden, thanks for the assist. Andrew
Re: [OT] #define
On Monday, 22 May 2017 at 13:15:31 UTC, Adam D. Ruppe wrote: On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote: #ifndef THING #define THING #endif This kind of thing is most commonly used in include guards https://en.wikipedia.org/wiki/Include_guard#Use_of_.23include_guards Have a basic understanding. In the specific case i'm looking at, they are not used as include guards though. You can usually just strip that out in D, since the module system already just works if imported twice. Makes sense. #ifndef SOME_THING #define SOME_THING THING * #endif Is this equivalent to: alias thing = void; alias someThing = thing*; I'd have to see that in context though to see why they are doing it... it is probably some kind of platform specific type definitions. Specific context at the following links: https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L24-L48 https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L57-L81 https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L88-L124 Thanks, Andrew
Re: [OT] #define
On Monday, 22 May 2017 at 13:18:51 UTC, Eugene Wissner wrote: On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote: Sorry if this is a stupid question but it eludes me. In the following, what is THING? What is SOME_THING? #ifndef THING #define THING #endif #ifndef SOME_THING #define SOME_THING THING * #endif Is this equivalent to: alias thing = void; alias someThing = thing*; Thanks, Andrew No, it isn't. THING is empty. Some SOME_THING is "*". Emtpy macros are used for example to inline the functions: #ifndef MY_INLINE #define MY_INLINE #endif MY_INLINE void function() { } So you can choose at compile time if you want inline the function or not. D is here more restrictive than C, I don't know a way to port to D. Thanks Eugene, got it. For context, see response to Adam.
[OT] #define
Sorry if this is a stupid question but it eludes me. In the following, what is THING? What is SOME_THING? #ifndef THING #define THING #endif #ifndef SOME_THING #define SOME_THING THING * #endif Is this equivalent to: alias thing = void; alias someThing = thing*; Thanks, Andrew
Re: Access specifiers and visibility
On Thursday, 11 May 2017 at 04:35:22 UTC, Jesse Phillips wrote: On Wednesday, 10 May 2017 at 13:29:40 UTC, Andrew Edwards wrote: On Wednesday, 10 May 2017 at 13:13:46 UTC, Jesse Phillips wrote: On Wednesday, 10 May 2017 at 01:42:47 UTC, Andrew Edwards wrote: Attempting to update a git repo to current D, I encounter the following deprecation messages: src/glwtf/signals.d-mixin-256(256,2): Deprecation: glwtf.input.BaseGLFWEventHandler._on_key_down is not visible from module glwtf.signals Thanks, Andrew This comes from: http://dlang.org/changelog/2.071.0.html#dip22 The module glwtf.signals needs to import glwtf.input. One of the other imports was contaminating the namespace. I actually attempted solve the issue with selective import as such:: import glwtf.input : BaseGLFWEventHandler; but it did not work. Importing the entire module does not work either. I'm not sure the library you're using but this like the one: https://github.com/Dav1dde/glwtf/blob/master/glwtf/input.d#L163 This code says that the function is protected. https://github.com/Dav1dde/glwtf/blob/master/glwtf/signals.d#L254 This line is probably mixing in a call to that function into a struct https://github.com/Dav1dde/glwtf/blob/master/glwtf/signals.d#L229 But that struct doesn't inherit from the class so it can't access protected fields. That's not the same library but the exact same implementation. The one I'm using (https://github.com/d-gamedev-team/dimgui) borrows its from the deimos bindings. So since the a struct cannot inherit from a class and vice versa, then the entire approach taken by the library must be reconsidered going forward. A little over my head at this point. Thanks for the assist.
Re: Access specifiers and visibility
On Wednesday, 10 May 2017 at 13:13:46 UTC, Jesse Phillips wrote: On Wednesday, 10 May 2017 at 01:42:47 UTC, Andrew Edwards wrote: Attempting to update a git repo to current D, I encounter the following deprecation messages: src/glwtf/signals.d-mixin-256(256,2): Deprecation: glwtf.input.BaseGLFWEventHandler._on_key_down is not visible from module glwtf.signals Thanks, Andrew This comes from: http://dlang.org/changelog/2.071.0.html#dip22 The module glwtf.signals needs to import glwtf.input. One of the other imports was contaminating the namespace. I actually attempted solve the issue with selective import as such:: import glwtf.input : BaseGLFWEventHandler; but it did not work. Importing the entire module does not work either.
Access specifiers and visibility
Attempting to update a git repo to current D, I encounter the following deprecation messages: src/glwtf/signals.d-mixin-256(256,2): Deprecation: glwtf.input.BaseGLFWEventHandler._on_key_down is not visible from module glwtf.signals src/glwtf/signals.d-mixin-256(256,2): Deprecation: glwtf.input.BaseGLFWEventHandler._on_key_up is not visible from module glwtf.signals src/glwtf/signals.d-mixin-256(256,2): Deprecation: glwtf.input.BaseGLFWEventHandler._on_mouse_button_down is not visible from module glwtf.signals src/glwtf/signals.d-mixin-256(256,2): Deprecation: glwtf.input.BaseGLFWEventHandler._on_mouse_button_up is not visible from module glwtf.signals The offending line of code in signal.d for all four messages is: _impl.addSlot(obj, cast(void delegate())mixin(""~method)); these methods are implemented in the following default constructor: class BaseGLFWEventHandler : AEventHandler { // [...] this() { on_key_down.connect!"_on_key_down"(this); on_key_up.connect!"_on_key_up"(this); on_mouse_button_down.connect!"_on_mouse_button_down"(this); on_mouse_button_up.connect!"_on_mouse_button_up"(this); } // [...] } Which are implemented in the following abstract class: abstract class AEventHandler { // input Signal!(int, int, int) on_key_down; Signal!(int, int, int) on_key_up; Signal!(int, int) on_mouse_button_down; Signal!(int, int) on_mouse_button_up; } I'm not sure how to address this issue so am seeking guidance on how to update this code such that it complies with current D. Thanks, Andrew
Re: Problem with using readln.
On Sunday, 30 April 2017 at 03:20:20 UTC, JV wrote: On Sunday, 30 April 2017 at 03:18:04 UTC, Adam D. Ruppe wrote: On Sunday, 30 April 2017 at 03:10:25 UTC, JV wrote: btw i forgot to add () at readln while editing the post That's not necessary, it doesn't change anything. But readln without arguments returns a string, not an int. okay?? but how do i return an int? tried using what i found in the internet like using stdio.conv; to use toInt() but still shows error Basically the simplest way would be: int val; readf("%d", ); But if you are dead set on using readln, you will need to parse the line to obtain the integer value. The following demonstrates: // Scherkl-Nielsen self-important lookup template Module(string moduleName) { mixin("import Module = " ~ moduleName ~ ";"); } void main() { with(Module!"std.stdio: readln, writeln") with(Module!"std.conv: parse") { string line; parse!int((line = readln)).writeln; } } Your attempt failed because there is a '\n' character sitting at the end of the line read in by readln. It cannot be converted to an integer so any attempt to do so will result in an Exception being thrown. As was the case with toInt. -- Andrew
Re: warning: pointer not aligned at address
On Wednesday, 12 April 2017 at 03:18:32 UTC, Matt Whisenhunt wrote: ld: warning: pointer not aligned at address 0x100050C7D Are you running macOS and recently installed an update to Xcode? I ran into this today as well. Looks like other have too: https://issues.dlang.org/show_bug.cgi?id=17289 Yes, I do indeed use macOS and am on the latest version. I spun up a Ubuntu vm and in works correctly there. Thanks.
Re: warning: pointer not aligned at address
Conveniently the site is down immediately after I posted that so here is the code to which I was referring: import std.stdio, std.algorithm, std.range; enum DoorState : bool { closed, open } alias Doors = DoorState[]; Doors flipUnoptimized(Doors doors) pure nothrow { doors[] = DoorState.closed; foreach (immutable i; 0 .. doors.length) for (ulong j = i; j < doors.length; j += i + 1) if (doors[j] == DoorState.open) doors[j] = DoorState.closed; else doors[j] = DoorState.open; return doors; } Doors flipOptimized(Doors doors) pure nothrow { doors[] = DoorState.closed; for (int i = 1; i ^^ 2 <= doors.length; i++) doors[i ^^ 2 - 1] = DoorState.open; return doors; } void main() { auto doors = new Doors(100); foreach (const open; [doors.dup.flipUnoptimized, doors.dup.flipOptimized]) iota(1, open.length + 1).filter!(i => open[i - 1]).writeln; }
warning: pointer not aligned at address
When compiled with any dmd compiler from 2.069.0 through present (2.074.0), https://rosettacode.org/wiki/100_doors#D produces the following linker warning: ld: warning: pointer not aligned at address 0x10004FCEB (_D51TypeInfo_S3std5range13__T4iotaTiTmZ4iotaFimZ6Result6__initZ + 24 from doors100.o) [65 other lines removed for brevity] ld: warning: pointer not aligned at address 0x100050C7D (_D11TypeInfo_xb6__initZ + 16 from doors100.o) specific compilers checked: dmd-2.068.0 dmd-2.068.1 dmd-2.068.2 dmd-2.069.0 dmd-2.070.0 dmd-2.071.2 dmd-2.073.1 dmd-2.073.2 dmd-2.074.0 What's the proper way to address these warnings? The code is linked and works as expected but, to me, there is just something about those warnings that cries out for attention. Is there something I can do to align this code or is this something that needs to be addressed in the compiler? Thanks, Andrew
Recursive-descent parsing
The authors of "The Art of Java" present, as a first coding example, a recursive-descent parser to demonstrate Java's ability to facilitate low level programming commonly performed in C and C++. I took the opportunity to port the code to D. By doing this, I now have an understanding of how a recursive-descent parser is written and works. What I am now interested in, is learning about what makes this particular implementation a poor or strong one, how to improve upon it and other, possibly superior, implementations made possible by D. Comments are invited and appreciated. Andrew Edwards If at first you don't succeed... = rdp2.d = //module rdp2; class ParserException : Throwable { this(string msg) { super(msg); } } // These are the token types. enum { NONE, DELIMITER, VARIABLE, NUMBER } // These are the types of syntax errors. enum { SYNTAX, UNBALPARENS, NOEXP, DIVBYZERO } // This token indecates end-of-expression. enum EOE = ";"; string exp; // refers to expression string int ndx; // current index into the expression string token; // holds current token int tokType;// holds token's types // Array for variables. double[] vars = new double[26]; // Parser entry poing. double evaluate(string expstr) { double result; exp = expstr; ndx = 0; getToken(); if (token == EOE) handleErr(NOEXP); // no expression present // Parse and evaluate the expression. result = evalExp1(); if (token != EOE) handleErr(SYNTAX); // last token must be EOE return result; } // Process an assignment. double evalExp1() { double result; int varNdx; int ttokType; string tmpToken; if (tokType == VARIABLE) { // save old token tmpToken = token; ttokType = tokType; // Compute the index of the variable. import std.ascii: toUpper; varNdx = token[0].toUpper - 'A'; getToken(); if (token != "=") { putBack(); // return current token // restore old token -- not an assignment token = tmpToken; tokType = ttokType; } else { getToken(); // get next part of exp result = evalExp2(); vars[varNdx] = result; return result; } } return evalExp2(); } // Add or subtract two terms double evalExp2() { char op; double result; double partialResult; result = evalExp3(); while ((op = token[0]) == '+' || op == '-') { getToken(); partialResult = evalExp3(); final switch (op) { case '-': { result -= partialResult; break; } case '+': { result += partialResult; break; } } } return result; } // Multiply or divide two factors double evalExp3() { char op; double result; double partialResult; result = evalExp4(); while ((op = token[0]) == '*' || op == '/' || op == '%') { getToken(); partialResult = evalExp4(); final switch (op) { case '*': { result *= partialResult; break; } case '/': { if (partialResult == 0.0) handleErr(DIVBYZERO); result /= partialResult; break; } case '%': { if (partialResult == 0.0) handleErr(DIVBYZERO); result %= partialResult; break; } } } return result; } // Process an exponent. double evalExp4() { double result; double partialResult; double ex; result = evalExp5(); if (token == "^") { getToken(); partialResult = evalExp4(); ex = result; if (partialResult == 0.0) { result = 1.0; } else { for (int t = cast(int)partialResult-1; t > 0; t--) result *= ex; } } return result; } // Evaluate a unary + or - double evalExp5() { double result; string op; op = null; if ((tokType == DELIMITER) && token == "+" || token == "-") { op = token; getToken(); } result = evalExp6(); //if (op == "-") result = -result; return (op == "-") ? -result : result; } // Process a parenthesized expression. double evalExp6() { double result; if (token == "(") { getToken(); result = evalExp2(); if (token != ")") handleErr(UNBALPARENS); getToken(); } else result = atom(); return result; } // Get the value of a number. double atom() {
Re: webfreak001: Request assist installing workspace-d on Windows
On Tuesday, 5 July 2016 at 19:43:02 UTC, WebFreak001 wrote: On Tuesday, 5 July 2016 at 19:34:48 UTC, Andrew Edwards wrote: It's more than that. Now, it fails because it can't find DMD. As you can see in the build.bat from DCD it is hardcoded to DMD: https://github.com/Hackerpilot/DCD/blob/master/build.bat Maybe I should have been a little clearer. Following your instructions from earlier (skip DCD by selecting 2,3) the process failed again: 'dmd' is not recognized as an internal or external command, operable program or batch file. Error while compiling Dscanner. Program exited with code 1 But if DCD doesn't compile with LDC, I don't think there is a way other than getting both DMD and LDC right now except if you are on linux. It's not that LDC cannot compile DCD in this case, it's that your build script is searching for DMD when it cannot use DMD.
Re: webfreak001: Request assist installing workspace-d on Windows
On Tuesday, 5 July 2016 at 19:25:50 UTC, WebFreak001 wrote: On Tuesday, 5 July 2016 at 19:14:32 UTC, Andrew Edwards wrote: There is on --config=client for the current version of dub so I went to the location of the source for experimental_allocator and ran dub build --build=release --config=library instead, which generated the missing file. Problem is I don't know how to fix this in your build instructions so that the compellation will resume or continue to completion. Please assist. It fails on installing DCD. On the installation.bat just select 2,3 and get prebuilt DCD binaries from the project page or build them yourself. It's more than that. Now, it fails because it can't find DMD. Now, I see no reason to use both DMD and LDC. Ultimately I'd like to use DMD because it is the simplest to install for a newcomer but your workspace-d/code-d requires LDC on windows platforms. If that's the case why would it now be failing because it cannot find DMD?
webfreak001: Request assist installing workspace-d on Windows
I cloned the package and ran install.bat. The result is $ dub build --build=release --config=client Performing "release" build using ldc2 for x86. experimental_allocator 2.70.0-b1: building configuration "library"... Using Visual Studio: C:\Program Files (x86)\Microsoft Visual Studio 14.0\ LINK : fatal error LNK1104: cannot open file '..\..\..\..\Roaming\dub\packages\experimental_allocator-2.70.0-b1\experimental_allocator\.dub\build\library-release-windows-x86-ldc_0-341F845AB271E17D9C62794DCB77B6FB\experimental_allocator.lib' Error: `C:\WINDOWS\system32\cmd.exe /s /c "C:\D\ldc2\bin\amd64.bat lib.exe"` failed with status: 1104 ldc2 failed with exit code 1104. Error while compiling DCD. Program exited with code 1 There is on --config=client for the current version of dub so I went to the location of the source for experimental_allocator and ran dub build --build=release --config=library instead, which generated the missing file. Problem is I don't know how to fix this in your build instructions so that the compellation will resume or continue to completion. Please assist. Thanks, Andrew
Re: Fibers under the hood
On 6/9/16 2:15 PM, Jonathan Marler wrote: On Thursday, 9 June 2016 at 05:07:33 UTC, Nikolay wrote: On Thursday, 9 June 2016 at 04:57:30 UTC, Jonathan Marler wrote: I've googled and searched through the forums but haven't found too much on how fibers are implemented. How does yield return execution to the caller but then resume execution in the same place on the next call? Also some information on how the fiber call stack works would be nice. I'm assuming it allocates the stack on the GC heap. If so, what is the default size and is that configurable? Any information or pointers to resources that provide this information would be helpful. Thanks. See "Documentation of Fiber internals" inside https://github.com/dlang/druntime/blob/master/src/core/thread.d Exactly what I was looking for, thanks. Would be nice if this documentation was published on the website somewhere (probably in the Fiber library documentation). Might be wrong but did you mean this? https://dlang.org/phobos/core_thread.html#.Fiber
Re: Request assistance binding to Windows dsound.{lib, dll}
On Friday, 27 May 2016 at 20:59:56 UTC, John wrote: Additionally, remove QueryInterface, AddRef and Release from the definition of IDirectSound. Also, interfaces are already references, so the definition of LPDIRECTSOUND should be: alias LPDIRECTSOUND = IDirectSound; Note there should be no *. Awesome... that's the missing link. Thank you very. I really appreciate the assistance of everyone who helped to clarify this matter. Regarding any linking errors, it's easier to either grab the .lib files from the Windows SDK and convert them with coffimplib, or use the m32mscoff switch so you can link with the SDK .lib files directly. Was already doing that (both approaches). As Adam pointed out, last bit of errors were occurring because it was a class vice an interface. Again, thank you all. Andrew
Re: Request assistance binding to Windows dsound.{lib, dll}
On Friday, 27 May 2016 at 17:49:56 UTC, Adam D. Ruppe wrote: On Friday, 27 May 2016 at 17:37:38 UTC, Andrew Edwards wrote: extern (C) class IDirectSound : IUnknown That should just be `interface IDirectSound : IUnknown` Thanks for the clarification. That actually compiles but results in access violation at the call site which takes place after verifying that the call to DirectSoundCreate() succeeded: if (SUCCEEDED(sound.SetCooperativeLevel(window, DSSCL_PRIORITY))) { MessageBoxA(null, "Hott Damn!!", null, MB_ICONINFORMATION); } else { MessageBoxA(null, "Naaah Man! Dat cyaan wuk!", null, MB_ICONINFORMATION); } Output: object.Error@(0): Access Violation -- 0x00402700 in void sound.initSound(void*) at C:\Users\edwarac\work\sound\code\sound.d(555) 0x004021A2 in int sound.myWinMain(void*, void*, char*, int) at C:\Users\edwasac\work\sound\code\sound.d(210) 0x00402050 in WinMain at C:\Users\edwasac\work\sound\code\sound.d(154) 0x00422B4A in WinMainCRTStartup 0x76DF3744 in BaseThreadInitTrunk 0x7721A064 in RtlSetCurrentTransaction 0x7721A02F in RtlSetCurrentTransaction
Re: Request assistance binding to Windows dsound.{lib, dll}
On Friday, 27 May 2016 at 16:08:27 UTC, Kagamin wrote: On Friday, 27 May 2016 at 15:28:42 UTC, Andrew Edwards wrote: Have you tried with extern(C) yet? extern(C) is for undecorated symbold extern(Windows) adds the _ and @12 decorations (would be __stdcall on C/C++ side) The thought never crossed my mind. Tried it and it works like a charm. Thanks to everyone who responded. If you declare extern function with wrong calling convention, calling it can result in stack corruption. Okay, that makes sense. Will remain mindful of that. Once DirectSoundCreate() returns successfully, I need to call one of the function pointers in the struct but am at a loss of how to define it based on the interface presented. This struct is called COM interface, D has built-in support for them: https://dlang.org/spec/interface.html#com-interfaces So if I'm understanding correctly, I should be able to take this: DECLARE_INTERFACE_(IDirectSound, IUnknown) { // IUnknown methods STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release) (THIS) PURE; // IDirectSound methods STDMETHOD(CreateSoundBuffer)(THIS_ LPCDSBUFFERDESC, LPDIRECTSOUNDBUFFER *, LPUNKNOWN) PURE; STDMETHOD(GetCaps) (THIS_ LPDSCAPS) PURE; STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER, LPDIRECTSOUNDBUFFER *) PURE; STDMETHOD(SetCooperativeLevel) (THIS_ HWND, DWORD) PURE; STDMETHOD(Compact) (THIS) PURE; STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD) PURE; STDMETHOD(SetSpeakerConfig) (THIS_ DWORD) PURE; STDMETHOD(Initialize) (THIS_ LPGUID) PURE; }; Convert it into this: extern (C) class IDirectSound : IUnknown { // IUnknown methods HRESULT QueryInterface(const(IID)*, void**); uint AddRef(); uint Release(); // IDirectSound methods HRESULT CreateSoundBuffer(LPCDSBUFFERDESC, LPDIRECTSOUNDBUFFER*, LPUNKNOWN); HRESULT GetCaps(LPDSCAPS); HRESULT DuplicateSoundBuffer(LPDIRECTSOUNDBUFFER, LPDIRECTSOUNDBUFFER*); HRESULT SetCooperativeLevel(HWND, DWORD); HRESULT Compact(); HRESULT GetSpeakerConfig(LPDWORD); HRESULT SetSpeakerConfig(DWORD); HRESULT Initialize(LPGUID); } Import the correct libraries: import core.sys.windows.windows; import core.sys.windows.com; And finally link to the lib file and I should be golden!!! Except I'm not :( C:\Users\edwarac\work\sound\code>build A subdirectory or file ..\..\build already exists. OPTLINK (R) for Win32 Release 8.00.17 Copyright (C) Digital Mars 1989-2013 All rights reserved. http://www.digitalmars.com/ctg/optlink.html sound.obj(sound) Error 42: Symbol Undefined __D8sound12IDirectSound17CreateÇàìBufferMWxPSÇï»DSBUFFERDESCPPCÇèÜ8Çî╔Çå╝C4core3sys7windows6unknwn8IU·ownZi@12 sound.obj(sound) Error 42: Symbol Undefined __D8sound12IDirectSound16SetSpeakerConfigMWkZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound12IDirectSound16GetSpeakerConfigMWPkZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound12IDirectSound7CompactMWZi@0 sound.obj(sound) Error 42: Symbol Undefined __D8sound12IDirectSound20DuplicateSoundBufferMWPC8sound18IDirectSoundBufferPPC8sound18IDirectSoundBufferZi@8 sound.obj(sound) Error 42: Symbol Undefined __D8sound12IDirectSound19SetCooperativeLevelMWPvkZi@8 sound.obj(sound) Error 42: Symbol Undefined __D8sound12IDirectSound10InitializeMWPS4core3sys7windows8basetyps4GUIDZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound12IDirectSound7GetCapsMWPS8sound6DSCAPSZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer12GetFrequencyMWPkZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer6SetPanMWiZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer9GetFormatMWPS4core3sys7windows8mmsystem12WAVEFORMATEXkPkZi@12 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer7RestoreMWZi@0 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer6GetPanMWPiZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer4StopMWZi@0 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer9GetStatusMWPkZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer4LockMWkkPPvPkPPvPkkZi@28 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer7GetCapsMWPS8sound7DSBCAPSZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer12SetFrequencyMWkZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer9SetFormatMWPxS4core3sys7windows8mmsystem12WAVEFORMATEXZi@4 sound.obj(sound) Error 42: Symbol Undefined __D8sound18IDirectSoundBuffer9SetVolumeMWiZi@4
Re: Request assistance binding to Windows dsound.{lib, dll}
On Friday, 27 May 2016 at 12:30:50 UTC, Guillaume Piolat wrote: On Friday, 27 May 2016 at 12:26:19 UTC, Andrew Edwards wrote: OPTLINK (R) for Win32 Release 8.00.17 Copyright (C) Digital Mars 1989-2013 All rights reserved. http://www.digitalmars.com/ctg/optlink.html sound.obj(sound) Error 42: Symbol Undefined _DirectSoundCreate@12 --- errorlevel 1 Have you tried with extern(C) yet? extern(C) is for undecorated symbold extern(Windows) adds the _ and @12 decorations (would be __stdcall on C/C++ side) The thought never crossed my mind. Tried it and it works like a charm. Thanks to everyone who responded. notna: It is not really necessary to put the lib in the libs folder since it's being passed on the command line and available in the build directory. I will place it there eventually though. On other issue remains that I could not sort out: Once DirectSoundCreate() returns successfully, I need to call one of the function pointers in the struct but am at a loss of how to define it based on the interface presented. According the code, SetCooperativeLevel() can be called one of two ways, either via a template[1] or directly through the second parameter provided to and modified by SetCooperativeLevel(). I tried the two approaches below both inside and outside the struct but neither worked. // first approach struct IDirectSound { extern(C) HRESULT SetCooperativeLevel(HWND, DWORD); } // second approach alias setCooperativeLevel = HRESULT function(HWND, DWORD); setCooperativeLevel SetCooperativeLevel; It seemed pointless trying to recreate the template since above attempts did not expose the function signature which is necessary to get the template working. Any ideas? [1] https://gist.github.com/AndrewEdwards/560601a62ea890842ecac90bb41896a8#file-dsound-h-L248
Request assistance binding to Windows dsound.{lib, dll}
http://ftp.dlang.org/ctg/implib.html The above URL suggests that, on Windoze, I can create a D compatible lib from a dll file by issuing the command: implib /s dsound.lib dsound.dll The following file: sound.d === pragma(lib, "dsound") struct IDirectSound{}; alias LPDIRECTSOUND = IDirectSound*; extern(Windows) HRESULT DirectSoundCreate(LPGUID, LPDIRECTSOUND*, LPUNKNOWN); void main() { LPDIRECTSOUND directSound; DirectSoundCreate(null, , null); } compiled as such: dmd sound dsound.lib produces the output: OPTLINK (R) for Win32 Release 8.00.17 Copyright (C) Digital Mars 1989-2013 All rights reserved. http://www.digitalmars.com/ctg/optlink.html sound.obj(sound) Error 42: Symbol Undefined _DirectSoundCreate@12 --- errorlevel 1 Obviously I'm doing something incorrectly but I'm unable to see it. Please shed some light. The only thing I can see is that IDirectSound8 is improperly declared. It is struct generated form an interface which I have now idea of how to bind to from D: https://gist.github.com/AndrewEdwards/560601a62ea890842ecac90bb41896a8#file-dsound-h-L214 Thanks, Andrew
Re: Request assistance converting C's #ifndef to D
On 5/14/16 12:35 AM, Steven Schveighoffer wrote: On 5/13/16 12:59 AM, Andrew Edwards wrote: On 5/13/16 8:40 AM, Andrew Edwards wrote: That seems wrong. You can't assign to an enum. Besides, doesn't your declaration of MIN shadow whatever other definitions may be currently in effect? Okay, got it. It seams I just hadn't hit that bug yet because of other unresolved issues. Perhaps what you meant is something like this? static if (!is(typeof(MIN) : int)) enum MIN = 99; This seems to do the trick. But not exactly the way it's expected to. In the snippets below, C outputs 10 while D outputs 100; min.c = #define MIN 10 // [1] #include "mild.h" int main() { print(); return 0; } min.h = #include #ifndef MIN #define MIN 100 #endif void print() { printf("%d\n", MIN); } minA.d = enum MIN = 10; // [1] import minB; void main() { print(); } minB.d = static if (!is(typeof(MIN) : int)) enum MIN = 100; void print() { import std.stdio: writeln; writeln(MIN); } Is there a way to reproduce the same behavior? Are there reason's for not allowing this functionality or am I just misunderstanding and going about things the wrong way? Code like this is FUBAR. I have seen abuse of pre-processor in many places, and it never justifies the cleverness of how it is done. This may be the case, but since I am not yet at a level of understanding where I can discern what is justifiable or not. At the moment I'm simply trying to port over 15k LOC so that I can play with it in D and improve my understanding of what's going on. Note that min.h is providing an inlined function. Essentially, min.h is like a template with the definition of the template parameter defined by the including file. But you can only ever include min.h ONCE in your entire project, or you will get linker errors. This was an extremely simplified example. There is far more going than than this. Just trying not to lose any of the functionality until I understand what why things are done the way they are and how to better do it in D. D will always compile a module without external configuration. That is, print is compiled ONCE and only in the context that minA.d defines. Inlining can replace the print call with inline functions, but it will still be compiled according to the module's definitions, not external. TL;DR: there isn't a good way to port this code, because it's shit code, and D doesn't do that :) -Steve
Re: Request assistance converting C's #ifndef to D
On 5/13/16 3:23 PM, tsbockman wrote: On Friday, 13 May 2016 at 06:05:14 UTC, Andrew Edwards wrote: Additionally, what's the best way to handle nested #ifdef's? Those that appear inside structs, functions and the like... I know that global #ifdef's are turned to version blocks but versions blocks cannot be used inside classes, stucts, functions, etc. `static if` and `version()` can be nested, and both work just fine inside classes, structs, functions, etc.: module app; version = withPrint; struct A { version(withPrint) { class B { static if(size_t.sizeof == 4) { static void print() { import std.stdio : writeln; version(unittest) { writeln("Hello, 32-bit world of unit tests!"); } else { writeln("Hello, 32-bit world!"); } } } else { static void print() { import std.stdio : writeln; version(unittest) { writeln("Hello, presumably 64-bit world of unit tests!"); } else { writeln("Hello, presumably 64-bit world!"); } } } } } } void main() { A.B.print(); } Not sure what I was doing wrong earlier. Works perfectly fine now. Glad I asked because I usually just get frustrated and put it aside and usually never return to it. Thanks for the assist. (Try it on DPaste: https://dpaste.dzfl.pl/0fafe316f739)
Re: imports && -run [Bug?]
On 5/13/16 3:10 PM, tsbockman wrote: On Friday, 13 May 2016 at 01:16:36 UTC, Andrew Edwards wrote: command: dmd -run mod inc output: Undefined symbols for architecture x86_64: "_D3inc5printFZv", referenced from: __Dmain in mod.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) --- errorlevel 1 None of the variations of imports work when compiled with the -run switch but all work perfectly well without it. According to the DMD compiler manual, the -run switch only accepts a single source file: -run srcfile args... After the first source file, any further arguments passed to DMD will be interpreted as arguments to be passed to the program being run. Thanks, I guess I just expected it to work the same as rdmd does and didn't even bother trying to look in the manual regarding this. I fail to see why the compiler would be less capable at this task than rdmd. Since it is already build to accept multiple input files and knows more about what's going on during compilation than rdmd will ever know, in does not make sense that it should inferior in this regard: yet rdmd takes one imput file and sorts out all dependencies. Have you tried using DUB? It has lots of convenient features, including a `run` command that supports multiple source files: http://code.dlang.org/docs/commandline#run I've used dub before but it is not desired for what I'm trying to do. rdmd does the trick. Thank you.
Re: Request assistance converting C's #ifndef to D
On 5/13/16 7:51 AM, Andrew Edwards wrote: The following preprocessor directives are frequently encountered in C code, providing a default constant value where the user of the code has not specified one: #ifndef MIN #define MIN 99 #endif #ifndef MAX #define MAX 999 #endif I'm at a loss at how to properly convert it to D. I've tried the following: enum MIN = 0; static if(MIN <= 0) { MIN = 99; } it works as long as the static if is enclosed in a static this(), otherwise the compiler complains: mo.d(493): Error: no identifier for declarator MIN mo.d(493): Error: declaration expected, not '=' This however, does not feel like the right way to do thinks but I cannot find any documentation that provides an alternative. Is there a better way to do this? Thanks, Andrew Additionally, what's the best way to handle nested #ifdef's? Those that appear inside structs, functions and the like... I know that global #ifdef's are turned to version blocks but versions blocks cannot be used inside classes, stucts, functions, etc.
Re: Request assistance converting C's #ifndef to D
On 5/13/16 8:40 AM, Andrew Edwards wrote: That seems wrong. You can't assign to an enum. Besides, doesn't your declaration of MIN shadow whatever other definitions may be currently in effect? Okay, got it. It seams I just hadn't hit that bug yet because of other unresolved issues. Perhaps what you meant is something like this? static if (!is(typeof(MIN) : int)) enum MIN = 99; This seems to do the trick. But not exactly the way it's expected to. In the snippets below, C outputs 10 while D outputs 100; min.c = #define MIN 10 // [1] #include "mild.h" int main() { print(); return 0; } min.h = #include #ifndef MIN #define MIN 100 #endif void print() { printf("%d\n", MIN); } minA.d = enum MIN = 10; // [1] import minB; void main() { print(); } minB.d = static if (!is(typeof(MIN) : int)) enum MIN = 100; void print() { import std.stdio: writeln; writeln(MIN); } Is there a way to reproduce the same behavior? Are there reason's for not allowing this functionality or am I just misunderstanding and going about things the wrong way? [1] same result whether placed before or after the #include/import statement. though I'm not sure if such a thing will actually work, since order-dependent declarations in D are a kind of dangerous territory to tread on. So what is the current best practice when encountering such statements during porting? T
imports && -run [Bug?]
module mod; // import inc; [1] // import inc: p=print; [1] // static import inc; [1] void main() { // import inc: print; // [2] print(); // static import inc; // [3] // inc.print(); } -- module inc; /*public*/ void print() // [4] { import std.stdio: writeln; writeln("You made it!"); } -- compiler: DMD v2.071.0 os: OS X El Capitan (10.11.3) -- command: dmd -run mod inc output: Undefined symbols for architecture x86_64: "_D3inc5printFZv", referenced from: __Dmain in mod.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) --- errorlevel 1 None of the variations of imports work when compiled with the -run switch but all work perfectly well without it.
Re: Request assistance converting C's #ifndef to D
On 5/13/16 8:00 AM, H. S. Teoh via Digitalmars-d-learn wrote: On Fri, May 13, 2016 at 07:51:17AM +0900, Andrew Edwards via Digitalmars-d-learn wrote: The following preprocessor directives are frequently encountered in C code, providing a default constant value where the user of the code has not specified one: #ifndef MIN #define MIN 99 #endif #ifndef MAX #define MAX 999 #endif I'm at a loss at how to properly convert it to D. I've tried the following: enum MIN = 0; static if(MIN <= 0) { MIN = 99; } [...] That seems wrong. You can't assign to an enum. Besides, doesn't your declaration of MIN shadow whatever other definitions may be currently in effect? Okay, got it. It seams I just hadn't hit that bug yet because of other unresolved issues. Perhaps what you meant is something like this? static if (!is(typeof(MIN) : int)) enum MIN = 99; This seems to do the trick. though I'm not sure if such a thing will actually work, since order-dependent declarations in D are a kind of dangerous territory to tread on. So what is the current best practice when encountering such statements during porting? T
Request assistance converting C's #ifndef to D
The following preprocessor directives are frequently encountered in C code, providing a default constant value where the user of the code has not specified one: #ifndef MIN #define MIN 99 #endif #ifndef MAX #define MAX 999 #endif I'm at a loss at how to properly convert it to D. I've tried the following: enum MIN = 0; static if(MIN <= 0) { MIN = 99; } it works as long as the static if is enclosed in a static this(), otherwise the compiler complains: mo.d(493): Error: no identifier for declarator MIN mo.d(493): Error: declaration expected, not '=' This however, does not feel like the right way to do thinks but I cannot find any documentation that provides an alternative. Is there a better way to do this? Thanks, Andrew
Re: Error with associative array initializer DMD32 D Compiler v2.070.0
On 3/3/16 7:01 PM, MGW wrote: immutable long[string] aa = [ "foo": 5, "bar": 10, "baz": 2000 ]; The only way this can be done outside the body of a function is if it is a manifest constant. This works: enum long[string] aa = [ "foo": 5, "bar": 10, "baz": 2000 ];
Re: Alternate databases
On 2/21/16 12:23 AM, yawniek wrote: On Saturday, 20 February 2016 at 13:09:53 UTC, Andrew Edwards wrote: I'm searching for client drivers for the following databases. Are the any available? https://rethinkdb.com/docs/install-drivers/ http://docs.basho.com/riak/latest/dev/references/client-implementation/ Thanks, Andrew none for riak afaik, for rethink i found: https://github.com/search?utf8=%E2%9C%93=language%3Ad+rethinkdb=Repositories=searchresults if you try them, please report back if any of them is already usablee Thank you very much for the links. Will do.