Re: DMD + Dynamic Library.
If it helps to know i also get in the other little window that tells me the activate compiler commands and stuff that the symbols for the functions i called undefined while the other side just said library reference not found.
Re: DMD + Dynamic Library.
On Wednesday, 15 March 2017 at 07:03:19 UTC, Damien Gibson wrote: If it helps to know i also get in the other little window that tells me the activate compiler commands and stuff that the symbols for the functions i called undefined while the other side just said library reference not found. I have an example of how to create a dll in d, read in c and d, if you want I can post the files, it's just an example to clarify, I use windows 10 32b and dmd 2.72 - yes my english is Too bad ... sorry. I speak Brazilian Portuguese.
Re: scope(~this)
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.
Re: What is PostgreSQL driver is most stable?
On Tuesday, 14 March 2017 at 16:24:31 UTC, Paolo Invernizzi wrote: On Tuesday, 14 March 2017 at 13:32:31 UTC, Suliman wrote: On Tuesday, 14 March 2017 at 13:21:39 UTC, Paolo Invernizzi wrote: On Tuesday, 14 March 2017 at 13:13:31 UTC, Suliman wrote: [...] I'm using ddb [1], a full-D implementation of the PostgreSQL protocol. Not everything it's in place, but it does its works, and the codebase is pretty simple, so it's not difficult to contribute if you need to add some feature that's missing for your use case. [1] https://github.com/pszturmaj/ddb --- Paolo Does it work fine on Linux with x64 Postgres? Yes --- Paolo We used dpq. http://code.dlang.org/packages/dpq
Re: What is PostgreSQL driver is most stable?
On Wednesday, 15 March 2017 at 08:50:11 UTC, Dsby wrote: On Tuesday, 14 March 2017 at 16:24:31 UTC, Paolo Invernizzi wrote: On Tuesday, 14 March 2017 at 13:32:31 UTC, Suliman wrote: On Tuesday, 14 March 2017 at 13:21:39 UTC, Paolo Invernizzi wrote: On Tuesday, 14 March 2017 at 13:13:31 UTC, Suliman wrote: [...] I'm using ddb [1], a full-D implementation of the PostgreSQL protocol. Not everything it's in place, but it does its works, and the codebase is pretty simple, so it's not difficult to contribute if you need to add some feature that's missing for your use case. [1] https://github.com/pszturmaj/ddb --- Paolo Does it work fine on Linux with x64 Postgres? Yes --- Paolo We used dpq. http://code.dlang.org/packages/dpq I'm curious: ddb does not support yet arbitrary precision numbers [1], does dpq support them? Thanks, Paolo [1] https://www.postgresql.org/docs/9.5/static/datatype-numeric.html#DATATYPE-NUMERIC-DECIMAL
Re: What is PostgreSQL driver is most stable?
On Tuesday, 14 March 2017 at 13:36:04 UTC, Daniel Kozak wrote: Dne 14.3.2017 v 14:21 Daniel Kozak napsal(a): Dne 14.3.2017 v 14:13 Suliman via Digitalmars-d-learn napsal(a): I need to develop App that should work on Linux and Windows. It need PostgreSQL driver. I tried Vadim's ddbc for PostgreSQL but it's fail on x64 version of PostgreSQL and possible will not on x64 PG on Linux (I can't test it now). Could anybody advice me good driver without problems? I seen some pg-wrapers on code.dlang.ru, but do not have test all of them. ddbc works fine for me s/ddbc/ddb/ Am I rightn understand that DBRow! is allow to get only single row, and if I need array of rows I need to use foreach? If I am wrong could you provide an example please.
Re: scope(~this)
On Tuesday, 14 March 2017 at 14:35:11 UTC, Inquie wrote: On Tuesday, 14 March 2017 at 05:33:28 UTC, thedeemon wrote: [...] 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. [...] 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. I was not sure to answer yesterday because the conversation turned on the COM thing. I wanted to say that you can use a mixin template because they can introduce destructors that are called automatically with the aggregate destrcutor mixin template Foo(T) { T x; void foo() { alloc(x); } ~this() // auto-called by the target aggregate { dealloc(x); } } class bar { mixin Foo!Stuff; }
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.
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: 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: What is PostgreSQL driver is most stable?
On Wednesday, 15 March 2017 at 09:18:16 UTC, Suliman wrote: On Tuesday, 14 March 2017 at 13:36:04 UTC, Daniel Kozak wrote: Dne 14.3.2017 v 14:21 Daniel Kozak napsal(a): Dne 14.3.2017 v 14:13 Suliman via Digitalmars-d-learn napsal(a): I need to develop App that should work on Linux and Windows. It need PostgreSQL driver. I tried Vadim's ddbc for PostgreSQL but it's fail on x64 version of PostgreSQL and possible will not on x64 PG on Linux (I can't test it now). Could anybody advice me good driver without problems? I seen some pg-wrapers on code.dlang.ru, but do not have test all of them. ddbc works fine for me s/ddbc/ddb/ Am I rightn understand that DBRow! is allow to get only single row, and if I need array of rows I need to use foreach? If I am wrong could you provide an example please. The retrieval of records is done via the execution of a (prepared) sql query, that returns a range object (PGResultSet), and the element of that range is the DBRow, in one of its form. So, basically, the elements are retrieved on demand while you popFront that range, leveraging what the PostgreSQL stream protocol provide. --- Paolo
[vibe.d] How to create authentication system via REST interface?
I'm trying to understand how to create some json-rest api that would return data (in json format) related to that specific logged in user. I see the documentation covers these but I'm totally new to vibe.d so can't quite figure out putting these two things together and make them work. Some easy to follow sample would be incredibly helpful, though any help is appreciated.
Re: [vibe.d] How to create authentication system via REST interface?
On Wednesday, 15 March 2017 at 13:24:07 UTC, NX wrote: I'm trying to understand how to create some json-rest api that would return data (in json format) related to that specific logged in user. I see the documentation covers these but I'm totally new to vibe.d so can't quite figure out putting these two things together and make them work. Some easy to follow sample would be incredibly helpful, though any help is appreciated. You need to look at JWT. There is few good video on youtube about it and packed on code.dlang.org I did not seen ready to use examples :( If will need implement client side look at Vue.js it is very best of existen JS frameworks.
Re: What is PostgreSQL driver is most stable?
The retrieval of records is done via the execution of a (prepared) sql query, that returns a range object (PGResultSet), and the element of that range is the DBRow, in one of its form. So, basically, the elements are retrieved on demand while you popFront that range, leveraging what the PostgreSQL stream protocol provide. --- Paolo Could you give an example when it's better to use DBRow and where to get data in structure?
Safe COM Variant
Is there a safe com variant? We need to call To use a variant properly we must 1. CoTaskMemAlloc 2. VariantInit 3. VariantClear 4. CoTaskMemFree With 1/4 COM calls randomly crash/fail. (which is what lead me to use them) 2/3 are specified by COM spec. I guess D doesn't have a SafeVariant type. What would be the best way to go about it? Would I need to wrap it in a class? class SafeVariant { VARIANT* v; alias v this; this() { v = cast(VARIANT*)CoTaskMemAlloc(VARIANT.sizeof); VariantInit(v); } ~this() { auto res = VariantClear(v); CoTaskMemFree(v); } } The main thing above is that it would be nice to alias v this to the struct instead of the ptr of the struct: e.g., alias v* this, which, of course, doesn't work. So the above is really a SafeVariantPtr, which is only half as useful. struct VARIANT { union { struct { VARTYPE vt; WORD wReserved1; WORD wReserved2; WORD wReserved3; union { int lVal; LONGLONG llVal; ubyte bVal; short iVal; float fltVal; double dblVal; VARIANT_BOOL boolVal; SCODE scode; CY cyVal; DATE date; BSTR bstrVal; IUnknown punkVal; IDispatch pdispVal; SAFEARRAY* parray; ubyte* pbVal; short* piVal; int* plVal; float* pfltVal; double* pdblVal; VARIANT_BOOL* pboolVal; _VARIANT_BOOL* pbool; SCODE* pscode; CY* pcyVal; DATE* pdate; BSTR* pbstrVal; IUnknown* ppunkVal; IDispatch* ppdispVal; SAFEARRAY** pparray; VARIANT* pvarVal; void* byref; CHAR cVal; USHORT uiVal; ULONG ulVal; ULONGLONG ullVal; INT intVal; UINT uintVal; DECIMAL* pdecVal; CHAR* pcVal; USHORT* puiVal; ULONG* pulVal; INT* pintVal; UINT* puintVal; struct { PVOID pvRecord; IRecordInfo pRecInfo; } } } DECIMAL decVal; } }
Re: [vibe.d] How to create authentication system via REST interface?
On Wednesday, 15 March 2017 at 13:24:07 UTC, NX wrote: I'm trying to understand how to create some json-rest api that would return data (in json format) related to that specific logged in user. I see the documentation covers these but I'm totally new to vibe.d so can't quite figure out putting these two things together and make them work. Some easy to follow sample would be incredibly helpful, though any help is appreciated. The "examples" folder in the github repo has demo on rest api. Along with the vibe.d api reference, you should get a badic service working. Authentication can be tricky but you can append a query with some api key for each request to authenticate.
Re: scope(~this)
On Wednesday, 15 March 2017 at 12:56:10 UTC, Inquie wrote: If it is trivial, can you write up a quick solution. I don't see how to accomplish it easily. Here it is, source and output: https://dpaste.dzfl.pl/bbf162529c6c
Re: strange CFTE issue
On 03/15/2017 02:00 PM, Inquie wrote: 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. The enum array is similar to an AliasSeq in that you can them both in contexts that require compile-time constants. But that doesn't mean that every context in which you put them gets evaluated at compile time. Different example: If you write `if (true)` that's a run-time conditional even though `true` is a constant. By the language rules, the check is done at run time. It may of course be optimized out, but the language doesn't care about that. There's also a `static if`. If you write `static if (true)`, that check is done at compile time, by the language rules. That means you can only put compile-time constants as the condition of a `static if`. In other words, the `static if` forces compile-time evaluation of its condition. This "forcing of compile-time evaluation" is how things work. Compile-time evaluation is only attempted when it's forced by the context. It's not attempted when run-time evaluation is possible. `enum`, `mixin`, and `static if` force compile-time evaluation. With `foreach` it's only forced when looping over an AliasSeq, because you can't do that at run-time. As for why this is so: Consider that a run-time loop can take a long time (hours, days, ...) even if it's over a constant array. It's expected that the generated program runs for a long time. It would be surprising if the compilation were to take that long time, just because the compiler saw that it's possible. By the way, I'd love to see an actual `static foreach`, with the `static` keyword. I'd have it work similar to `static if` and force compile-time semantics. Then (slowly) deprecate using plain `foreach` on AliasSeqs. Would make D code clearer, in my opinion. But this might have non-obvious issues. I haven't thought too hard about it. [...] 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. It would make a difference with the hypothetical `static foreach`, which would accept the first one but reject the second one. With plain `foreach` it doesn't matter. Ignoring the body, the loop can be done at run-time in both versions, so that's what the compiler tries to do. Compile-time evaluation must be requested by the programmer. The compiler doesn't attempt it eagerly. Essentially what you are saying is that if I were to have Methods! return an AliasSeq then it would work. Yup. It is a CTFE that returns an array. You might use the term "CTFE" correctly here, but you also might use it incorrectly. Just to clarify the term, if `Methods` looks this: template Methods(T) { enum Methods = /* ... whatever ... */; } or like this: enum Methods(T) = /* ... whatever ... */; then it's not a function, but a template. CTFE may happen in the "whatever" part, but `Methods` itself does not go through CTFE as it's not a function. But if `Methods` looks like this: string[] Methods(T)() { /* ... whatever ... */ } then it is a function and does go through CTFE. 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? Phobos has it: std.meta.aliasSeqOf "converts an input range [...] to an alias sequence." [1] Applied to your code: enum X = ["int foo;", "double bar;"]; foreach(x; aliasSeqOf!X) { mixin(x); /* works */ } 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. Yeah, no. A compile-time constant being used doesn't mean anything. It's the context in which it is used that forces compile-time evaluation.
Re: strange CFTE issue
Phobos has it: std.meta.aliasSeqOf "converts an input range [...] to an alias sequence." [1] Woops, forgot to give the URL for that "[1]". Here it is: http://dlang.org/phobos/std_meta.html#aliasSeqOf
Re: scope(~this)
On 03/15/2017 03:23 AM, Basile B. wrote: > you can use a mixin template because > they can introduce destructors that are called automatically with the > aggregate destrcutor > > mixin template Foo(T) > { > T x; > void foo() > { > alloc(x); > } > ~this() // auto-called by the target aggregate > { > dealloc(x); > } > } > > class bar > { > mixin Foo!Stuff; > } Wow! Is this specified anywhere or have you come across this by chance? :) Ali
Re: [vibe.d] How to create authentication system via REST interface?
On 03/15/2017 07:06 AM, Suliman wrote: > You need to look at JWT. WekaIO uses jwtd, with minor improvements on it (improved error handling and code coverage): https://github.com/weka-io/jwtd Ali
Re: scope(~this)
On Wed, Mar 15, 2017 at 12:34:32PM -0700, Ali Çehreli via Digitalmars-d-learn wrote: > On 03/15/2017 03:23 AM, Basile B. wrote: > > > you can use a mixin template because they can introduce destructors > > that are called automatically with the aggregate destrcutor > > > > mixin template Foo(T) > > { > > T x; > > void foo() > > { > > alloc(x); > > } > > ~this() // auto-called by the target aggregate > > { > > dealloc(x); > > } > > } > > > > class bar > > { > > mixin Foo!Stuff; > > } > > Wow! Is this specified anywhere or have you come across this by chance? :) [...] Whoa. This is a really bizarre unknown (AFAICT) bit of the language (or at least, dmd's implementation thereof). I just did a bit of local testing, and found that while dmd happily chains mixin template dtors into an aggregate, it behaves erratically if the mixin template declares this(). It works if there's only a single this() declared either in the class itself, or a single mixin template. But if the class declares this() and the (single) mixin template also declares this(), then the mixin template's version is ignored and the class-declared this() is run upon construction. However, if there are two mixin templates both declaring this(), the compiler dies with an ICE. :-D T -- It is widely believed that reinventing the wheel is a waste of time; but I disagree: without wheel reinventers, we would be still be stuck with wooden horse-cart wheels.
Re: scope(~this)
On Wednesday, 15 March 2017 at 20:36:27 UTC, H. S. Teoh wrote: But if the class declares this() and the (single) mixin template also declares this(), then the mixin template's version is ignored and the class-declared this() is run upon construction. That's normal mixin template behavior: if the name of a mixed in object already exists in the instantiation scope, the existing one is preferred. This allows you to "override" mixin functions and is quite useful. You can also bring in the others via alias. See my tip here for a related factoid: http://arsdnet.net/this-week-in-d/2016-feb-07.html That's what I *thought* was going on with the destructor too... but I confirmed both do in fact exist and seem to be merged by the compiler. I knew it did that with static dtors, but the spec says "a class can have only one destructor and it is always virtual" so idk what's going on. Bug, perhaps, but I now am inclined to believe it is a hidden feature. Important note though: such behavior is already possible. Struct dtors of members are called when the class dtor runs too... However, if there are two mixin templates both declaring this(), the compiler dies with an ICE. :-D eek.
Re: DMD + Dynamic Library.
I have an example of how to create a dll in d, read in c and d, if you want I can post the files, it's just an example to clarify, I use windows 10 32b and dmd 2.72 - yes my english is Too bad ... sorry. I speak Brazilian Portuguese. I would love that :D And no dont worry your english was perfectly fine!
Re: scope(~this)
On Wed, Mar 15, 2017 at 08:55:34PM +, Adam D. Ruppe via Digitalmars-d-learn wrote: [...] > > However, if there are two mixin templates both declaring > > this(), the compiler dies with an ICE. :-D > > eek. Filed a bug for it: https://issues.dlang.org/show_bug.cgi?id=17259 T -- Meat: euphemism for dead animal. -- Flora
real simple manifest constant question probably regret asking...
One of my D books says: "an enum declared without any braces is called a manifest constant." The example shows, enum string author = "Mike Parker"; Is this equivalent to const string author = "Mike Parker"; or immutable string author = "Mike Parker"; I guess what I'm asking is does enum give you some advantages over say non-enum constants? Thanks.
Re: real simple manifest constant question probably regret asking...
On 16/03/2017 4:27 PM, WhatMeForget wrote: One of my D books says: "an enum declared without any braces is called a manifest constant." The example shows, enum string author = "Mike Parker"; Is this equivalent to const string author = "Mike Parker"; or immutable string author = "Mike Parker"; I guess what I'm asking is does enum give you some advantages over say non-enum constants? Thanks. No. An enum is an enum, that variation of the syntax just has a special name that's all. Keep in mind the typed aspect doesn't have an affect other than forcing the value to it. enum Foo : string { Author = "Mike Parker" }
Re: real simple manifest constant question probably regret asking...
WhatMeForget wrote: One of my D books says: "an enum declared without any braces is called a manifest constant." The example shows, enum string author = "Mike Parker"; Is this equivalent to const string author = "Mike Parker"; or immutable string author = "Mike Parker"; I guess what I'm asking is does enum give you some advantages over say non-enum constants? Thanks. "enum constants" are so-called "inline constants". i'll try to explain it. imagine that you have a constant: int[2] carr = [ 42, 69 ]; this array will be placed in read-only data segment, and each time you refer to it, the same array will be used. i.e. assert(carr.ptr is carr.ptr); will pass. now let's try enum int[2] carr = [ 42, 69 ]; this time, assert(carr.ptr is carr.ptr); will fail. why? 'cause when you are using "enum constant", it will be created in-place. i.e. in the second case you'll get *two* arrays with identical content. wether you want that effect or not is completely up to you. usually, it is better to declare numeric constants as enums (so they won't take any storage at all), and array constants as `immutable`s. as for strings, it depends of your system, compiler and linker. usually, linkers "deduplicating" strings (i.e. merging identical strings into one), but if your string is heavily used, it may still be better to declare it as non-enum.
Re: real simple manifest constant question probably regret asking...
On 03/15/2017 08:27 PM, WhatMeForget wrote: > > One of my D books says: "an enum declared without any braces is called a > manifest constant." The example shows, > > enum string author = "Mike Parker"; > > Is this equivalent to > const string author = "Mike Parker"; > or > immutable string author = "Mike Parker"; > > I guess what I'm asking is does enum give you some advantages over say > non-enum constants? The guideline should be, "prefer enum except when the type is an array except if it's a string." :) You can think of enum as a text replacement similar to C macros. Whenever you see 'author' in code, it would be as if it was replaced with its value: writeln(author); writeln("Mike Parker");// Same as above The limitation is that just like you cannot take the address of e.g. 42, you can't take the address of an enum: // All lines below are compilation errors: "not an lvalue" writeln(&42); writeln(&"Mike Parker"); writeln(&author); const static and immutable have the advantage of being initialized at runtime. This one reads the name from a file: import std.stdio; immutable string author; string makeAuthor() { import std.file; auto content = read("author_name_file"); return cast(string)content; } shared static this() { author = makeAuthor(); } void main() { writeln(author); } Ali