is char[] faster than string?
I have a lot of string concatenation to do and I'm wondering if char[] is faster? Does it simply extend the buffer or are new buffers created every time? What I am looking for is something like StringBuilder in C#.
Re: Single exe vibe.d app
On Wednesday, 5 April 2017 at 12:42:23 UTC, evilrat wrote: On Wednesday, 5 April 2017 at 12:13:38 UTC, Satoshi wrote: Hi, How can I build single exe application with vibe.d (windows)? now it require zlib.dll, libeay32.dll and ssleay32.dll But I need it as single app. btw, if all you need is to ship it as a single file and don't care if it writes anything, you can probably compile-in those .dll's to your .exe as string with D import statement and write them on disk from static module ctor (static shared this{} at module scope) when it launched. Why is the writing to disk necessary? Seems like a costly step for no real benefit. The dll gets read in to memory anyways. https://github.com/fancycode/MemoryModule
opDispatch/template get this
I am using opDispatch to wrap function calls Error: 'this' is only defined in non-static member functions, not opDispatch!"foo" class X { auto localfoo() { return 3; } template opDispatch(string name, Args...) { static if (name == `foo`) { alias opDispatch = () { return this.localfoo(); }; } which doesn't work because of this I tried template opDispatch(string name, this _this, Args...) { static if (name == `foo`) { alias opDispatch = () { return _this.localfoo(); }; } but that doesn't work either ;/ I call it like auto y = x.foo(); but foo isn't found https://dpaste.dzfl.pl/bf31f535340f class X { auto localfoo() { return 3; } auto localfoo2(int x) { return x; } template opDispatch(string name, Args...) { static if (name == `foo`) { alias opDispatch = () { return this.localfoo(); }; } static if (name == `bar`) { alias opDispatch = () { return this.localfoo2(); }; // need to be able to pass Args properly here } } } void main() { auto x = new X(); auto z = x.localfoo(); auto y = x.foo(); auto q = x.bar(); }
Re: Write file at compile time?
On Monday, 3 April 2017 at 19:34:36 UTC, Adam D. Ruppe wrote: On Monday, 3 April 2017 at 19:25:35 UTC, Inquie wrote: what if I don't care about security reasons? I'm only needing it for developmental purposes. Why does it have to be at compile time then? Just run an ordinary runtime program as part of your develop process; run a helper file in your makefile before compiling it. Because it the code doesn't compile one has to copy and paste the pragma output to a d file and compile it to find the errors. It is useful to help debug mixins. Since D is pretty sorry at giving useful information for mixins it is easier to write the mixins out to disk in a d file then input them back in to the program. A simple static switch can alternate between the two. If we could output at compile time then we could 1. compile 2. flip switch 3. compile and get useful error messages rather than 1. compile 2. copy pragma to do 3. flip switch 4. compile and get useful error messages the pragma copy is, by far, the slowest step here and the others can be automated to basically happen in one step(although, I guess with some work one could automate the copying of the pragma too but it is not as robust). Would be much easier to simply have the ability to write to disk instead of the console.
Re: Write file at compile time?
On Monday, 3 April 2017 at 19:06:01 UTC, Meta wrote: On Sunday, 2 April 2017 at 19:42:52 UTC, Inquie wrote: I would like to write the output of a manifest constant at compile time to a file instead of console using pragma(msg). Is this possible? D does not allow IO at compile time for security reasons. what if I don't care about security reasons? I'm only needing it for developmental purposes.
Re: delegate with optional parameters
On Monday, 3 April 2017 at 03:08:22 UTC, Ali Çehreli wrote: On 04/02/2017 03:24 PM, Inquie wrote: >> Show a usage, someone certainly propose a pattern that does the job. > > int delegate() f; > void delegate(int) f; That won't work because both of those are variables and variables don't have overloading. > These are effectively overload methods, but my guess is that D won't > support it like overloads. > e.g., > > int f(); > void f(int); Yep, both 'f' are functions there. I'm having difficulty understanding your actual need as well. :/ A guess: It is possible to determine delegate parameter list at compile time like std.concurrency.receive does. Ali Yes, but they are really not any different. They only look different. A field can be a function just like a method because they look exactly the same except on is in a vtable and the other is in the fields memory. But both point functions. The only difference is that we can't write to the vtable to overwrite a value easily but we can to a delegate(no hackery). So, it would be nice to be able to overload them. Effectively we can extend the vtable out in to the fields. (it would require a bit of work to make it work identical to a class, but it could, the outside world would know no difference). If one wants: It essentially allows for methods to be modifiable at run time(something that classes can't do without unsafely hacking the vtable) and that is exactly why I have used it, but overloading causes a problem because only the name collides yet it works with the methods case but not the field delegates(a field delegate is essentially a method, is the point(for functional usage)).
Re: delegate with optional parameters
On Sunday, 2 April 2017 at 21:47:55 UTC, Basile B. wrote: On Sunday, 2 April 2017 at 20:48:09 UTC, Inquie wrote: On Sunday, 2 April 2017 at 20:02:56 UTC, Basile B. wrote: On Sunday, 2 April 2017 at 19:24:14 UTC, Inquie wrote: is it possible to create a delegate that takes an optional number of parameters and/or return type? T delegate(S...)(S) special_delegate; I guess this is impossible? alias Dg(Return, Params...) = Return delegate(Params); Dg!(int,float, string) myDg; What I mean is that I want to be able to overload delegates like one can do with normal members. Show a usage, someone certainly propose a pattern that does the job. int delegate() f; void delegate(int) f; These are effectively overload methods, but my guess is that D won't support it like overloads. e.g., int f(); void f(int);
Re: delegate with optional parameters
On Sunday, 2 April 2017 at 20:02:56 UTC, Basile B. wrote: On Sunday, 2 April 2017 at 19:24:14 UTC, Inquie wrote: is it possible to create a delegate that takes an optional number of parameters and/or return type? T delegate(S...)(S) special_delegate; I guess this is impossible? alias Dg(Return, Params...) = Return delegate(Params); Dg!(int,float, string) myDg; What I mean is that I want to be able to overload delegates like one can do with normal members.
Write file at compile time?
I would like to write the output of a manifest constant at compile time to a file instead of console using pragma(msg). Is this possible?
delegate with optional parameters
is it possible to create a delegate that takes an optional number of parameters and/or return type? T delegate(S...)(S) special_delegate; I guess this is impossible?
Re: Building DMD
On Saturday, 1 April 2017 at 00:12:10 UTC, Inquie wrote: So, I rebuilt everything again from scratch, I fixed up the make files and such and everything went smooth. I was able to not have the errors. [...] I was able to solve the comdat problem by moving a local function outside a loop(didn't really need to define it in the loop)... but it had no problems on previous build. Seems that the function was being defined several times due to ctfe or whatever and that caused problems.
Re: Building DMD
So, I rebuilt everything again from scratch, I fixed up the make files and such and everything went smooth. I was able to not have the errors. I think what I did first was I built dmdx64 then copied it to the bin dir and tried to use it but got the phobos errors. I then tried to build druntime/phobos and it was trying to use that version of the dmd, which I guess was faulty because phobos\druntime wasn't correct. Instead, I simply built everything first then copied everything together and that seemed to work. It would be real nice if we could have the x64 version added to the distro so people don't have to rebuild each time. Also, the make files needs to be updated to support the latest VS. It's nice that the build process went pretty smooth otherwise though. Seems to work but now I run in to two problems: If I try to compile for win32 I get Error: more than 32767 symbols in object file if I try to compile for x64 I get fatal error LNK1179: invalid or corrupt file: duplicate COMDAT '_D6modu2557__T19fooVAyaa13_6d50686f746f73686f70434f4dVAAyaA82a11_4170706c69636174696f6ea8_446f63756d656e74a8_4172744c61796572a8_546578744974656da10_536f6c6964436f6c6f72a8_524742436f6c6f72a9_47726179436f6c6f72a9_434d594b436f6c6f72a8_4c6162436f6c6f72a8_485342436f6c6f72a8_4c61796572536574a6_4c6179657273a9_4c6179657253657473a9_4172744c6179657273a12_486973746f72795374617465a12_446f63756d656e74496e666fa9_53656c656374696f6ea7_4368616e6e656ca11_584d504d65746164617461a16_4d6561737572656d656e745363616c65a8_4368616e6e656c73a13_486973746f7279537461746573a10_4c61796572436f6d7073a9_4c61796572436f6d70a9_506174684974656d73a8_506174684974656da12_537562506174684974656d73a11_537562506174684974656da10_50617468506f696e7473a9_50617468506f696e74a10_436f756e744974656d73a9_436f756e744974656da13_436f6c6f7253616d706c657273a12_436f6c6f7253616d706c6572a11_507265666572656e636573a9_446f63756d656e7473a9_54657874466f6e7473a8_54657874466f6e74a9_4e6f74696669657273a8_4e6f746966696572a14_4d6561737572656d656e74! 4c6f67a16_416374696f6e44657363726970746f72a10_416374696f6e4c697374a15_416374696f6e5265666572656e6365a18_50686f746f43444f70656e4f7074696f6e73a20_526177466f726d61744f70656e4f7074696f6e73a14_5044464f70656e4f7074696f6e73a14_4550534f70656e4f7074696f6e73a16_4449434f4d4f70656e4f7074696f6e73a20_43616d6572615241574f70656e4f7074696f6e73a20_50686f746f73686f70536176654f7074696f6e73a14_424d50536176654f7074696f6e73a14_474946536176654f7074696f6e73a14_455053536176654f7074696f6e73a15_4a504547536176654f7074696f6e73a14_504446536176654f7074696f6e73a19_5049435446696c65536176654f7074696f6e73a16_5069786172536176654f7074696f6e73a14_504e47536176654f7074696f6e73a14_526177536176654f7074696f6e73a17_534749524742536176654f7074696f6e73a16_5461726761536176654f7074696f6e73a15_5469536176654f7074696f6e73a16_444353315f536176654f7074696f6e73a16_444353325f536176654f7074696f6e73a24_4578706f72744f7074696f6e73496c6c7573747261746f72a23_4578706f72744f7074696f6e7353617665466f72576562a23_4269746d6170436f6e76657273! 696f6e4f7074696f6e73a24_496e6465786564436f6e76657273696f6e4f7074696f6e73a7_4e6f436f6c6f72a19_50726573656e746174696f6e4f7074696f6e73a14_47616c6c6572794f7074696f6e73a20_47616c6c65727942616e6e65724f7074696f6e73a20_47616c6c657279496d616765734f7074696f6e73a23_47616c6c6572795468756d626e61696c4f7074696f6e73a25_47616c6c657279437573746f6d436f6c6f724f7074696f6e73a22_47616c6c65727953656375726974794f7074696f6e73a19_436f6e7461637453686565744f7074696f6e73a21_506963747572655061636b6167654f7074696f6e73a12_42617463684f7074696f6e73a11_53756250617468496e666fa13_50617468506f696e74496e666fZ19. It seems I get the corrupt comdat when using come ctfe stuff.
Re: Building DMD
On Friday, 31 March 2017 at 14:24:43 UTC, Stefan Koch wrote: On Friday, 31 March 2017 at 14:19:59 UTC, Inquie wrote: On Friday, 31 March 2017 at 08:20:51 UTC, Nicholas Wilson wrote: [...] Yes, I downloaded druntime from github and built it as I did phobos. The 64-bit make files have issues because paths are hard coded and things are not so simple as they used to be, but I was able to, I think, get everything to work. So, if this is a druntime issue, and if built it "correctly" is there any settings I would have to change to add them or anything like that? Any way to check if those symbols exist in druntime64.lib? It seems the methods are in src\core\exception.d so not sure why they wouldn't be added. But yes, I downloaded everything nearly simultaneously and build them. Download the source of a release version. ~master is always a little unstable. picking the ~stable branch for phobos druntime and dmd should end up in a working compiler close to the latest release. So, I downloaded all stables an rebuilt and replaced and same error ;/(dmd, druntime, and phobos) The error seems to be in something else: 1. I had to use fix up the paths to get win64.mak to compile because the paths are hard coded for old visual studio/clang/sdk's that simply do not translate in to the newer visual studio revamps. (wish it did, because it's a pain to find all the right files). 2. druntime64.lib has _d_arrayboundsp and _d_assertp in it(doing a text search). Any ideas? I'm at a loss. So close but so far!
Re: Building DMD
On Friday, 31 March 2017 at 08:20:51 UTC, Nicholas Wilson wrote: On Friday, 31 March 2017 at 07:23:42 UTC, Inquie wrote: I am trying to build DMD 64-bit. I was able to build everything after getting the paths fixed for zlib, druntime, and phobos. Everything seems to compile. I replaced all the files generated in to the dmd directories of the old ones. (phobos64.lib, gcstub.obj, dmd.exe) But anytime I build my projects that worked fine in the x86 compiler I get the errors: Error 42: Symbol Undefined __d_arrayboundsp Error 42: Symbol Undefined __d_assertp These seem like dmd runtime functions or something similar but not sure why they don't exist. Any ideas? Are these functions suppose to be in phobos or druntime? and why aren't they showing up when I build from sources and replaced everything, I believe, correctly? Those are runtime functions. Did you build druntime64.lib? If so is it up to date? The compiler and runtime are required to by in sync. Alternately compiling with `-release -boundscheck=off` should remove reliance on those functions (this is not a proper solution). Yes, I downloaded druntime from github and built it as I did phobos. The 64-bit make files have issues because paths are hard coded and things are not so simple as they used to be, but I was able to, I think, get everything to work. So, if this is a druntime issue, and if built it "correctly" is there any settings I would have to change to add them or anything like that? Any way to check if those symbols exist in druntime64.lib? It seems the methods are in src\core\exception.d so not sure why they wouldn't be added. But yes, I downloaded everything nearly simultaneously and build them.
Building DMD
I am trying to build DMD 64-bit. I was able to build everything after getting the paths fixed for zlib, druntime, and phobos. Everything seems to compile. I replaced all the files generated in to the dmd directories of the old ones. (phobos64.lib, gcstub.obj, dmd.exe) But anytime I build my projects that worked fine in the x86 compiler I get the errors: Error 42: Symbol Undefined __d_arrayboundsp Error 42: Symbol Undefined __d_assertp These seem like dmd runtime functions or something similar but not sure why they don't exist. Any ideas? Are these functions suppose to be in phobos or druntime? and why aren't they showing up when I build from sources and replaced everything, I believe, correctly?
64-bit DMD
Is there a 64-bit DMD compiler that doesn't have the 2GB memory limitations that the 32-bit one has? I am not talking about compiling 64-bit programs but the dmd binary itself.
Re: debug mixins
On Wednesday, 15 March 2017 at 03:50:21 UTC, Jonathan M Davis wrote: On Wednesday, March 15, 2017 03:43:20 Inquie via Digitalmars-d-learn wrote: [...] Related: https://issues.dlang.org/show_bug.cgi?id=5051 - Jonathan M Davis So, after 3 years, nothing?
Re: strange CFTE issue
On Wednesday, 15 March 2017 at 03:40:42 UTC, ag0aep6g wrote: On 03/15/2017 03:01 AM, Inquie wrote: If I do something like enum X = Methods!(C); foreach(x; X) { mixin(x); } I get an error about x not being a compile time variable. (code above is simplified, the error has nothing to do with the form but of the foreach(x ) "Compile time variable" may be misleading here. The compiler does not try to figure out what values are actually constant at compile time. Rather, the language defines some specific cases where it's guaranteed that a value is a compile-time constant. Only then can you use it in static contexts such as mixins. Other values are rejected, even if they would turn out be constant on a closer look. `foreach` is mostly a run-time feature. There is a special case when you iterate over a "compile-time list" [1] (aka AliasSeq, formerly TypeTuple). In that case, the loop variable is recognized as a constant. That variant of `foreach` is also dubbed a "static foreach" (even though the `static` keyword is not used). Note that it's not a "static foreach" when you iterate over an array, no matter if that array is constant at compile time or not. So this works: import std.meta: AliasSeq; foreach (x; AliasSeq!("int foo;", "double bar;")) mixin(x); But this doesn't: foreach (x; ["int foo;", "double bar;"]) mixin(x); This is expected and works as intended. Without the definition of your `Methods` template, I can't say for sure if you're hitting this or if something else is going on. But if your `X` is an array, this is it. but if I wrap it in a function it works string foo() { enum X = Methods!(C); string y = ""; foreach(x; X) { y ~= x; } return y; } mixin(y); (I'm assuming that last line should be `mixin(foo());`.) The return value of `foo` is recognized as a compile-time constant there, because you call it in a context that forces it. This is called CTFE. Note that you cannot assign the result of `foo()` to a variable first: string y = foo(); /* no CTFE */ mixin(y); /* no go */ That's because `y` is a normal variable, which is not a recognized compile-time constant. The value could of course be evaluated at compile-time, but the compiler doesn't attempt CTFE opportunistically. The only diff, of course, is the foreach in the first case mixes in on each iteration, while in the second it doesn't... but it shouldn't matter. in both cases x is the same.. and it definitely is a compile time constant in both. To the compiler it's not a "compile-time constant" in either of them (in a rather specific sense of the term "compile-time"). During CTFE, run-time rules apply. So in `foo`, `x` is a normal variable. The same rules apply as for actual run-time variables. Only the return value of `foo` is seen as a compile-time value by the compiler. You're not the first one who stumbles over this meaning of "compile time". CTFE happens at compile time, and has "compile time" in the name, but during CTFE you're actually dealing with "run time" values that might never see the actual run time. Maybe these things could use some better names. [1] https://dlang.org/ctarguments.html Thanks, it explains it, but there is one difference. The array is assigned to an enum, so surely the compiler can figure that out? It should be similar to AliasSeq. I could probably wrap AliasSeq around it and it work or convert it to an AliasSeq. Seems like an issue with the compiler. Remember, it's enum X = Methods!(C); foreach(x; X) { mixin(x); } and not string X = Methods!(C); foreach(x; X) { mixin(x); } that should be quite difference and the static foreach in the first case and non-static foreach in the second. Essentially what you are saying is that if I were to have Methods! return an AliasSeq then it would work. It is a CTFE that returns an array. If there is a function that can convert the the array to an AliasSeq of tuples there should be no problem, although I don't see how to do that, it should be possible? But, this all then seems to be skirting the fact that the loop is still over a compile time constant(enum or AliasSeq, shouldn't matter) and should work.
Re: scope(~this)
On Wednesday, 15 March 2017 at 08:17:11 UTC, thedeemon wrote: On Tuesday, 14 March 2017 at 14:35:11 UTC, Inquie wrote: There is really no any arrays to keep track of or anything like that matter you stated. ... 3 steps: ... 3. The compiler calls all the delegates on destruction. Here you are. "All the delegates" - where are they stored? This is the array of delegates I was talking about. In a library solution you don't even need to think about the string mixins and variables copying. Just make a method that takes a delegate. Then call it like this: scopeThis({ dealloc(x); }); The compiler will create the delegate for you and store x in the heap in the first place. In scopeThis() you just add the passed delegate to an array of other delegates, then in destructor call them. Seems rather trivial, I don't see a need for a language feature that affects all the classes and objects. If it is trivial, can you write up a quick solution. I don't see how to accomplish it easily. If ScopeThis({dealloc(x);}); copies locals to the heap, then that solves part 1 trivially. But a bit of CT reflection is required to store the delegates in the class and I don't see it as being trivial... although it very well might be.
debug mixins
So, is it possible to debug string mixins? I ran visual D and tried to step in to a function that was generated by a mixin and it brought an open file dialog box asking me to load the source code where the function was located... of course, it wasn't located anywhere except in the mixin string. This leads to the idea, why can't the compiler simply output the mixin string to a file then the debugger can load that source file? One of the most frustrating things about D is not having the ability to debug it's powerful meta programming in any reasonable way. (bad enough having to resort to using pragma(msg)) But we can't even debug the results of those meta programming in the case of string mixins because there is no way to step in to them... It seems all the machinery is there, but just a few extra steps are needed.
strange CFTE issue
If I do something like enum X = Methods!(C); foreach(x; X) { mixin(x); } I get an error about x not being a compile time variable. (code above is simplified, the error has nothing to do with the form but of the foreach(x ) but if I wrap it in a function it works string foo() { enum X = Methods!(C); string y = ""; foreach(x; X) { y ~= x; } return y; } mixin(y); The only diff, of course, is the foreach in the first case mixes in on each iteration, while in the second it doesn't... but it shouldn't matter. in both cases x is the same.. and it definitely is a compile time constant in both. (Methods is just a wrapper on __traits(allMembers) but does some manipulation (stole the code from somewhere on the forum))
Re: code folding
On Tuesday, 14 March 2017 at 20:56:02 UTC, Ali Çehreli wrote: On 03/13/2017 10:29 AM, Inquie wrote: Does D have any nice way to specify a block for cold folding? I have a very large set of structs and I'd like to be able to code fold them all at once and together. I have been using static if(true) { ... junk } but the static if is uninformative since that is the only line that is shown when folded. A comment helps but still kinda ugly. C# has #regions and hopefully D has something as useful. There is version: version (all) { // ... } You can define your own version identifiers as well: version = some_descriptive_name; version (some_descriptive_name) { // ... } Ali Oh, that might be better. I thought of versions but I didn't want to have to define anything... didn't know about all.
Re: Filter out common object functions
On Tuesday, 14 March 2017 at 19:43:59 UTC, Adam D. Ruppe wrote: On Tuesday, 14 March 2017 at 19:39:26 UTC, Inquie wrote: __traits(allMembers, T); Try derivedMembers instead. That doesn't work, unfortunately, probably because of the types I'm using(just returns object. What I can do is this: enum isElementOfObject(alias T) = (staticIndexOf!(T, __traits(allMembers, Object)) < 0) ? true : false; enum isElementOfIDispatch(alias T) = (staticIndexOf!(T, __traits(allMembers, IDispatch)) < 0) ? true : false; enum membersList = Filter!(isElementOfIDispatch, Filter!(isElementOfObject, __traits(derivedMembers, T))); It would be nice if instead of having to make a large list of isElementOf, I could pass the types to the predicate: enum isElementOf(alias S, alias T) = (staticIndexOf!(T, __traits(allMembers, S)) < 0) ? true : false; enum membersList = Filter!(isElementOf!Object, __traits(derivedMembers, T))); and ultimately give a list of objects: enum membersList = Filter!(isElementOf!(Object, IDispatch), __traits(derivedMembers, T))); Would be pretty cool if D could do that, but I doubt it can ;/ (not logically impossible, sort of like currying or something)
Filter out common object functions
I am iterating over the members of classes and interfaces and get things like hash, this, etc. These are causing problems in my code. I would like to get only the "specified" members. While I can filter out __traits(allMembers, T); using Erase, it is tedius and error prone. Is there a way to get only the immediate members? Non-inherited, and "common"(for a lack of a better word), this(), for example, is specified by the language... i don't need it, just functions the user specifies in the type.
Re: Function pointer pitfalls
On Tuesday, 14 March 2017 at 19:14:34 UTC, H. S. Teoh wrote: On Tue, Mar 14, 2017 at 06:59:58PM +, Inquie via Digitalmars-d-learn wrote: [...] [...] > [...] [...] [...] [...] Keep in mind, though, that the above creates a function pointer with the same signature as the member function, but you may not be able to assign a member pointer to it because it lacks object context. To wit: [...] Yeah, I don't think I'll run in to that problem since I'm constructing the function ahead of time and only need the declaration but we'll see. Thanks again.
Re: Function pointer pitfalls
On Tuesday, 14 March 2017 at 17:42:34 UTC, H. S. Teoh wrote: On Tue, Mar 14, 2017 at 05:05:10PM +, Inquie via Digitalmars-d-learn wrote: I am generating member function pointers using the declaration specified from a standard member function. The standard member function is a valid D function that could use any types. Is there any pitfalls like there are in C++ from generating a function pointer from them? e.g., X foo(A,B,C) @R @S @T -> X function(A,B,C) @R @S @T fooptr; In my case, there are no attributes, so that might ease the burden. e.g., a template that converts a member function declaration. ToFunctionPtr!("X foo(A,B,C) @R @S @T)", fooptr) or ToFunctionPtr!(foo, fooptr) gives function pointer declaration who's declaration is the same as foo. Not 100% sure what exactly you mean... but I'm guessing you have some aggregate X with some member function method(), and you want to get a function pointer from that? Perhaps something like this? struct X { int method(float x) { return 0; } } typeof() membptr; pragma(msg, typeof(membptr)); // prints `int function(float x)` If you need to refer to the function pointer type frequently, you could alias it to something easier to type; alias FuncPtr = typeof(); FuncPtr membptr; T Thanks, that will work. In C++ there were issues with pointers and one would have to properly group the function name or some thing like that. Your suggestion avoids all that.
Inline mixin
Many times I need to build a type using a string. I have to resort to building the entire expression/statement using the mixin: mixin("This is a long and complex expression where I only need to modify X") Is there any way to do a sort of "inline mixin"? This is a long and complex expression where I only need to modify mixin("X") ? e.g., mixin("int "~name~" = 3;") vs int mixin(name) = 3; (a gross simplification) Maybe a template could handle it or is something like this impossible by D's gramar?
Re: code folding
On Tuesday, 14 March 2017 at 17:07:57 UTC, Adam D. Ruppe wrote: On Monday, 13 March 2017 at 17:29:41 UTC, Inquie wrote: Does D have any nice way to specify a block for cold folding? I personally sometimes use // some description { // } since my editor does a really good job matching {}, even in comments so it is convenient to jump anywhere, and i can search the description text to get back to it from anywhere. I can fold it too but i personally prefer just jumping it than actually folding it. Yeah, that would be better, unfortunately VS/VD doesn't do this.
Function pointer pitfalls
I am generating member function pointers using the declaration specified from a standard member function. The standard member function is a valid D function that could use any types. Is there any pitfalls like there are in C++ from generating a function pointer from them? e.g., X foo(A,B,C) @R @S @T -> X function(A,B,C) @R @S @T fooptr; In my case, there are no attributes, so that might ease the burden. e.g., a template that converts a member function declaration. ToFunctionPtr!("X foo(A,B,C) @R @S @T)", fooptr) or ToFunctionPtr!(foo, fooptr) gives function pointer declaration who's declaration is the same as foo.
Re: code folding
On Tuesday, 14 March 2017 at 16:29:15 UTC, Mike Parker wrote: On Tuesday, 14 March 2017 at 15:44:27 UTC, Inquie wrote: So, with all the bloviating, all I have arrived at is that my original hack is still the only way to get the cold folding I wanted(the original use case I had in mind, even though I'd rather have proper code structuring support in general). Generally when even a hint of a suggestion of a language addition is created, the worms come out to party... If it's something you feel strongly about, then the way to go about it is to put together a DIP. There was a time when you could open a forum post about a new feature and eventually see it added, but those days are long gone (for good reason). If any new feature is going to have any hope of getting in these days, then it needs someone to champion it through the DIP process. It's not that I feel strongly about, I simply would like the best useable solution. Like usually what happens, my original post was taken completely out of context: "Does D have any nice way to specify a block for cold folding? I have a very large set of structs and I'd like to be able to code fold them all at once and together. I have been using static if(true) { ... junk } but the static if is uninformative since that is the only line that is shown when folded. A comment helps but still kinda ugly. C# has #regions and hopefully D has something as useful. " No where do I mention anything about a language change. I asked if D had something useful and better than my hack. What it seems to stir up is a bunch of people that have a fear based reaction, which I can only hypothesize why. Usually it involves someone trying to state absolutely why what I am doing is wrong or bad and all they offer is anecdotal evidence and their opinions. None of which are helpful or useful. I would wager that more than 50% of D users have this mentality, and given that, it is highly unlikely that I could push for such changes. I'd get more done and have more use by forking D and adding my own features for my own personal use. What perplexes me is why so many have such a disdain for any change that ultimately doesn't effect them much. If, say the "#regions" feature was implement, or some variant, and they are right and it is useless then chances of them ever encountering such code is slim... and code they do encounter would generally not a a problem(light use). Yet, those that do use it(in house), which, if it is so bad, according to them, should be rare, would benefit from it, at least in their own mind. You know, there is something called "Survival of the fittest" and if an idea is truly bad then it will die out. Many people don't even want to give any idea a chance to go through that process... fear of it being successful? Fear they might have to learn something new? Fear it might require them to adapt their understanding of how things work? Fear of it being a waste of time? Fear of it causing a nuclear meltdown? When it will affect them almost nil, and they rail against it, it is some deep seeded fear from something... Unless they can give nearly absolute mathematical proof why it is invalid/wrong. Anyways, my hack is good enough for me. If they ever see any of my code, they might rather have allowed something a bit more syntactically pleasing and so they can blame themselves(which they won't). Of course, we could always depreciate "static if (true)" to prevent that possibility! Maybe that is the real solution?
Re: code folding
On Tuesday, 14 March 2017 at 15:18:00 UTC, bachmeier wrote: On Tuesday, 14 March 2017 at 00:38:12 UTC, Vladimir Panteleev wrote: FYI: The "you must implement my feature request or D will never succeed" attitude is rather common and never helpful. Not to mention that such an argument would be demonstrably false: every popular language without the feature you want has apparently succeeded despite not having said feature. This is a little different, however, in the sense that there is no reason to add a feature to the language to do what is requested. If you use Emacs, you can get the same thing in any language using comments: https://www.emacswiki.org/emacs/FoldingMode and I agree that having an such a feature(for #region) would better be handled by comments(assuming it, itself, can be commented out easily). But either way, we do not have the capabilities with D in the first place. I do not use Emacs but the Visual D, which I assume is the sponsored IDE for D. This is an issue for the IDE, not for the language, and changing the language would not have any effect on IDE support for code folding. Remember, it is not just about code folding(which seems to be the common misconception). The cold folding is a sort of byproduct of struct defining language features... of which, D has very little of. Version, is a good one for certain things, but useless here for code structure itself. My original statement was if D had the ability to do proper code folding rather than resorting to hacks and it has been derailed in to an language vs ide battle. So, with all the bloviating, all I have arrived at is that my original hack is still the only way to get the cold folding I wanted(the original use case I had in mind, even though I'd rather have proper code structuring support in general). Generally when even a hint of a suggestion of a language addition is created, the worms come out to party...
Re: code folding
Just for fun: 1. Folding directives are glorified comments. #region has zero meaning to the compiler; it's a hint to the editor to allow code folding. It doesn't do any namespacing or scoping. Why, exactly, are we writing code to accommodate the editor? It boggles my mind that we'd add significant lines of code to our project that do nothing but offer organizational hints to the editor. Even traditional comments are a better value for your keystroke, because they can be more expressive. And folding is certainly no substitute at all for bona-fide refactoring. BS. I use regions in C# to separate disparate code. I like to know how my code functions and the structure of code relative to itself. It helps conceptually understand the code better. 2. Folding is used to sweep code under the rug. Got a bunch of boring boilerplate code that makes your eyes water? A slew of ugly, gnarly code that nobody in their right mind wants to look at? Hide it in a region and fold that sucker into oblivion! Problem solved, right? Hardly. Your project is now full of crappy code that you can't see. That's worse. Much worse! Code that hides from you is code that will rot in the most putrescent and painful way possible. Your code should be front and center at all times -- exposed to as many programmers' eyes, and as much healing light, as possible. No matter what color language you use to object to something doesn't mean it is more true. I guess this guy doesn't realize that you can unfold the code. 3. Folding is used to mask excessive length. The presence of folded code can lull developers into a false sense of what clean code looks like. Under the cover of folding, you can end up writing long, horrible spaghetti code blocks. If the code needs the crutch of folding to look organized, it's bad code. Well duh, that is one of the benefits of it. I'll state it again. I use regions in C# to separate disparate code. I like to know how my code functions and the structure of code relative to itself. It helps conceptually understand the code better. 4. Folding can hide deficiencies in your editor. The presence of so-called "standard" boilerplate regions like "Public Constructors" and "Public Properties" and "Events" is not a feature. It's a bug. The editor should automatically offer to fold up these common structural blocks for you! I'm continually amazed that programmers spend time doing this scutwork when they could be writing useful code. Or at least demanding a smarter code editor. This guy obviously doesn't know what a bug is so how could we trust his "expertise"? But which is it? the language or the stupid IDE? I'm confused? This guy probably never used #regions to learn how to use them properly and has such a pathetic uptight life that all he can do is bitch about other peoples poor code practices. That is no proof of anything. Instead of bitching, like most people, why didn't he write a constructive article about how to use #regions properly? Anyone can write a blog these days kinda sad actually. ;/ I guess you will then state that he is an amazing programmer because of SO and that we should all bow down to his wisdom? yeah, right
Re: code folding
On Tuesday, 14 March 2017 at 00:38:12 UTC, Vladimir Panteleev wrote: On Monday, 13 March 2017 at 21:33:56 UTC, Inquie wrote: One can say that it is a useless feature because D doesn't have it... or one could say that D is useless because it doesn't have it. A nice balance is simply to say "It is a useful feature that has proven it's worth and it is time that D implements something like it". As D becomes more mainstream, these features will be requested. D should learn from other language/compilers just as other languages/compilers have learned from it. (it's a two a way street) FYI: The "you must implement my feature request or D will never succeed" attitude is rather common and never helpful. Not to mention that such an argument would be demonstrably false: every popular language without the feature you want has apparently succeeded despite not having said feature. I never said that. I said those were the extremes and you decided to pick the extreme that you disagreed with. I'd like you to take a moment and instead of arguing against the feature that you obviously do not like and try to argue for it. I know it will be hard and you won't be able to come up with anything, but try anyways... When one had a shit load of types in a single file, it is nice to be able to fold them. It is also nice to be able to group them in some way(hence the question) and fold the group so that large chunks of the file can be visibly reduced. If you have enough declarations in one file that they call for code folding, it may be better to move them to a separate module. Public imports and aliases allow doing this without breaking any code. Maybe, maybe not... proves nothing as it is just your preference. If you would like a way to achieve code folding without involving language constructs, I think the starting point would be your IDE/editor's D plugin vendor. Once implemented in one editor, the syntax could be implemented in others and be informally standardized. That would be fine and dandy, but that is just kicking the can down the road to someone else. You should argue on the validity of the issue itself and not on I don't think that it would make sense to introduce it into the language syntax proper. The #region syntax in C# makes sense for C# because, as already mentioned, the language vendor is also the main IDE vendor; but also because C#, like Java, requires a lot more boilerplate - writing programs in C# is much more tedious without an IDE than with. This is not the case of D, which was designed to solve problems that would otherwise require boilerplate code in the language itself. This is not logical. When the designers of C# were creating it, in no way did they say "Well, since C#'s IDE will be our IDE we will add this feature", and if they weren't they wouldn't have added it. They added it because they thought it was a useful thing in general. People don't create compilers based on what the IDE can or can not do. Generally speaking, I would recommend to simply avoid code folding altogether: https://blog.codinghorror.com/the-problem-with-code-folding/ Anecdotal. One guys view is not proof of anything. Sometimes it is not feasible to split things. The baby shouldn't be thrown out with the bath water. Obviously the designers of C# thought it was important and useful enough and anyone can hunt for a counter example of someone not liking something. If you start with the conclusion that something is wrong or bad(or even right or good) and simply simply opinions as proof, you do not prove anything. You should argue on the merits of the feature itself and not your own person opinions, desires, and wishes.
Re: scope(~this)
On Tuesday, 14 March 2017 at 05:33:28 UTC, thedeemon wrote: On Monday, 13 March 2017 at 14:28:01 UTC, Inquie wrote: On Monday, 13 March 2017 at 05:18:18 UTC, Nicholas Wilson wrote: On Sunday, 12 March 2017 at 21:38:44 UTC, Inquie wrote: Is there any easy way to create a scope for termination of the object? I have a template method that takes a type and allocates and deallocates based on that type. class bar { void foo(T)() { T x; alloc(x); scope(~this) dealloc(x); // hypothetical that wraps the statement in a lambda and deallocates in the destructor ... x must stay allocated until class instance termination(has to do with COM, can't release it in foo) } } I think the feature you're asking for is too complicated/involved for a language feature. Because it means there must be some implicit array in each object of your 'bar' class that holds some number of closures that will be executed in destructor. This affects object's memory layout and raises questions of allocating memory for those closures and since those closures will have pointers to some data (like 'x' here) it affects garbage collection. So there are a lot of things to be careful about and things that might affect other language features we haven't thought about yet. This is something quite big and something that affects a lot of code, not just a couple of classes you'll write in your one app. Probably it would be better to implement it as a library feature. Just make a base class having a method for registering such closures and calling them in destructor, and inherit from it or just embed it in your 'bar'. Complexity is in the eye of the beholder. Children think many things are complex when they are not. If a library solution could be created that is as seamless as a language solution, then I guess it would work. The downside of a library solution is uniformity of syntax and added verbosity. There is really no any arrays to keep track of or anything like that matter you stated. It requires creating a delegate to wrap the scope block and a copy of the variable to one on the heap. The GC uses arrays and that happens regardless. No reason for the compiler to create a new array. 3 steps: 1. Compiler copies local variables to heap(the "closure" part, which actually means it is not closing anything as a normal delegate would require). 2. The compiler creates a delegate. No big deal, does this in many places. 3. The compiler calls all the delegates on destruction. The only new part. But not difficult. Create a ScopeThis(...) and adds no extra overhead would be nice but I see that as being more complex. How can we determine what are variables that need to be copied to the heap? How can we hook in to the ~this? (can't have multiple ones, can we?) If you can come up with a working ScopeThis that doesn't have any more overhead than a language version, I'd be all for it, I don't know or see how it could be done. ScopeThis!("dealloc(x);") Must determine that x is a variable(hard?) and copy it to the heap(easy). Must create access to any local functions used(e.g., if dealloc is local). Then must hook in to ~this to execute the code. It would be nicer to not have to use a string but it would work easy since we could use a mixin and modify the string easily once we could parse it.
Re: how to assign tuple named Tuple easily
On Monday, 13 March 2017 at 14:15:05 UTC, Adam D. Ruppe wrote: On Monday, 13 March 2017 at 14:09:58 UTC, Inquie wrote: Yeah, so, surely though we can extract the names from the variable and then supply those like I mentioned? Yeah, we prolly could, but a simpler thing might be to just use typeof: Tuple!(int, "A")[] x; x ~= typeof(x[0])(3); x ~= tuple!x(3) ? Seems like it would probably be rather trivial with a bit of template code? Yeah, tuple could certainly adapt to do that too, but I see you would write: x ~= tuple!typeof(x)(3, 5.0); and the `tuple!` there is unnecessary: if you already use `typeof(x[0])` (you still need a `[0]` in there to get the type of the element instead of the array), then you can just construct it right there with the next set of parens. Yeah, I didn't know one could do that. Seems to be better ;) Thanks.
Re: code folding
On Monday, 13 March 2017 at 21:17:31 UTC, XavierAP wrote: On Monday, 13 March 2017 at 17:29:41 UTC, Inquie wrote: I have been using static if(true) { ... junk } Indeed #region is part of the C# specification, even if it has no effect on the code. (The specification does not say anything about folding/collapsing, just about "marking sections of code", although I guess most IDEs supporting it will follow the example of MS's reference implementation.) Short answer, D does not have this, as far as I know. I don't really think it's good substitute practice to insert meaningless static if(true)... Even if you're really used to that feature, and even if you're right that it does the job and doesn't change the generated code. Unfortunately you can't get this folding easily (I'm sure some Vim wizard would come up with something). Instead if you want to mark regions of code, that's what comments are for. You can't get the folding you want unfortunately (outside of naturally existing bracket pairs) but you can use your editor to search forward and backward in the file for whatever text, e.g. //region: foo// That's not the point. The point is that the IDE I use(VS, which is the most common IDE on windows), requires an actual block to fold. Folding is useful so it is not an irrelevant issue. Even notepad++ can fold blocks if it can determine what a block, so this isn't an "IDE" specific thing nor an "IDE" specific feature. When one had a shit load of types in a single file, it is nice to be able to fold them. It is also nice to be able to group them in some way(hence the question) and fold the group so that large chunks of the file can be visibly reduced. One can say that it is a useless feature because D doesn't have it... or one could say that D is useless because it doesn't have it. A nice balance is simply to say "It is a useful feature that has proven it's worth and it is time that D implements something like it". As D becomes more mainstream, these features will be requested. D should learn from other language/compilers just as other languages/compilers have learned from it. (it's a two a way street) If D supported such simple stuff hacks would not be required to do the simple things.
Re: code folding
On Monday, 13 March 2017 at 18:26:22 UTC, Jonathan M Davis wrote: On Monday, March 13, 2017 17:29:41 Inquie via Digitalmars-d-learn wrote: Does D have any nice way to specify a block for cold folding? I have a very large set of structs and I'd like to be able to code fold them all at once and together. I have been using static if(true) { ... junk } but the static if is uninformative since that is the only line that is shown when folded. A comment helps but still kinda ugly. C# has #regions and hopefully D has something as useful. Code-folding is an IDE thing, not a language thing. So, it's not the sort of thing that would normally be built into a language. If Microsoft did it with C#, it's only because they assumed that everyone would use Visual Studio, but I would guess that #region actually does more than just enable code folding. However, since I've done relatively little with C#, I don't know. So, how code folding works is going to depend entirely on whatever IDE or code editor you're using. If you told us which IDE you were using, maybe someone here could give you some tips, but it's going to be specific to your IDE. Normally, I think that folks just code fold based on braces if they're doing fode folding, but I don't know. I've certainly never heard of anyone adding anything to a source file just to enable code folding. - Jonathan M Davis This is wrong. It is a language feature. #region lets you specify a block of code that you can expand or collapse when using the outlining feature of the Visual Studio Code Editor. In longer code files, it is convenient to be able to collapse or hide one or more regions so that you can focus on the part of the file that you are currently working on. The following example shows how to define a region: Obviously it is useful for the IDE, but if it was not a language feature then the code would not compile(as it's not a comment). I use visual studio and if it was an IDE feature then I could insert #regions in it and it would compile. This would, of course, break anyone else code that doesn't use an IDE that supports it... hence it has to be a language feature(or some type of meta comment thing, which it is not in this case). Just because you have never heard of it doesn't mean much... it is anecdotal... before the year 0BC no one ever heard of computers... or antibiotics, or spacecraft, or transistors, or just about anything we have to day.
code folding
Does D have any nice way to specify a block for cold folding? I have a very large set of structs and I'd like to be able to code fold them all at once and together. I have been using static if(true) { ... junk } but the static if is uninformative since that is the only line that is shown when folded. A comment helps but still kinda ugly. C# has #regions and hopefully D has something as useful.
Re: how to assign tuple named Tuple easily
On Monday, 13 March 2017 at 00:23:36 UTC, ag0aep6g wrote: On 03/13/2017 01:02 AM, Inquie wrote: Ok, it doesn't work for appending though ;) [...] Tuple!(int, "A", double, "B")[] y; y ~= tuple(3, 2.5); Interestingly, this works: Tuple!(int, "A", double, "B")[] y; y.length += 1; y[$ - 1] = tuple(3, 2.5); yeah, seems more like a bug/feature issue. If the compiler can figure it out with assignment, it should also be able to figure it out with appending EXACTLY because what you wrote. Since a default append is effectively the code you wrote above there should be no difference between the two. In fact, I would have hoped that appending built in arrays would have been expanded using the pattern you specifically implemented which should then not produce the error and simplify life.
Re: scope(~this)
On Monday, 13 March 2017 at 05:18:18 UTC, Nicholas Wilson wrote: On Sunday, 12 March 2017 at 21:38:44 UTC, Inquie wrote: Is there any easy way to create a scope for termination of the object? I have a template method that takes a type and allocates and deallocates based on that type. class bar { void foo(T)() { T x; alloc(x); scope(~this) dealloc(x); // hypothetical that wraps the statement in a lambda and deallocates in the destructor ... x must stay allocated until class instance termination(has to do with COM, can't release it in foo) } } Now, x cannot be a field because T is unknown(i suppose I could use object, void*, etc, but...). If it is COM then you should use IUnknown (the COM root interface),or if you are expecting multiple calls to foo, an array of IUnknown. I think the GC will clean up completely for you in either case and call release(?) on the member(s). Also as it is COM you probably don't need to template it, just choose T to be the most recent ancestor of all (old) T's you would be expecting foo to be instantiated with (e.g. IUnknown if you expect any COM object. Sorry, but that is missing the point! First, it isn't that simple. I do not think the GC will call release as the GC has no idea of COM nor the interfaces. While it might be safe not to release them and let the OS deal with it, this is not standard. The template is to not part of COM but required to dynamically instantiate the COM interface that is not supplied(using GetIDsOfNames). So, the way it work is, I have a function that takes an interface which specifies the dynamic COM functions. Using GetIDsOfNames(since that seems to be the only way) gets the function pointers to these functions in which I build up a new object representing that interface. The problem is, One must use CoCreateInterface to create the COM object to use GetIDsOfNames(neither of which depends on the interface). But CoCreateInterface returns the interface with the Release function as a member and this function must be called later(at terminate of the overall class handling all this stuff). But since I have to create a variable with the interface to get the methods and to pass to CoCreateInstance, and eventually use it to call Release, I can't discard the variable at the end of the function. Basically the interface's lifetime must exist for the entirety of the containing object. Normally one would use the constructor and class fields to manage this, but it is impossible here because the actual interfaces are unknown at compile time(they are extracted from an idl by this class). The only thing I could do is keep an array of all these IUnknown interfaces(sorta using the above technique), since IUnknown has the Release function in it, basically using your suggestion or what I originally said is a feasible solution. But this pollutes the class name space unnecessarily(I know it is just an array, but ultimately should be unnecessary). Rather, if I could simply use a scope(~this) or some other mechanism, everything will be automatically taken care of. scope(~this) X.Release(); would realize that X, the local variable in the function, will be used and the GC will not free it just like delegates do(although it would need to be copied to the heap so future function calls won't corrupt the value when used on the stack, or, alternatively I could malloc it in the function instead). Then, on destruction, the scope is executed. X still exists. In this case, it's 1 line of code rather than about 5(a class field array, an append, and calling release on all appends in the destructor). It's very clear and very precise. It's very similar to scope(exit) for function but for classes(since classes can "exit" too). It may be better to call it scope(this) which is more clear(when the scope of the object instance is over, then "execute" what follows). I think this feature would actually be quite useful. Instead of handling many things in the destructor, we can handle them on site. e.g., any class resources that are allocated could then have a scope(this) right after allocation to deallocate them instead of having to push it in the the destructor which separates the code visually and programmatically. The same argument which is used to make scope(exit) useful, but on a higher level... Which, if we follow it, we should then also have scope(application) or something for application level scope.
Re: how to assign tuple named Tuple easily
On Monday, 13 March 2017 at 00:51:27 UTC, Adam D. Ruppe wrote: On Monday, 13 March 2017 at 00:02:12 UTC, Inquie wrote: I just figured it didn't work in general, but seems to be an issue with appending. Oh, it is because of the implicit construction thing, see my answer here to learn more: http://stackoverflow.com/a/42285015/1457000 You can construct the named tuple from a tuple() but you can't convert one to another since the names change the type. I don't think the language has a solution with this since you can't implicit construct nor overload operators on built in arrays (if it is a custom array, you can do an opOpAssign). What you could do is alias ShortName = Tuple!(int, "A"); ShortName[] a; a ~= ShortName(3); ... of course, at that point, you can also just use a regular struct too... Yeah, so, surely though we can extract the names from the variable and then supply those like I mentioned? Tuple!(int, "A")[] x; x ~= tuple!(ExtractTupleNames!x)(3); which would be equivalent to x ~= tuple!("A")(3) which, of course, works. ExtractTupleNames is a template that surely can get the names from x? Knowing it's type and that every other element of the type is a "name" it should be able to get the names then provide them to tuple? From there, we could redefine tuple to do this automatically as x ~= tuple!x(3) ? Seems like it would probably be rather trivial with a bit of template code? Ok, I did this real quick, maybe you can see how to improve it and reduce verbosity: import std.typecons, std.typetuple, std.meta, std.string, std.array, std.range; template ExtractTupleNames(T) { string fix() { enum q = (T.stringof[7..$-3]); return "alias ExtractTupleNames = AliasSeq!("~q~");"; } mixin(fix()); } void main(string[] argv) { Tuple!(int, "A", double, "B")[] x; x ~= tuple!("A", "B")(3, 5.0); x ~= tuple!(int, "A", double, "B")(3, 5.0); x ~= tuple!(ExtractTupleNames!(typeof(x)))(3, 5.0); } The goal would be to not have to specify the long string each time. e.g., the third line would be either x ~= tuple!(x)(3, 5.0); or x ~= tuple!typeof(x)(3, 5.0); It would be nice if we could pass a "run time" variable since we are only going to use it's type in the first place(avoids having to specify the typeof at the call point). I realize that we will probably have to redefine tuple but I'm ok with that as it only makes it more robust.
Re: how to assign tuple named Tuple easily
On Sunday, 12 March 2017 at 23:55:44 UTC, Adam D. Ruppe wrote: On Sunday, 12 March 2017 at 23:16:48 UTC, Inquie wrote: Tuple!(int, "A") x; x = tuple(3); fails of course umm it works for me... Ok, it doesn't work for appending though ;) Tuple!(int, "A", double, "B")[] y; y ~= tuple!("A", "B")(3, 2.5); vs Tuple!(int, "A", double, "B")[] y; y ~= tuple(3, 2.5); I just figured it didn't work in general, but seems to be an issue with appending.
Re: scope(~this)
On Sunday, 12 March 2017 at 22:13:21 UTC, Stefan Koch wrote: On Sunday, 12 March 2017 at 21:38:44 UTC, Inquie wrote: Is there any easy way to create a scope for termination of the object? [...] scope(exit) That is for the function, correct? If I release the resource at the end of the function, the COM interface will no longer be valid. It must be done when the class terminates, not the function.
scope(~this)
Is there any easy way to create a scope for termination of the object? I have a template method that takes a type and allocates and deallocates based on that type. class bar { void foo(T)() { T x; alloc(x); scope(~this) dealloc(x); // hypothetical that wraps the statement in a lambda and deallocates in the destructor ... x must stay allocated until class instance termination(has to do with COM, can't release it in foo) } } Now, x cannot be a field because T is unknown(i suppose I could use object, void*, etc, but...). I realize there are ways to work around this. I will create lambdas that release them since that is easiest. I could return x but that creates a mess. Hoping that either something like this exists or could be a feature enhancement.
Re: Accessing COM Objects
On Friday, 17 June 2016 at 08:09:42 UTC, John wrote: On Wednesday, 15 June 2016 at 21:06:01 UTC, Joerg Joergonson wrote: My thinking is that CoCreateinstance is suppose to give us a pointer to the interface so we can use it, if all this stuff is crashing does that mean the interface is invalid or not being assigned properly or is there far more to it than this? The problem is Photoshop hasn't provided an interface with methods that can be called directly. They don't exist on the interface, hence them being commented out. It's a mechanism known as late binding (everything is done at runtime rather than compile time). You need to ask the interface for the method's ID, marshal the parameters into a specific format, and then "invoke" the method using that ID. And you're not going to like it. Here's an example just to call the "Load" method: // Initialize the Photoshop class instance IDispatch psApp; auto iid = IID__Application; auto clsid = CLSID_Application; assert(SUCCEEDED(CoCreateInstance(, null, CLSCTX_ALL, , cast(void**; scope(exit) psApp.Release(); // Get the ID of the Load method auto methodName = "Load"w.ptr; auto dispId = DISPID_UNKNOWN; iid = IID_NULL; assert(SUCCEEDED(psApp.GetIDsOfNames(, , 1, 0, ))); // Put the parameters into the expected format VARIANT fileName = { vt: VARENUM.VT_BSTR, bstrVal: SysAllocString("ps.psd"w.ptr) }; scope(exit) VariantClear(); DISPPARAMS params = { rgvarg: , cArgs: 1 }; // Finally call the method assert(SUCCEEDED(psApp.Invoke(dispId, , 0, DISPATCH_METHOD, , null, null, null))); tlb2d only outputs the late-bound methods as a hint to the user so they know the names of the methods and the expected parameters (well, it saves looking them up in OleView). Had Photoshop supplied a compile-time binding, you could have just called psApp.Load(fileName) like you tried. It's possible to wrap that ugly mess above in less verbose code using native D types, and the Juno COM library mentioned earlier enabled that, but the code is quite ancient (and is part of and depends on a larger library). I've been slowly working on a more modern library. You'd be able to just write this: auto psApp = makeReference!"Photoshop.Application"(); psApp.Load("ps.psd"); But I don't know when it'll be ready. So, I was playing around with this method and was able to get things to work. Have you been able to automate this properly? Seems like if we have the interface and methods, we can create an implementation that automates the above marshaling and stuff automatically using reflection? e.g., give interface _Application : IDispatch { ... /*[id(0x4C64536C)]*/ void Load(BSTR Document); ... /*[id(0x71756974)]*/ void Quit(); ... } it shouldn't be too hard to generate a class like Generated code: class PSAppication : _Application { ... void Load(BSTR Document) { // The invoking and marshaling code automatically generated // } ... void Quit() { // The invoking and marshaling code automatically generated // } ... } ? I assume this is what you said you were working on, more or less? Would be awesome if you already had this up and running! If not, I guess I'll try to implement something like it ;/ If you haven't worked on this, I have a few questions for ya: 1. Do we have to cocreateinit every time or can we just do it once? Seems like it could be a major performance issue if we have to call it each time? 2. Marshaling the paramters seems like it could be tricky as we would have to know each case? Scanning the photoshop idl file suggests there are many different parameter and return types(strings, ints, VARIANT_BOOL, com interfaces, enum, etc). A few are easy to handle and you showed how to handle strings, but some of the others I wouldn't know how to do. 3. Does the juno code handle this well enough to copy and paste most of the labor? 4. Any pitfalls to worry about? Thanks.
Re: Accessing COM Objects
On Friday, 17 June 2016 at 08:09:42 UTC, John wrote: On Wednesday, 15 June 2016 at 21:06:01 UTC, Joerg Joergonson wrote: [...] The problem is Photoshop hasn't provided an interface with methods that can be called directly. They don't exist on the interface, hence them being commented out. It's a mechanism known as late binding (everything is done at runtime rather than compile time). You need to ask the interface for the method's ID, marshal the parameters into a specific format, and then "invoke" the method using that ID. [...] Any news on this? I'd like to do some photoshop programming in D too but it seems like a mess?!?