Re: Can't make inout work.
On 17/03/2019 18:34, Kagamin via Digitalmars-d-learn wrote: On Saturday, 16 March 2019 at 14:57:35 UTC, Paul Backus wrote: This code fails to compile if you change `auto s2` to `const s2`--in other words, it has the same problem as the original example. Maybe there's not much need for qualifiers anyway. This is what I meant as well. diniz
Re: Block statements and memory management
On 16/03/2019 11:19, Dennis via Digitalmars-d-learn wrote: On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote: Does anyone know if when I create a variable inside a scope as in {int a = 10;} it disappears complete from the memory when the scope finishes? Or does it remain in some part of the memory? I am thinking of using scopes to make optimized programs that consume less memory. In general, you want variables to have no larger scope than needed, so in large functions reducing the scope may be useful. When it comes to efficiency however, doing that is neither necessary nor sufficient for the compiler to re-use registers / stack space. I looked at the assembly output of DMD for this: ``` void func(int a); void main() { { int a = 2; func(a); } { int b = 3; func(b); } } ``` Without optimizations (the -O flag), it stores a and b on different places in the stack. With optimizations, the values of a and b (2 and 3) are simply loaded in the EDI register before the call. Removing the braces doesn't change anything about that. The compiler does live variable analysis [1] as well as data-flow analysis [2] to figure out that it's only needed to load the values 2 and 3 just before the function call. This is just a trivial example, but the same applies to larger functions. In any case, for better memory efficiency I'd consider looking at reducing dynamic allocations such as new or malloc. Memory on the stack is basically free compared to that, so even if adding lots of braces to your code reduces stack memory, chances are it's a low leverage point. [1] https://en.wikipedia.org/wiki/Live_variable_analysis [2] https://en.wikipedia.org/wiki/Data-flow_analysis Just to add a bit on what has been said: * Register allocation (see wikipedia) is a well-researched area. * By coding that way, you force the compiler to optimise *a certain way* which may prevent it to perform other, more relevant optimisations. * You cannot beat the knowledge in that domain, it is simply too big and complex, just be confident. diniz
Re: Can't make inout work.
PS: the chapter of Ali Çehreli's book on func args is great: http://ddili.org/ders/d.en/function_parameters.html diniz
Re: Can't make inout work.
On 16/03/2019 04:49, Paul Backus via Digitalmars-d-learn wrote: On Friday, 15 March 2019 at 23:57:15 UTC, aliak wrote: Anyone knows how to make this work? You need an explicit `inout` on the return value of `make`: auto ref make(T)(inout auto ref T value) { return inout(S!T)(value); } I think (but may be wrong) that you don't need inout here, since a plain 'ref' will (and does) work. This is accepted by me (I added vars to make the code clearer to myself): struct S(T) { T value = T.init; } auto ref make(T)(ref T value) { return S!T(value); } auto ref f(T)(ref S!T s) { return make(s.value); } void main() { class C {} C c ; auto s1 = S!C(c) ; auto s2 = make!C(c) ; auto s3 = f!C(s2) ; }
Re: local class instance (at module-level)
On 15/03/2019 00:45, ag0aep6g via Digitalmars-d-learn wrote: On 14.03.19 20:43, Jacob Carlborg wrote: class C { uint i ; this (uint i) { this.i = i ; } this (uint i) shared { this.i = i ; } this (uint i) immutable { this.i = i ; } } __gshared c0 = new C(0); shared c1 = new shared C(1); immutable c2 = new immutable C(2); You only need one of the constructors depending on if you want a __gshared, shared or immutable variable. If you make it `pure`, you can use the same constructor in all cases: class C { uint i ; this (uint i) pure { this.i = i ; } } __gshared c0 = new C(0); shared c1 = new shared C(1); immutable c2 = new immutable C(2); all right, thank you!
Re: bug in doc?
On 14/03/2019 15:52, H. S. Teoh via Digitalmars-d-learn wrote: On Thu, Mar 14, 2019 at 03:22:52PM +0100, spir via Digitalmars-d-learn wrote: https://dlang.org/spec/hash-map.html#static_initialization: immutable long[string] aa = [ "foo": 5, "bar": 10, "baz": 2000 ]; ==> Error: non-constant expression `["foo":5L, "bar":10L, "baz":2000L]` Also: I don't understand the error message: * What is non-constant in the *expression*? * And why should it be constant at all? (Removing "immutable" does not help...) [...] It's a well-known limitation. The workaround is: immutable long[string] aa; static this() { aa = [ "foo" : 5, ... ]; } All right! No language has to be perfect... (I'm joking). But the doc (the language ref for the matter) should definitely say what you just explained above, shouldn't they? I actually think clearly stating limitations is a +++. (Like an industry company that does not make perfect product but has great client support.) diniz
Re: local class instance (at module-level)
On 14/03/2019 12:16, H. S. Teoh via Digitalmars-d-learn wrote: On Thu, Mar 14, 2019 at 12:05:22PM +0100, spir via Digitalmars-d-learn wrote: I desperately try to declare/define/initialise a simple class instance at module-level. This is a special (conceptually static and immutable) instance used as a "marker", that just should exist and be accessible by methods of this class and/or other classes defined in the same module. (Thus I don't care if TLS.) I use it as a remplacement for null, to avoid semantic confusion and unhelpful segfaults in case of bug. Does this work? class C { ... } immutable C c0; static this() { c0 = new C(...); } T Oh yes, that was it ! Thank you very much. diniz
bug in doc?
https://dlang.org/spec/hash-map.html#static_initialization: immutable long[string] aa = [ "foo": 5, "bar": 10, "baz": 2000 ]; ==> Error: non-constant expression `["foo":5L, "bar":10L, "baz":2000L]` Also: I don't understand the error message: * What is non-constant in the *expression*? * And why should it be constant at all? (Removing "immutable" does not help...) diniz
local class instance (at module-level)
I desperately try to declare/define/initialise a simple class instance at module-level. This is a special (conceptually static and immutable) instance used as a "marker", that just should exist and be accessible by methods of this class and/or other classes defined in the same module. (Thus I don't care if TLS.) I use it as a remplacement for null, to avoid semantic confusion and unhelpful segfaults in case of bug. I have tried a number of options and never manage to do it, including: * [C/auto/static immutable c0] = new C(0) ; * C c0 ; c0.i = 0 ; * defining a static this() * more... The most confusing error is: Error: variable `_base.c0` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead. I also could not find any information --for a while, repeatedly, since I can go on developing in the meantime, using null instead. I'm bluffed and confused, since there is nothing weird in that, is there? (the compiler can just allocate it in static mem and take the address) Reduced test case: === class C { uint i ; this (uint i) { this.i = i ; } } // error auto c0 = new C(0) ; void main () { // ok auto c0 = new C(0) ; } === I would enjoy an explanation (or a pointer to) in addition to a solution. Thank you, diniz PS: I take the opportnity to ask if I can count on the compiler to intern literal strings (which my code may use in several places, including loops), esp. "", or should I declare and use (for instance): static immutable s0 = "" ;
Re: Why does D language do not support BigDecimal type?
On 12/03/2019 10:31, Boqsc via Digitalmars-d-learn wrote: Please attach quick working examples for every sentence you write or it's just a waste of time. People want to see the results and direct actions first before anything else, it's more efficient communication. We are in the subforum of Dlang learn, after all. Do not write "For Example". Then you may help people helping you by giving examples of your own use cases, first. I'm interested in writing a simple game prototype and I imagine that I would like to include some item parts in decimal. (100.00) To keep everything simple I would like to make my code as clean and simple as possible. From this single example, you don't need "fractal" (decimal or binary) numbers at all, just plain ints. Look up "fixed point arithmetics" on wikipedia, the article is rather good. It's easy and clean in comparison, at least if you only need simple operations. (That's how, by the way, monetary/financial software is or at least used to be implemented.) diniz
Re: Distinguish float and integer types from string
On 09/03/2019 19:11, Jacob Shtokolov via Digitalmars-d-learn wrote: The thing is that in PHP, for example, I would do The thing is php needs to be able to "lexify" raw input data at runtime, while in D this is done at compile-time. The ompiler has the lexer to do that. But I agree that, for user input, it would be cool to have such a feature available. However, this would quickly become complex because of (the reciprocal of) localisation, or even personalisation. Eg I like to write decimals like: -1'234'457,098 diniz
Re: this is null
On 09/03/2019 21:10, ANtlord via Digitalmars-d-learn wrote: On Saturday, 9 March 2019 at 20:04:53 UTC, Paul Backus wrote: You can end up with a null `this` reference if you dereference a null pointer to a struct and then call a method on the result. For example: I can but my reference is not null before calling. Take a look at the line of code [0]. There is a check before the line. https://github.com/ANtlord/deadmemory/blob/master/src/deadmemory/mem.d#L20 [0] There is a typo in this instruction: T* ptr = this.list.getFisrtFreeOrAdd(memViewLen).getPtr!T(); ^^ rs (may this explain your null? the compiler should complain) diniz
Re: 2 class issues -- PS
from [https://dlang.org/spec/attribute.html#abstract] : --- abstract Attribute An abstract member function must be overridden by a derived class. Only virtual member functions may be declared abstract; non-virtual member functions and free-standing functions cannot be declared abstract. Classes become abstract if any of its virtual member functions are declared abstract or if they are defined within an abstract attribute. Note that an abstract class may also contain non-virtual member functions. Classes defined within an abstract attribute or with abstract member functions cannot be instantiated directly. They can only be instantiated as a base class of another, non-abstract, class. Member functions declared as abstract can still have function bodies. This is so that even though they must be overridden, they can still provide ‘base class functionality’, e.g. through super.foo() in a derived class. Note that the class is still abstract and cannot be instantiated directly. --- Is there thus another way to enforce overriding of given methods? I wish to instantiate superclasses for special instances, as shown in previous mail. It is not a big deal (I can live without this enforcement, and my clients as well since if they wish to implement their own subclasses, they will have to override) but I still wish to know that for further cases. Thank you, diniz
2 class issues
Hello, First, I am not very experimented with the combination of static lang (alloc & typing) and OO (class-based). I'm implementing a library for lexical analysis (lexing), with 2 minor issues: -1- How to enforce that subclasses implement given methods without using "abstract", which seems to make the whole class abstract? (no info found in doc, actually, the page on classes [1] does not seem to even mention abstract classes) -2- How to have "constant" (predefined) class instances at the module-level? The compiler requires a "static this ()". What does this actually mean (for a constructor)? What are the consequences, for either my code or client code? (The doc on the topic [2] is rather obscure for me, and I could not find better elsewhere.) I'm also bluffed by "Static constructors have empty parameter lists." Does this mean I should manually fill the fields? (not a big deal, but why???) This may give: // Predefined pseudo-pattern "End-of-Text": auto EoT = new Pattern() ; // ??? EoT.name = "EoT" ; // Unique lexeme "end-of-text": auto eot = new Lexeme() ; // ??? eot.patname = "EoT" ; eot.slice = null ; eot.index = uint.max ; Then, why have a constructor at all? This would also prevent me from making classes immutable, while conceptually all are immutable... (no reason for a pattern or a lexeme to change) Thank you, diniz [1] https://dlang.org/spec/class.html [2] https://dlang.org/spec/class.html#static-constructor
Re: Beginner ?. Why does D suggest to learn java
On 17/10/14 07:38, maarten van damme via Digitalmars-d-learn wrote: While d can be complex, there's nothing preventing you from starting out simple and not using all features at first. I don't understand why it's not suitable for a beginner if you use this approach... For some reasons, in my view: A beginner has to learn programming in addition to a first lang. A beginner has to learn a first lang in addition to programming. We learn languages by understanding valid, meaningful input, ie here reading code. All static langs introduce tons of complication only due to their staticity. D is rather big complex, in the field of static langs. Most code will use more than a theoretical minimal set of features. And this minimal set is far more in size, difficulty, complication than in langs partly designed for ease of learning (Lua, Python, Scheme...). Even plain C is far more difficult than say, Lua. d
Re: Beginner ?. Why does D suggest to learn java
On 17/10/14 03:05, ketmar via Digitalmars-d-learn wrote: On Fri, 17 Oct 2014 00:52:14 + MachineCode via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: I don't understand. If at least it were C but java? why not D itself? C is *awful* as beginner's language. never ever let people start with C if you don't hate 'em. as for D... current version of D can be used, but with some precautions. we now have excellent book by Ali. (it's great, really! i believe that it must be featured on the front dlang.org page!) but java has alot more books and tutorials. not that D is bad for beginners, it's just has a smaller userbase. and all that things with classes are reference types and structs are not, empty array is not empty array but is empty array and so on D may be confusing a little. it's good to have some CS background to understood that things. What you say here applies, I guess, to many other points. I applaud Ali for writing a tutorial like his but... Check it (just the first pages is enough) for literally the dozens of notions one must know and master for being able to understand, not only the features of D introduced, but even the tutorial itself. If I am not a programmer, and one who knows other static langs, and better of the mainstream procedural paradigm, if not D itself, then I do not understand more than few isolated words here and there. We are blind to the huge pile of concepts we know, I guess, because we know them, thus take them for granted... d
Re: String created from buffer has wrong length and strip() result is incorrect
On 17/10/14 09:29, thedeemon via Digitalmars-d-learn wrote: On Friday, 17 October 2014 at 06:29:24 UTC, Lucas Burson wrote: // This is where things breaks { ubyte[] buff = new ubyte[16]; buff[0..ATA_STR.length] = cast(ubyte[])(ATA_STR); // read the string back from the buffer, stripping whitespace string stringFromBuffer = strip(cast(string)(buff[0..16])); // this shows strip() doesn't remove all whitespace writefln(StrFromBuff is '%s'; length %d, stringFromBuffer, stringFromBuffer.length); // !! FAILS. stringFromBuffer is length 15, not 3. assert(stringFromBuffer.length == strip(ATA_STR).length); Unlike C, strings in D are not zero-terminated by default, they are just arrays, i.e. a pair of pointer and size. You create an array of 16 bytes and cast it to string, now you have a 16-chars string. You fill first few chars with data from ATA_STR but the rest 10 bytes of the array are still part of the string, not initialized with data, so having zeroes. Since this tail of zeroes is not whitespace (tabs or spaces etc.) 'strip' doesn't remove it. Side-note: since your string has those zeroes at the end, strip only removes the space at start (thus, final size=15), instead of at both ends. d
Re: How to check i
On 16/10/14 20:46, Uranuz via Digitalmars-d-learn wrote: I have some string *str* of unicode characters. The question is how to check if I have valid unicode code point starting at code unit *index*? [...] You cannot do that without decoding. Cheking whether utf-x is valid and decoding are the very same process. IIRC, D has a validation func which is more or less just an alias for the decoding func ;-). Moreover, you also need to distinguish word-character code points from others (punctuation, spacing, etc) which requires unicode code points (Unicode the consortium provide tables for such tasks). Thus, I would recommand you to just abandon the illusion of working at the level of code units for such tasks, and simply operate on strings of code points. (Why do you think D has them builtin?) denis
use case for alias this
Hello, For what it's worth, I have finally found one use case for the famous alias this trick for structs: struct ScienceConstant { float value; string name; alias value this; string toString () { return this.name; } } unittest { auto PI = ScienceConstant(3.14, pi); writefln(%s/3 = %s, PI, PI/3); // -- pi/3 = 1.04667 } For people who don't know it: the point is that alias this implicitely delegates messages (here requests for arithmetic operations) to the actual element (here value) on which they should apply, that happens to be embedded in a struct object. Or rather: that's how I conceive this feature. Denis -- _ vita es estrany spir.wikidot.com
Re: A use case for fromStringz
On 04/16/2011 06:55 AM, Andrej Mitrovic wrote: I wonder.. in all these years.. have they ever thought about using a convention in C where the length is embedded as a 32/64bit value at the pointed location of a pointer, followed by the array contents? Sometimes called Pascal strings (actually, IIRC, the length is at the address /before/ the one pointed by the pointer). One of the important diffs between C Pascal from the practical pov. Actually, it's the same diff as C arrays vs true arrays like D's. Denis -- _ vita es estrany spir.wikidot.com
Re: Else clauses for loops
On 04/13/2011 06:48 PM, bearophile wrote: Bernard Helyer: You could wrap the loop in an if clause: if (condition) while (true) { // ... } else { // ... } This is the semantics of the else clause of Python for (and while) loops: bool broken = false; for (...) { if (...) { broken = true; break; } } if (!broken) { ... } I agree with BCS in the bug 2304, I'd like something more semantically descriptive instead of just an else. True. Python tends to overload its keywords, which leads to weird expression. Also weird, again using then: try: n = 1 + 1 except Exception, e: print (*error*) else: print (n) actually means try: n = 1 + 1 then: print (n) except Exception, e: print (*error*) Denis -- _ vita es estrany spir.wikidot.com
Re: So why doesn't popFront return an element?
On 04/14/2011 01:00 AM, Andrej Mitrovic wrote: I'm trying to understand the design of ranges. Why does popFront only set the front() property to return the next element in the range? Why not return the element in the call to popFront right away? For example code like this (which doesn't work since popFront doesn't return): void main() { int[] a = [1, 2]; auto b = a.popFront; assert(a == [2]); assert(b == 1); } Isn't it wasteful to have to call both popFront() and front() to simultaneously remove an element from a range and return it? I mean it's an extra function call, right? I like to have three members (even if not quite necessary, this cleanly separates notions). Why I don't understand is why empty and front are methods, not simple data members. Denis -- _ vita es estrany spir.wikidot.com
un-requested compiler optimisations
On 04/14/2011 06:57 PM, Andrej Mitrovic wrote: This leads me to another question I've always wanted to ask. A call such as: auto b=map!foo(map!bar1(map!bar2(a)); This constructs a lazy range. What I'm wondering is if there are any performance issues when constructing long chains of ranges like that, since this basically routes one function to the next, which routes to the next, etc. E.g: auto a = [1, 2]; auto b = retro(a); auto c = retro(b); auto d = retro(c); Under the surface, I assume calling d.front would mean the following calls: d.front()-c.back()-b.front()-a.back() Or another example: auto b = retro(retro(a)); Can the compiler optimize the second case and convert b.front to just do one field access? If it does optimise, then it is definitely a compiler bug. Since you *explicitely* ask for a double reverse, it *must* just do it. Suppressing them is here just breaking the language's semantics! It is not the compiler's role to interpret, meaning to guess your reasons for requesting that; and the compiler is certainly not in position to do it. Even less to *judge* that request as stupid, and thus ignore it (unlike in the army ;-). You are the master, asking for stupid computations is both your right and your problem ;-) Anyway, there are probably perfectly valid reasons to do a double reverse; at least (0) exploring (1) teaching (2) benchmarking. In a similar vein: { long n; static N = 10_000; foreach (_ ; 0..N) { n = factorial(9); } } Should the compiler optimise by computing n only once? (even possibly at compile-time) Then, what if I'm doing that in purpose? (be it stupid or not) Denis -- _ vita es estrany spir.wikidot.com
Re: un-requested compiler optimisations
On 04/14/2011 08:33 PM, Steven Schveighoffer wrote: If it does optimise, then it is definitely a compiler bug. Since you *explicitely* ask for a double reverse, it *must* just do it. Suppressing them is here just breaking the language's semantics! I feel like people aren't looking at my post :) Sorry, I wrote this reply before reading yours. denis -- _ vita es estrany spir.wikidot.com
Re: Range violation error in the code
On 04/12/2011 02:20 PM, Ishan Thilina wrote: I can compile the following code. But when I run the program it gives me a core.exception.RangeError@untitled(34): Range violation error. The code is as follows. import std.stdio; int main(char[][] args) { struct Node{ int _value; Node* _next,_prev,_up,_down; } Node*[] pointers; int i=0; auto n=new Node; pointers[i]=n; return 0; } Here's the error. core.exception.RangeError@untitled(34): Range violation [...] As it seems the problem is with the line pointers[i]=n. What's wrong here? :s There is no node in pointers as of now, thus pointers[i] can only be a range violation, whatever i (even 0, which should point to the *first* node). pointers[i]=n; would *change* the current element number i. To put a *new* node into pointers, if that's what you intended, use the '~' appending operator (here in version '~='); pointers ~= n; Denis -- _ vita es estrany spir.wikidot.com
strange warning at link-time
/usr/bin/ld: Warning: size of symbol `_D5table14__T5TableTkTkZ5Table7opApplyMFDFKkZiZi' changed from 96 in /tmp/.rdmd/rdmd-table.d-403917940996C846133B5FCD56447466/table.o to 100 in /tmp/.rdmd/rdmd-table.d-403917940996C846133B5FCD56447466/table.o ??? Note: this is just a warning, program runs fine anyway. Denis -- _ vita es estrany spir.wikidot.com
Re: Semicolon can be left out after do-while
On 04/12/2011 09:21 PM, Steven Schveighoffer wrote: int main(){ int a,b; do{ scanf(%d %d,a,b); }while(ab) //note missing semicolon here return 0; } The grammar specifies this correctly, but then again, the example uses the semicolon. (http://www.digitalmars.com/d/2.0/statement.html#DoStatement) [...] I think the grammar should be changed... yop! This is almost as bad as go's requirement for if statement opening block to be on the same line... why? I like Go's syntactuc diffs. (except for its multi-for) denis -- _ vita es estrany spir.wikidot.com
Re: Semicolon can be left out after do-while
On 04/12/2011 11:51 PM, Steven Schveighoffer wrote: On Tue, 12 Apr 2011 17:21:57 -0400, spir denis.s...@gmail.com wrote: On 04/12/2011 09:21 PM, Steven Schveighoffer wrote: int main(){ int a,b; do{ scanf(%d %d,a,b); }while(ab) //note missing semicolon here return 0; } The grammar specifies this correctly, but then again, the example uses the semicolon. (http://www.digitalmars.com/d/2.0/statement.html#DoStatement) [...] I think the grammar should be changed... yop! This is almost as bad as go's requirement for if statement opening block to be on the same line... why? I like Go's syntactuc diffs. (except for its multi-for) in Go, this: if(x) { gosWriteRoutineThatIDontKnowTheSyntaxOf(hello) } is equivalent to this in D: if(x) { } writeln(hello); This is frankly unforgivable IMO. Of course it's fixable, but the attitude that the coder should know better doesn't really make me comfortable with it. And I hate the brace on the same line format (but this of course is not a real argument against it). Oh, that's what you meant! I find this a Good Thing, in that it enforces one bracing style (the right one, that does not eats one more line for just a '{'). About knowing or not about this (non/mis/-)feature, it's written down, and clearly, in all Go docs I've read. And one cannot miss it for very long anyway ;-) Maybe, if not done already, a line starting with an opening brace should generate a parsing error. Denis -- _ vita es estrany spir.wikidot.com
Why tuples? [was: Why tuple Re: Why are unsigned to signed conversions implicit...?]
On 04/11/2011 01:47 AM, Andrej Mitrovic wrote: alias Tuple!(byte, red, byte, green, byte, blue) RGBTuple; RGBTuple GetRGB(COLORREF cref) { RGBTuple rgb; rgb.red = GetRValue(cref); rgb.green = GetGValue(cref); rgb.blue = GetBValue(cref); return rgb; } [O your T] Hello, andrej, I'm trying to understand why people use tuples (outside multiple return values and variadic typetuples). Why do you prefere the above to: struct RGBColor { byte red, green, blue; } RGRColor GetRGB (COLORREF cref) { RGBColor rgb; rgb.red = GetRValue(cref); rgb.green = GetGValue(cref); rgb.blue = GetBValue(cref); return rgb; } ? [/O your T] Denis -- _ vita es estrany spir.wikidot.com
Re: Why are unsigned to signed conversions implicit and don't emit a warning?
On 04/11/2011 02:42 AM, bearophile wrote: I and Don have asked (in Bugzilla and elsewhere) to change the built-in names into sbyte and ubyte, to avoid the common confusions between signed and unsigned bytes in D, but Walter was deaf to this. I think a good naming scheme would be: * signed : int8 .. int64 * unsigned : nat8 .. nat64 (since natural number more or less means unsigned integer number) already. What do you think? or counting in octets: * signed : int1 .. int8 * unsigned : nat1 .. nat8 (I prefere the latter naming scheme in absolute, but it would be confusing because some languages --and LLVM, I guess-- count in bits.) Denis -- _ vita es estrany spir.wikidot.com
Re: Why are unsigned to signed conversions implicit and don't emit a warning?
On 04/11/2011 10:10 AM, SimonM wrote: On 2011/04/11 09:31 AM, spir wrote: On 04/11/2011 02:42 AM, bearophile wrote: I and Don have asked (in Bugzilla and elsewhere) to change the built-in names into sbyte and ubyte, to avoid the common confusions between signed and unsigned bytes in D, but Walter was deaf to this. I think a good naming scheme would be: * signed : int8 .. int64 * unsigned : nat8 .. nat64 (since natural number more or less means unsigned integer number) already. What do you think? I like the idea of removing all the different integer type names (byte, short, int, long, cent) and replacing them with int8..int64 (I'd still prefer uint8..uint64 though). Then you could use just 'int' to specify using the current system's architecture (and hopefully replace the ugly size_t type). I also think it makes more sense to just use 'int' when you don't really care about the specific size of the value. Unfortunately it would break backwards compatility so it would never make it into D's current state. Agreed. Same for uint or nat. And no implicit cast, please ;-) Denis -- _ vita es estrany spir.wikidot.com
Re: Before and after in contracts?
On 04/11/2011 04:36 PM, Magnus Lie Hetland wrote: I guess I could just use a local variable (guarded by version()) and then have an assert() near the end of the function. Probably a better solution... If you mean coding your checking by habd inside the func's normal body, this seems to me the right solution. In any case, much simpler and less contorsed than declaring an additional attribute just for that. I would add a comment note telling why it's coded that way (asp. if you use contracts elsewhere). Contracts, like any software tool, do not correctly match all possibly needs. Denis -- _ vita es estrany spir.wikidot.com
Re: Before and after in contracts?
On 04/11/2011 09:18 PM, bearophile wrote: spir: Contracts, like any software tool, do not correctly match all possibly needs. This is true in general, but this isn't true in this case: here they don't match a basic need because D DbC misses a significant feature (prestate). If you take a look at other implementations of DbC in Eiffel and C# the prestate is present. Right, did not know that. Thnaks for this useful info. Denis -- _ vita es estrany spir.wikidot.com
optional func alias template param
Hello, I need a trick to allow a function template parameter be optional. The following (reduced case) fails because D wants to call f: uint f(uint i) { return i; } struct S (alias func=null) { enum bool hasFunc = !(func == null);// *** error line *** } unittest { // ok auto s1 = S!()(); writeln(s1.hasFunc); // not ok auto s2 = S!(f)(); writeln(s2.hasFunc); } == Error: function ___.f (uint i) is not callable using argument types () (I consider that a bug due to f implicitely meaning f() --but this is another story.) The following also fails: // not ok auto s3 = S1!(f)(); writeln(s3.hasFunc); == Error: expression f is not a valid template value argument Denis -- _ vita es estrany spir.wikidot.com
Re: optional func alias template param
On 04/10/2011 04:10 PM, spir wrote: Hello, I need a trick to allow a function template parameter be optional. The following (reduced case) fails because D wants to call f: uint f(uint i) { return i; } struct S (alias func=null) { enum bool hasFunc = !(func == null); // *** error line *** } unittest { // ok auto s1 = S!()(); writeln(s1.hasFunc); // not ok auto s2 = S!(f)(); writeln(s2.hasFunc); } == Error: function ___.f (uint i) is not callable using argument types () (I consider that a bug due to f implicitely meaning f() --but this is another story.) The following also fails: // not ok auto s3 = S1!(f)(); writeln(s3.hasFunc); == Error: expression f is not a valid template value argument PS: I also cannot pass a typed func: struct S (uint delegate (uint) func=null) { enum bool hasFunc = !(func == null); } == Error: arithmetic/string type expected for value-parameter, not uint delegate(uint) -- _ vita es estrany spir.wikidot.com
Re: optional func alias template param
On 04/10/2011 04:10 PM, spir wrote: Hello, I need a trick to allow a function template parameter be optional. The following (reduced case) fails because D wants to call f: uint f(uint i) { return i; } struct S (alias func=null) { enum bool hasFunc = !(func == null); // *** error line *** } unittest { // ok auto s1 = S!()(); writeln(s1.hasFunc); // not ok auto s2 = S!(f)(); writeln(s2.hasFunc); } == Error: function ___.f (uint i) is not callable using argument types () (I consider that a bug due to f implicitely meaning f() --but this is another story.) Found one solution using isCallable! Other tricks welcome... uint f(uint i) { return i; } struct S (alias func=null) { enum bool hasFunc = isCallable!(typeof(func)); } unittest { auto s1 = S!()(); writeln(s1.hasFunc); auto s2 = S!(f)(); writeln(s2.hasFunc); } I'd also like to know why pointer cannot be template *alias* parameters, like in: auto s2 = S!(f)(); == Error: expression f is not a valid template value argument Denis -- _ vita es estrany spir.wikidot.com
speed of low-level C funcs: example of memmove
Hello, To insert of delete an array slice, I tried to use C's memmove, thinking it would be far faster than manually copying bit per bit (by any kind of magic). But I still wrote a D versions just to check what the actual speed gain is. To my great surprise, the C-memmove and D-manual versions perform *exactly* at the same speed (considering measure imprecision). Note: this remains true when elements are bigger; speed slows down slowly (eg dchar's take only 1/3 more time). Any comment or explanation welcome. Below the code. Denis = code = import std.date : getUTCtime, d_time; import std.c.string : memmove; // C interface: void *memmove(void *dest, const void *src, size_t n); void shiftEndPartC (E) (ref E[] array, size_t source, size_t dest) { // Record length before possible extension. auto length = array.length; int offset = dest - source; // If move up, extend array to make place. if (offset 0) array.length += offset; // Shift slice. auto pDest = cast(void*)((array[dest])); auto pSource= cast(void*)((array[source])); size_t size = (length - source) * E.sizeof; memmove(pDest, pSource, size); // If move down, compress array. if (offset 0) array.length += offset; } void shiftEndPartD (E) (ref E[] array, size_t source, size_t dest) { // Record length before possible extension. auto length = array.length; int offset = dest - source; // If move up, extend array shift backwards. if (offset 0) { array.length += offset; for (size_t i=length-1 ; i=source ; i--) array[i+offset] = array[i]; } // If move down, shift forwards compress array. if (offset 0) { for (size_t i=source ; ilength ; i++) array[i+offset] = array[i]; array.length += offset; } } void testFuncs () { char[] s; // C memmove s = 0123456789.dup; writeln(s); // Insert slice. s.shiftEndPartC(3,5); s[3..5] = --; writeln(s); // Delete slice. s.shiftEndPartC(5,3); writeln(s); writeln(); // D manual s = 0123456789.dup; writeln(s); // Insert slice. s.shiftEndPartD(3,5); s[3..5] = --; writeln(s); // Delete slice. s.shiftEndPartD(5,3); writeln(s); writeln(); } void chrono () { char[] s; d_time t; enum N = 1_000_000; // C memmove s = 0123456789.dup; t = getUTCtime(); foreach (_ ; 0..N) { s.shiftEndPartC(3,5); s[3..5] = --; s.shiftEndPartC(5,3); } t = getUTCtime() - t; writefln(C time: %s, t); // D manual s = 0123456789.dup; t = getUTCtime(); foreach (_ ; 0..N) { s.shiftEndPartD(3,5); s[3..5] = --; s.shiftEndPartD(5,3); } t = getUTCtime() - t; writefln(D time: %s, t); } unittest { //~ testFuncs(); chrono(); } void main () {} -- _ vita es estrany spir.wikidot.com
Re: speed of low-level C funcs: example of memmove
On 04/09/2011 07:08 PM, spir wrote: Hello, To insert of delete an array slice, I tried to use C's memmove, thinking it would be far faster than manually copying bit per bit (by any kind of magic). But I still wrote a D versions just to check what the actual speed gain is. To my great surprise, the C-memmove and D-manual versions perform *exactly* at the same speed (considering measure imprecision). Note: this remains true when elements are bigger; speed slows down slowly (eg dchar's take only 1/3 more time). Correction: memmove can be from 5 to 10 times faster on big arrays. For instance, with 1_000_000 char array: void chrono () { char[] s; d_time t; enum N = 100; // C memmove s = (0.mult(1_000_000)).dup; t = getUTCtime(); foreach (_ ; 0..N) { s.shiftEndPartC(3,5); s[3..5] = --; s.shiftEndPartC(5,3); } t = getUTCtime() - t; writefln(C time: %s, t); // D manual s = (0.mult(1_000_000)).dup; t = getUTCtime(); foreach (_ ; 0..N) { s.shiftEndPartD(3,5); s[3..5] = --; s.shiftEndPartD(5,3); } t = getUTCtime() - t; writefln(D time: %s, t); } -- _ vita es estrany spir.wikidot.com
Re: ddoc patterns
On 04/08/2011 03:00 PM, Aleksandar Ružičić wrote: On Thu, Apr 7, 2011 at 7:27 PM, spirdenis.s...@gmail.com wrote: how are we supposed to insert code phrases in the flow of normal text? code/code tags should be used for that (http://www.w3.org/TR/html401/struct/text.html#h-9.2.1). Right, but IIUC unlike pre there is no guarantee for code contents not to be interpreted further. It's a semantic hint to the rendering engine (which is often used to perform syntax highlighting). But I know nothing about ddoc so I don't know how to write macro that will use code instead ofpre. Although I believe it's a piece of cake :) Yes: Macros: CODE = code$0/code Denis -- _ vita es estrany spir.wikidot.com
Re: char[][] join == string
On 04/07/2011 03:07 AM, Ali Çehreli wrote: Given an array of strings std.string.join() returns a single string: import std.string; void main() { string[] a1 = [hello, red]; string j1 = join(a1, ); // OK } But in a program I need an array of mutable arrays of chars. If I join the arrays I get a mutable array of chars. [...] Finally, casting ourselves works: string j2 = cast(string)join(a2, ); Oh, that's very good news! Thans Ali, I never thought at that solution. I'm often i/dup-ing from/to string to manipulate text due to the fact there is no automatic conversion. cast() works in place, doesn't it? so this is supposed avoid to avoid copy. PS: Checked: indeed, it works in-place. But watch the gotcha: unittest { string s = abc; char[] chars = cast(char[])s; chars ~= de; s = cast(string) chars; writeln(s, ' ', chars); // abcde abcde chars[1] = 'z'; writeln(s, ' ', chars); // azcde azcde } s's chars are mutable ;-) So, I guess there is /really/ no reason for implicite casts between char[] and string no to exist. (I assumed the reason was precisely to avoid such traps). Denis -- _ vita es estrany spir.wikidot.com
Re: char[][] join == string
On 04/07/2011 09:52 AM, spir wrote: On 04/07/2011 03:07 AM, Ali Çehreli wrote: Given an array of strings std.string.join() returns a single string: import std.string; void main() { string[] a1 = [hello, red]; string j1 = join(a1, ); // OK } But in a program I need an array of mutable arrays of chars. If I join the arrays I get a mutable array of chars. [...] Finally, casting ourselves works: string j2 = cast(string)join(a2, ); Oh, that's very good news! Thans Ali, I never thought at that solution. I'm often i/dup-ing from/to string to manipulate text due to the fact there is no automatic conversion. cast() works in place, doesn't it? so this is supposed avoid to avoid copy. PS: Checked: indeed, it works in-place. But watch the gotcha: unittest { string s = abc; char[] chars = cast(char[])s; chars ~= de; s = cast(string) chars; writeln(s, ' ', chars); // abcde abcde Sorry: forgot this line: assert(s.ptr == chars.ptr); // pass chars[1] = 'z'; writeln(s, ' ', chars); // azcde azcde } s's chars are mutable ;-) So, I guess there is /really/ no reason for implicite casts between char[] and string no to exist. (I assumed the reason was precisely to avoid such traps). Denis -- _ vita es estrany spir.wikidot.com
Re: char[][] join == string
On 04/07/2011 09:52 AM, spir wrote: On 04/07/2011 03:07 AM, Ali Çehreli wrote: Given an array of strings std.string.join() returns a single string: import std.string; void main() { string[] a1 = [hello, red]; string j1 = join(a1, ); // OK } But in a program I need an array of mutable arrays of chars. If I join the arrays I get a mutable array of chars. [...] Finally, casting ourselves works: string j2 = cast(string)join(a2, ); Oh, that's very good news! Thans Ali, I never thought at that solution. I'm often i/dup-ing from/to string to manipulate text due to the fact there is no automatic conversion. cast() works in place, doesn't it? so this is supposed avoid to avoid copy. PS: Checked: indeed, it works in-place. But watch the gotcha: unittest { string s = abc; char[] chars = cast(char[])s; chars ~= de; s = cast(string) chars; writeln(s, ' ', chars); // abcde abcde chars[1] = 'z'; writeln(s, ' ', chars); // azcde azcde } s's chars are mutable ;-) So, I guess there is /really/ no reason for implicite casts between char[] and string no to exist. (I assumed the reason was precisely to avoid such traps). After some more thought, I guess it's better to leave things as are. We have a way to cast without copy --which is one issue perfectly solved. The other issue --typing-- is small enough to keep it, since it also serves as warning to the programmer about the above trap. What should definitely be done is teaching this idiom in all relevant places of the reference, manuals, tutorials: while this issue is often submitted on D lists, I had never read about it (nore thought about it myself). Questions: did you know this idiom? if yes, have you found it yourself or read about it? if the latter, where? Denis -- _ vita es estrany spir.wikidot.com
ddoc patterns
Hello, In D stdlib's ddoc the idiom $(D some d code) is constantly used. But it does not work by me. Not only it's not interpreted, but the contents are stripped out all together. (A *very* big bug of ddoc.) First, I'd like to know why. Second, there is another pattern $(D_CODE some d code), but it place the code on a separate block. Is this intended? Third, http://www.digitalmars.com/d/2.0/ddoc.html seems to imply one can define new patterns. How to do that? I tried following the example, but my code ends up interpreted and stripped out. Denis -- _ vita es estrany spir.wikidot.com
Re: ddoc patterns
On 04/07/2011 10:20 AM, spir wrote: Hello, In D stdlib's ddoc the idiom $(D some d code) is constantly used. But it does not work by me. Not only it's not interpreted, but the contents are stripped out all together. (A *very* big bug of ddoc.) First, I'd like to know why. Second, there is another pattern $(D_CODE some d code), but it place the code on a separate block. Is this intended? Third, http://www.digitalmars.com/d/2.0/ddoc.html seems to imply one can define new patterns. How to do that? I tried following the example, but my code ends up interpreted and stripped out. OK found it: pattern defs must be places under a Macro: section title. I take the opprtunity to ask another question: does anyone know how to tag a *span* of text as literal/uninterpreted (either in html or css). The issue is pre makes a *block*, even if not inside a div or p; I desperately need the same feature for inline pieces of code. Denis -- _ vita es estrany spir.wikidot.com
Re: ddoc patterns
On 04/07/2011 12:53 PM, bearophile wrote: spir: I take the opprtunity to ask another question: does anyone know how to tag a *span* of text as literal/uninterpreted (either in html or css). The issue is pre makes a *block*, even if not inside adiv orp; I desperately need the same feature for inline pieces of code. Try: -- code here -- Bye, bearophile This makes a block --just what I don't want. Denis -- _ vita es estrany spir.wikidot.com
use of C memmove
Hello, I'm trying to use C's memmove as a tool to delete or insert a slice from/into an array. But I cannot manage to do it: systematic segmentation fault. What is wrong below? import std.c.string : memmove; // void *memmove(void *dest, const void *src, size_t n); void moveEnd (E) (E[] elements, size_t start, int offset) { // Length must be known before possible extension. auto length = elements.length; // If move up, extend array to make place. if (offset 0) elements.length += offset; // Move slice. auto dest = cast(void*)((elements[start + offset])); auto source = cast(void*)((elements[start])); size_t size = length - start; memmove(dest, source, size);// segfault *** // If move down, compress array. if (offset 0) elements.length += offset; } unittest { string s = 012--3456789; // Remove slice. s.moveEnd(5, -2); writeln(s); } Denis -- _ vita es estrany spir.wikidot.com
Re: ddoc patterns
On 04/07/2011 03:32 PM, Jacob Carlborg wrote: On 2011-04-07 12:25, spir wrote: On 04/07/2011 10:20 AM, spir wrote: Hello, In D stdlib's ddoc the idiom $(D some d code) is constantly used. But it does not work by me. Not only it's not interpreted, but the contents are stripped out all together. (A *very* big bug of ddoc.) First, I'd like to know why. Second, there is another pattern $(D_CODE some d code), but it place the code on a separate block. Is this intended? Third, http://www.digitalmars.com/d/2.0/ddoc.html seems to imply one can define new patterns. How to do that? I tried following the example, but my code ends up interpreted and stripped out. OK found it: pattern defs must be places under a Macro: section title. I take the opprtunity to ask another question: does anyone know how to tag a *span* of text as literal/uninterpreted (either in html or css). The issue is pre makes a *block*, even if not inside a div or p; I desperately need the same feature for inline pieces of code. Denis Have a look at the CSS display property: http://w3schools.com/css/pr_class_display.asp Great, does the trick! But is there else really no other way to suspend interpretation as pre? I find this strange... how are we supposed to insert code phrases in the flow of normal text? Denis -- _ vita es estrany spir.wikidot.com
Re: use of C memmove
On 04/07/2011 08:12 PM, Steven Schveighoffer wrote: On Thu, 07 Apr 2011 13:09:05 -0400, spir denis.s...@gmail.com wrote: Hello, I'm trying to use C's memmove as a tool to delete or insert a slice from/into an array. But I cannot manage to do it: systematic segmentation fault. What is wrong below? import std.c.string : memmove; // void *memmove(void *dest, const void *src, size_t n); void moveEnd (E) (E[] elements, size_t start, int offset) { // Length must be known before possible extension. auto length = elements.length; // If move up, extend array to make place. if (offset 0) elements.length += offset; // Move slice. auto dest = cast(void*)((elements[start + offset])); auto source = cast(void*)((elements[start])); size_t size = length - start; memmove(dest, source, size); // segfault *** // If move down, compress array. if (offset 0) elements.length += offset; } unittest { string s = 012--3456789; // Remove slice. s.moveEnd(5, -2); writeln(s); } Two problems. One is, the memmove size_t n is number of *bytes*, not number of elements as you have expected. You probably would have noticed this quickly if the other problem wasn't there. The other problem is, strings literals are immutable. On Windows, this code may have worked, but Linux protects the pages of static data, so writing to a string literal creates a seg fault. Try this: auto s = 012--3456789.dup; // convert to char[] To fix first problem use memmove(dest, source, size * (E).sizeof); Thank you very much, Steven! Denis -- _ vita es estrany spir.wikidot.com
error Not the start of the UTF-8 sequence
Hello, I get this error message: Not the start of the UTF-8 sequence without any other comment module name or whatnot. This happens when I just added toString to the following struct, and used it: struct Node { // Note: level is equal to the number of chars up to this node. // Note: a 'path' node without entry has key=. char ch; uint level; Key key; Value value; ... string toString() { if (this.key != ) return format(%s %s:%s, this.ch, this.key, this.value); else return format(%s, this.ch); } } Hints? I'm blocked :-( Denis -- _ vita es estrany spir.wikidot.com
[SOLVED] [BUG?] Re: error Not the start of the UTF-8 sequence
On 04/06/2011 11:53 AM, Kagamin wrote: spir Wrote: Hello, I get this error message: Not the start of the UTF-8 sequence without any other comment module name or whatnot. This happens when I just added toString to the following struct, and used it: struct Node { // Note: level is equal to the number of chars up to this node. // Note: a 'path' node without entry has key=. char ch; uint level; Key key; Value value; ... string toString() { if (this.key != ) return format(%s %s:%s, this.ch, this.key, this.value); else return format(%s, this.ch); } } Hints? I'm blocked :-( struct Node { // Note: level is equal to the number of chars up to this node. // Note: a 'path' node without entry has key=. dchar ch; Sorry, no, nothing to do with the type. The error came from a special case where ch='\0'. Seems some routine in dmd does not like that; but no idea where the error comes from. There are two points to solve, I guess: * The error message should tell where it happens. * '\0' is a valid code point, should pass through without error. Denis -- _ vita es estrany spir.wikidot.com
Re: The is expression
On 04/02/2011 12:14 AM, enuhtac wrote: template isA( T ) { static if( is( T U == A!( U, s ), string s ) ) enum bool isA = true; else enum bool isA = false; }; What does , string s do here inside the is expression? Denis -- _ vita es estrany spir.wikidot.com
Re: null Vs [] return arrays
On 04/01/2011 12:38 PM, Regan Heath wrote: On Mon, 28 Mar 2011 17:54:29 +0100, bearophile bearophileh...@lycps.com wrote: Steven Schveighoffer: So essentially, you are getting the same thing, but using [] is slower. It seems I was right then, thank you and Kagamin for the answers. This may be slightly OT but I just wanted to raise the point that conceptually it's nice to be able to express (exists but is empty) and (does not exist). Pointers/references have null as a (does not exist) value and this is incredibly useful. Try doing the same thing with 'int' .. it requires you either use int* or pass an additional boolean to indicate existence.. yuck. I'd suggest if someone types '[]' they mean (exists but is empty) and if they type 'null' they mean (does not exist) and they may be relying on the .ptr value to differentiate these cases, which is useful. If you're not interested in the difference, and you need performance, you simply use 'null'. Everybody is happy. :) That's the way I understand this distinction. Unfortunately, D does not really allow this, by semantically treating both indifferently (eg one can put a new element into an null array). Denis -- _ vita es estrany spir.wikidot.com
Re: We could use a hasExt function in std.path
On 04/01/2011 11:03 PM, Andrej Mitrovic wrote: At least on Windows, as far as I know, the casing of a file extension doesn't come into play. But when comparing extensions, you have to be careful to lowercase the result of `getExt()`, for example: foreach (string name; dirEntries(curdir, SpanMode.shallow)) { if (name.isFile name.getExt == txt) { // do something } } If the extension is cased tXt, the if block will not be entered. That's a silent bug in your code right there! I think we could use a function in Phobos that returns true if an extension of a file matches any number of strings passed to it (a range). And an extra argument could be a flag (enum) or a boolean which can set the case sensitivity to true, but is false by default, e.g.: bool hasExt(Range)(string fileName, Range exts, bool caseSensitive = false) { static if (isSomeString!Range) { if (caseSensitive) { if (exts == fileName.getExt) return true; } else { if (exts.tolower == fileName.getExt.tolower) return true; } } else { foreach (ext; exts) { if (caseSensitive) { if (ext == fileName.getExt) return true; } else { if (ext.tolower == fileName.getExt.tolower) return true; } } } return false; } foreach (string name; dirEntries(curdir, SpanMode.shallow)) { if (name.isFile name.hasExt([ini, conf])) { // do something } } Yes, that is a horrible implementation, but I can't be bothered with trying to make it nice and simple right now, I'm in a rush. Sorry. :) I often have to search for files that have a certain extension. Having to expand the code to the following becomes ugly real fast: foreach (string name; dirEntries(curdir, SpanMode.shallow)) { if (name.isFile name.hasExt.tolower == ini || name.hasExt.tolower == conf)) { // do something } } Would be nice eg to match a whole set of image formats at once (while also caring for uncased matching). But why a range? Denis -- _ vita es estrany spir.wikidot.com
Re: Contracts or Exceptions?
On 03/30/2011 05:32 AM, Ali Çehreli wrote: On 03/29/2011 03:40 PM, Kai Meyer wrote: I was given two words of advice on exceptions: Use exceptions for the exceptional Use exceptions only for the exceptional Those advices are given by wise people: they are wise only because they leave the definition as vague as exceptional. :) And what do we do for the not so exceptional? Do we return error codes? So the function implementation will be complicated and the caller code will be complicated. Exceptions are a great tool to eliminate the need for error codes. Here is what I follow: - Functions have specific tasks to do; if those tasks cannot be accomplished, the function must throw. In some cases the function can continue, but that behavior must be documented. For example, if an HTML library function is responsible for making HTML headers, of which only the levels in the range of 1-6 are valid, that function may throw when the level is outside of the valid range, for in that case it cannot make an HTML header; or it can document that if the level is outside of the range, 1 or 6 will be used. - Catch exceptions only when there is a sensible thing to do at that level: log an error, skip that operation, go back to the user with an error code, take corrective action, etc. Disclaimer: That is what I follow in C++ code. I don't have experience with exception safety in D. I don't know issues that may be specific to D. These are sensible and well expressed guidelines, thank you. In other languages, I happened to use exceptions as a // channel for side-information (eg 'nomatch' for a matching func), but in D I realised how 'exceptionnally' (!) costly throwing catching exceptions is, so that I do not do it anymore. No idea though whether this exceptional cost is perticular to D. Denis -- _ vita es estrany spir.wikidot.com
Re: Memory usage of AAs?
On 03/30/2011 03:31 PM, Steven Schveighoffer wrote: On Tue, 29 Mar 2011 22:20:05 -0400, Nick Sabalausky a@a.a wrote: spir denis.s...@gmail.com wrote in message news:mailman.2909.1301443345.4748.digitalmars-d-le...@puremagic.com... On 03/30/2011 01:24 AM, Nick Sabalausky wrote: My understanding of hash tables is that they allocate a fixed size array and map keys to indicies within the range 0..predefined_length_of_the_AA. So I've been wondering, how many elements do D's built-in AAs have? And what's the content of each one, just a single pointer? Each element is a data structure, often called bucket (typically a link list), storing (key:value) pairs for which the key, once hashed and modulo-ed, maps to the given index. That's why the famous O(1) lookup time for hash tables is very theoretic: the constant part holds average time for hashing which is very variable, plus another average time for linearly traversing the bucket. The latter part depends on table load factor (= number of elements / number of buckets) and proper statistical repartition of keys into buckets. The key (!) points are finding a good hash func to linearize said repartition (which depends on actual key-data domain, not only on their type...), but better ones rapidly eat much time (ones used in practice are rather simple fast); and finding optimal load factor, and growth scheme. In practice, all of this tends to make hash tables an implementation nightmare (for me). I'd love to find practicle alternatives, but efficient binary trees also are complex and even more depend on kind of keys, I guess. Right, I know that, but that's not what I was asking. Take this hypothetical implementation: struct Bucket(TKey, TVal) { ... } enum hashTableSize = ...; struct Hash(TKey, TVal) { Bucket!(TKey, TVal)[hashTableSize] data; TVal get(TKey key) { ... } void set(TKey key, TVal value) { ... } } I assume that D's AA are something at least vaguely like that. My questions are: 1. What does D use for hashTableSize? Or does hashTableSize vary? If it varies, what's a typical rough ballpark size? (And just out of curiosity, if it varies, is it decided at compile-time, or does it change even at runtime?) It varies. The hash table size is not constant, the load factor is. The load factor is the number of elements in the hash divided by the number of buckets. You never want to fill up all the spaces, because the more full you get, the more chances for collisions there are. Essentially, the tricky part about hashing is what to do about collisions (two elements are different, but go in the same bucket). So what happens is when the load factor exceeds a predefined constant (e.g. in dcollections the load factor defaults to .75), the table rehashes, or increases (usually logarithmically) the size of the array, and re-inserts all its elements. I believe there is a minimum array size, and things are increased from there. I think also you can do a manual rehash which should adjust the size of the array to match a certain load factor (below the maximum). Yes, there is a rehash method. In some implementations, hashes will even shrink when the load factor goes below a minimum (dcollections does not do this to avoid invalidating ranges). There are a million different ways to implement the basic hash. The most complex part though, is usually the collision handling. In my algo book, there are at least 3 ways to handle collisions, and I think there are countless more. If you look up hashing on wikipedia, you'll get a much better explanation. 2. What is sizeof(Bucket(TKey, TVal))? And I mean the shallow size, not deep size. Is it dependent on TKey or TVal? Or is it just simply a pointer to the start of a linked list (and therefore sizeof(size_t))? Here is the AA implementation: https://github.com/D-Programming-Language/druntime/blob/master/src/rt/aaA.d From that page, you can see that AA is your bucket (note this is runtime stuff, so there are no templates), and BB is your Hash struct. It looks like BB has an array of AA pointers. IIRC, this is because buckets are (minimal) link lists. Cells holding key:value are list nodes. -Steve -- _ vita es estrany spir.wikidot.com
Re: Using opDispatch as *magic* getter/setter. Possible or not?
On 03/31/2011 02:40 AM, Aleksandar Ružičić wrote: 2011/3/31 Aleksandar Ružičićruzicic.aleksan...@gmail.com: Or maybe there is some other way to achive what I want and I'm not aware of it? :-) I know I could have used opIndex and opIndexAssign but I really want config.section.entry syntax instead of config[section][entry]... Agreed. And I would really have an answer to your question, since I tried to do the same thing. Don't understand why D does not have an 'opMember' or 'opDot'. Someone knows? This would be one of the first metamethods I would introduce in a language (definitely before operator overloading). denis -- _ vita es estrany spir.wikidot.com
Re: Container access in std.container
On 03/29/2011 12:43 PM, Ishan Thilina wrote: I'm using GDC because I can't use DMD in linux. I have started a seperate thread for that. I'm using dmd on Linux without any issue. But only stable releases (several versions have passed). May I suggest you take some time to uninstall everything properly, then install again from scratch according to the online guidelines: downloads: http://www.digitalmars.com/d/download.html win: http://www.digitalmars.com/d/2.0/dmd-windows.html linux: http://www.digitalmars.com/d/2.0/dmd-linux.html Denis -- _ vita es estrany spir.wikidot.com
Re: Memory usage of AAs?
On 03/30/2011 01:24 AM, Nick Sabalausky wrote: My understanding of hash tables is that they allocate a fixed size array and map keys to indicies within the range 0..predefined_length_of_the_AA. So I've been wondering, how many elements do D's built-in AAs have? And what's the content of each one, just a single pointer? Each element is a data structure, often called bucket (typically a link list), storing (key:value) pairs for which the key, once hashed and modulo-ed, maps to the given index. That's why the famous O(1) lookup time for hash tables is very theoretic: the constant part holds average time for hashing which is very variable, plus another average time for linearly traversing the bucket. The latter part depends on table load factor (= number of elements / number of buckets) and proper statistical repartition of keys into buckets. The key (!) points are finding a good hash func to linearize said repartition (which depends on actual key-data domain, not only on their type...), but better ones rapidly eat much time (ones used in practice are rather simple fast); and finding optimal load factor, and growth scheme. In practice, all of this tends to make hash tables an implementation nightmare (for me). I'd love to find practicle alternatives, but efficient binary trees also are complex and even more depend on kind of keys, I guess. Denis -- _ vita es estrany spir.wikidot.com
Re: Sample source code for D
On 03/28/2011 05:43 AM, Ishan Thilina wrote: @ David: I'm looking for example code that explains specific pieces of functionality :) @Lutger: Those two links were really helpful :). Thank you :) There are tutorial examples of D code at DSource; they were initially D1, but many of them are compatible or translated to D2; rather good place to start: http://www.dsource.org/projects/tutorials On the official D wiki, you'll find some useful material and links (tutorial, example, howto); unfortunatly, some of those materials are rather light: http://prowiki.org/wiki4d/wiki.cgi?DevelopmentWithD http://prowiki.org/wiki4d/wiki.cgi?D__Tutorial http://prowiki.org/wiki4d/wiki.cgi?HowTo http://prowiki.org/wiki4d/wiki.cgi?ExamplesRoadmap Also useful comparisons: http://prowiki.org/wiki4d/wiki.cgi?LanguagesVersusD http://en.wikibooks.org/wiki/D_Transition_Guide Denis -- _ vita es estrany spir.wikidot.com
Re: object.d: Error: module object is in file 'object.d' which cannot be read
On 03/28/2011 04:49 PM, Ishan Thilina wrote: now I get a whole lot more errors :s. ishan@ishan-Ubu-I1464:~/Geany Projects$ dmd untitle.d /usr/include/d/dmd/phobos/object.d(51): C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers /usr/include/d/dmd/phobos/std/format.d(672): no identifier for declarator inout(fakevalue) /usr/include/d/dmd/phobos/std/c/stdlib.d(43): C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers /usr/include/d/dmd/phobos/std/c/stdlib.d(59): C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers /usr/include/d/dmd/phobos/std/c/linux/linux.d(558): C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers /usr/include/d/dmd/phobos/std/c/linux/linux.d(574): C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers I'm trying to compile the following simple code. As you can see it should work without any problem. import std.stdio; int main() { writefln(Hello world); return 0; } I have no idea why and where your issues in using D with dmd come from. AFAIK, it just works out of the box if you use release versions. Just 2 notes about the piece of code: First, you often do not need in D a program result code (int). Second, writefln, as opposed to writeln, expects a format string as first argument. void main () { writeln(Hello, world!); auto userName = Otto; writefln(Hello, %s!, userName); } Denis -- _ vita es estrany spir.wikidot.com
Re: object.d: Error: module object is in file 'object.d' which cannot be read
On 03/27/2011 12:28 PM, Ishan Thilina wrote: When I give dmd untitled.d command in my ubuntu maverick 64 bit laptop I get the following error. object.d: Error: module object is in file 'object.d' which cannot be read import path[0] = /etc/../../src/phobos import path[1] = /etc/../../src/druntime/import I tried all morning to solve this problem, tried every google result I could find. Checked the mail archive to solve this problem. But I still couldn't get rid of that error.I anybody can help me, it would be a great help. I followed the steps in http://www.digitalmars.com/d/2.0/dmd-linux.html .I first used the command cp dmd2/linux/bin/dmd.conf /etc . Then I gave sudo apt-get install gcc-multilib g++-multilib libc6-i386 libc6-dev-i386 command. Thank you :) First, please always post the piece of code that provokes an error. If it's a big or complicated thing, then try to reduce it to the smallest and simplest bit possible. Usually, doing this will let you find the source of the problem ;-) Second, this kind of error is caused by wrong import path (yes, the error message could mention import). Typically, when one writes eg: import range; instead of import std.range; But your case is strange. Do you know object.d is the core of D's std lib, which defines about all what you absolutely need to use when programming in D? One does not need to import it, this is automatical. Also, the message says the error happens in object.d itself, which is very un-probable. I thus suspect you named one of your own modules object.d, which breaks the import mechanics (for D's standard object.d and possibly for other stdlib/phobos modules). This may be considered as a bug. denis -- _ vita es estrany spir.wikidot.com
Re: object.d: Error: module object is in file 'object.d' which cannot be read
On 03/27/2011 12:28 PM, Ishan Thilina wrote: When I give dmd untitled.d command in my ubuntu maverick 64 bit laptop I get the following error. object.d: Error: module object is in file 'object.d' which cannot be read import path[0] = /etc/../../src/phobos import path[1] = /etc/../../src/druntime/import I tried all morning to solve this problem, tried every google result I could find. Checked the mail archive to solve this problem. But I still couldn't get rid of that error.I anybody can help me, it would be a great help. I followed the steps in http://www.digitalmars.com/d/2.0/dmd-linux.html .I first used the command cp dmd2/linux/bin/dmd.conf /etc . Then I gave sudo apt-get install gcc-multilib g++-multilib libc6-i386 libc6-dev-i386 command. Thank you :) PS: I tried to compile an empty module called object.d. This gives me pages pages pages of undefined x errors ;-) denis -- _ vita es estrany spir.wikidot.com
Re: Want to help DMD bugfixing? Write a simple utility.
On 03/24/2011 08:53 AM, Alexey Prokhin wrote: Currently, as far as I know, there are only two lexers and two parsers for D: the C++ front end which dmd, gdc, and ldc use and the D front end which ddmd uses and which is based on the C++ front end. Both of those are under the GPL (which makes them useless for a lot of stuff) and both of them are tied to compilers. Being able to lex D code and get the list of tokens in a D program and being able to parse D code and get the resultant abstract syntax tree would be very useful for a number of programs. I fully support this. We desperately need it, I guess, working and maintained along language evolution. This is the whole purpose of the GSOC proposal D tools in D: http://prowiki.org/wiki4d/wiki.cgi?GSOC_2011_Ideas#DtoolsinD Semantic analysis, introduced step by step, would be a huge plus. Denis -- _ vita es estrany spir.wikidot.com
Re: Little quiz
On 03/25/2011 01:50 AM, bearophile wrote: A little quiz for people here: guess the output of this little D2 program (it compiles correctly and doesn't crash at run time, so it's a fair question): import std.typecons: tuple; import std.c.stdio: printf; auto foo() { printf(foo\n); return tuple(1, 2); } void main() { foreach (x; foo().tupleof) printf(%d\n, x); } lol, would never haver guessed Denis -- _ vita es estrany spir.wikidot.com
Re: Other integral literals?
On 03/20/2011 04:40 PM, bearophile wrote: Do you ever desire literals for byte, ubyte, short and ushort integrals (beside the currently present for int, uint, long, ulong that are 10, 10U, 10L, 10UL)? Because of the more strict typing of templates in some situations I have had to write things like: cast(ubyte)100 Possible literals for byte, ubyte, short and ushort integrals (the byte ones aren't great): 10Y 10UY 10S 10US Are similar suffixes useful enough to have? I would support this gratefully. I find it a big weakness of D that its literals do not map to a type. As for precise morphology, I'd prefere * instead of cryptic suffixes like 'Y' or 'S', numerous languages simply write the size : 8, 16, 32, 64: much nicer! A better idea would be to count the size in bytes: 1, 2, 4, 8. * else, use lowercase suffixes in std, because digits are full height (so that the suffix is more clearly told apart) * for the same reason, hex literals should use uppercase digits in std and '0x' prefix * ideally, I would use the sign to tell signed types apart (1 is unsigned, +1 is signed) * get rid of 1. and .1 horrors! * get rif of 01 octal bug! Denis -- _ vita es estrany spir.wikidot.com
Re: Ranges
On 03/18/2011 10:29 AM, Peter Alexander wrote: On 13/03/11 12:05 AM, Jonathan M Davis wrote: So, when you're using a range of char[] or wchar[], you're really using a range of dchar. These ranges are bi-directional. They can't be sliced, and they can't be indexed (since doing so would likely be invalid). This generally works very well. It's exactly what you want in most cases. The problem is that that means that the range that you're iterating over is effectively of a different type than the original char[] or wchar[]. This has to be the worst language design decision /ever/. You can't just mess around with fundamental principles like the first element in an array of T has type T for the sake of a minor convenience. How are we supposed to do generic programming if common sense reasoning about types doesn't hold? This is just std::vectorbool from C++ all over again. Can we not learn from mistakes of the past? I partially agree, but. Compare with a simple ascii text: you could iterate over it chars (=codes=bytes), words, lines... Or according to specific schemes for your app (eg reverse order, every number in it, every word at start of line...). A piece of is not only a stream of codes. The problem is there is no good decision, in the case of char[] or wchar[]. We should have to choose a kind of natural sense of what it means to iterate over a text, but there no such thing. What does it *mean*? What is the natural unit of a text? Bytes or words are code units which mean nothing. Code units (- dchars) are not guaranteed to mean anything neither (as shown by past discussion: a code unit may be the base 'a', the following one be the composite '^', both in â). Code unit do not represent characters in the common sense. So, it is very clear that implicitely iterating over dchars is a wrong choice. But what else? I would rather get rid of wchar and dchar and deal with plain stream of bytes supposed to represent utf8. Until we get a good solution to operate at the level of human characters. Denis -- _ vita es estrany spir.wikidot.com
Re: Reading a line from stdin
On 03/16/2011 06:05 AM, Ali Çehreli wrote: I am going over some sample programs in a text of mine and replacing std.cstream references with std.stdio. There are non-trivial differences with formatted input. The following program may be surprising to the novice: import std.stdio; void main() { write(What is your name? ); string name = readln(); writeln(Hi , name, !); } The newline character is read as a part of the input: What is your name? Ali Hi Ali ! -- this is outputted on the next line because of the newline character This is a design bug. 99% of the time one does not want the newline, which is not part of the string data, instead just a terminator. Even more on stdin where it is used by the user to say Im done!. If the text is written back to the output /and/ newline is needed, it's easy to add it or use writeln. Also, to avoid using strip --which is costly and may remove other significant whitespace at start and end of line, one would have to manually check for CR and/or LF, and remove it, *twice*. A solution may be to have a boolean param keepNewLine beeing false in standard. A solution is to strip the line after reading: import std.string; // ... string name = strip(readln()); Right? Is there a better way that I am missing? Dunno. Denis -- _ vita es estrany spir.wikidot.com
Re: Reading a line from stdin
On 03/16/2011 06:41 AM, Jesse Phillips wrote: Ali Çehreli Wrote: Right? Is there a better way that I am missing? Thank you, Ali No better way, the stated reason IIRC is that it is easier to remove the new line then to append it back on. May be stated, but it is very wrong! I guess: s = s ~ '\n'; versus if ((str[$-1] == '\n') || (str[$-1] == '\r')) { str = str[0..$-1]; if ((str[$-1] == '\n') || (str[$-1] == '\r')) { str = str[0..$-1]; } } And it's not what programmers want in most cases, anyway. Actually, when does one need it? Denis -- _ vita es estrany spir.wikidot.com
Re: Help passing D strings to C libs
On 03/14/2011 07:55 AM, Gene P. Cross wrote: -Daniel I tried what you said: char* ptr = toStringz(path); SDL_LoadBMP(ptr); and made a check to see if the pointer is null, which it isn't, but I'm unable to inspect is value, I haven't a debugger at the moment, could you recommend one ? I also made the string a char[] and tested to see if that made a difference. I think it may be something to do with SDL itself. I tried calling another function, SDL_GetTicks(), and that's causing problems as well. -Jonathan I read the docs earlier and found the same thing about literals being null terminated but not regular strings, which explains why they work. Double check after double check, I am also certain that no other code is messing with it and changing values. I'm surprised about your problem. There is no difference between the .ptr property of a null-terminated D char[] and a C string (hum). And I'm rather sure (not checked the code) that's precisely what toStringZ does. The issue must lie on some point you have not mentionned yet. Denis -- _ vita es estrany spir.wikidot.com
Re: Iterating over an enum associative array
On 03/14/2011 12:21 PM, Nebster wrote: Hey, I'm having some problems iterating over an enumerated associative array. It comes up with this error at compile time: Internal error: e2ir.c 4835 I cut the code down to this: import std.stdio; enum int[string] assoc = [;: 0, =: 1, +: 2, -: 2, *: 3, /: 3]; void main() { foreach(op; assoc.byKey()) writefln(op: %s, op); } What does this mean/how can I get this to work? There are problems with associative array constants. I'm not 100% sure this is the source of your error, though. Anyway, the following works fine, using the module's static this constructor: static int[string] assoc; static this () { assoc = [;: 0, =: 1, +: 2, -: 2, *: 3, /: 3]; } static enum seq = [1,2,3]; unittest { foreach(op ; assoc.byKey()) writefln(op: %s, op); foreach(n ; seq) writefln(n: %s, n); } == op: * op: + op: - op: / op: ; op: = n: 1 n: 2 n: 3 You can use this trick each time you need a D module to hold predefined and/or precomputed data (meaning, you need D to play the role of a data description language). This is not needed if said data is plain simple literal values. As you see, dmd does not consider an associative array to be plain simple literal, even when it obviously is; but a sequential array, yes. A side note: constant struct data can be directly defined at the module top-level, at least in simple cases. But (for any reason), dmd in fact does not create a single constant value that will be used everywhere you write its name. Instead, it re-creates the constant value at each place you write it. Aside the possible cost (?), this can create bugs if you count on it be unique: struct S { int i; } enum S* ps0 = (S(0)), ps1 = (S(1)); unittest { S* ps; if (true) ps = ps0; else ps= ps1; assert (*ps == *ps0); // indeed //~ assert (ps == ps0); // fail !!! writefln(%s != %s, ps,ps0); // BFC95FE4 != BFC95FF0 } The trick of using the module's static this clause also solves this issue. Denis -- _ vita es estrany spir.wikidot.com
Re: Ranges
On 03/13/2011 01:05 AM, Jonathan M Davis wrote: If you were to try and iterate over a char[] by char, then you would be looking at code units rather than code points which is _rarely_ what you want. If you're dealing with anything other than pure ASCII, you _will_ have bugs if you do that. You're supposed to use dchar with foreach and character arrays. That way, each value you process is a valid character. Ranges do the same, only you don't give them an iteration type, so they're _always_ iterating over dchar. Side-note: you can be sure the source is pure ASCII if, and only if, it is mechanically produced. (As soon as an end-user touches it, it may hold anything, since OSes and apps offer users means to introduces characters which are not on their keyboards). This can also easily be checked in utf-8 (which has been designed for that): all ASCII chars are coded using the same code as in ASCII, thus all codes should be 128. Denis -- _ vita es estrany spir.wikidot.com
Re: foo.bar !in baz not allowed?
On 03/13/2011 07:58 PM, Magnus Lie Hetland wrote: For some reason, it seems like expressions of the form foo.bar !in baz aren't allowed. I suspect this is a grammar/parser problem -- the bang is interpreted as a template argument operator, rather than a negation operator, and there's really no need to make that interpretation when it is immediately followed by in. This suspicion is strengthened by the fact that bar !in baz is fine, as is (foo.bar) !in baz. Should I file this as a bug? Small sample program: struct Foo { uint bar; } struct Baz { bool opIn_r(uint e) { return false; } } void main() { Baz baz; Foo foo; auto res = (foo.bar) !in baz; res = !(foo.bar in baz); // res = foo.bar !in baz; // Not OK... uint frozz; res = frozz !in baz; } Would be nice to copy the error, wouldn't it? template argument expected following ! Anyway, this is definitely a bug in my opinion. Denis -- _ vita es estrany spir.wikidot.com
Re: Commenting out a print slows my code?
On 03/10/2011 01:44 AM, Charles McAnany wrote: Hi, all. I'm in college, taking a freshman-level CS class. (I'm actually a senior chemist with free time.) Anyhoo, the warm-up assignment was Hardy Taxi problem, phrased like this: [Exposition removed.] 1729 is the smallest number such that for (a!=b!=c!=d)0, there exists a combination of a, b, c, and d where a^3+b^3 = 1729 = c^3+d^3. The task was to find all other numbers with this property less than 25,000. The code is basically for (int iters = 1; iters= 25_000; iters++){ if(isTaxiNumber(iters)){ writefln(%s is a taxi number, iters); } } (There's also a StopWatch timing things, and isTaxiNumber returns a struct, not a bool. See attached code.) This code runs in about 0.09 seconds. If I comment out the writefln, it takes 0.11 seconds. (These are collected from about 20 runs of each. Times are very consistent.) Any ideas why commenting out the write makes things slower? No idea. But more idiomatic D would rather b: foreach (n ; 1..25000) {...} Also I don't understand why your loop var is called 'iters'. Finally, the attachment is not readible by me: see below. Denis begin 644 taxi.d M:6UP;W)T('-T9YD871E=EM93L@+R\@9F]R('1H92!3=]P5V%T8V@@W1R M=6-T+B`-FEM]R=!S=0NW1R:6YG.R`O+V9OB!T:4@9F]R;6%T*DN M(`T*:6UP;W)T('-T9YS=1I;SL@+R]PFEN=EN9RX@#0HO+R\@02!S=')U M8W0@=AA=!R97!R97-E;G1S($@8V%B+B!)=!D;V5S;B=T(1O('1H92!C M:5C:VEN9R!T:%T('1H92!O;F4@:6X@=AE(%SVEG;FUE;G0@9]ERP@ M=AO=6=H+B`-G-TG5C=!T87AI0V%BPT*6EN=!T87AI3G5M8F5R.PT* M6EN=!A+!B+!C+!D.PD-@ES=')I;F@=]3=')I;FH*7L-@D)F5T M=7)N(9OFUA=@B8V%R(5S(#T@6R5S(5S(5S(5S72(L=%X:4YU;6)E MBP@82P@8BP@8RP@9D[#0H)?0T*?0T*#0HO*BH-BH@4')O9W)A;2!T:%T M(UE87-UF5S('1H92!T:6UE(ET('1A:V5S('1O(1E=5R;6EN92!T:4@ M=%X:2!N=6UB97)S(QEW,@=AA;B`R-3`P,X@#0HJ($%U=AOCH@0VAA MFQER!-8T%N86YY#0HJ#0HJ+PT*=F]I9!M86EN*E[#0H)4W1O%=A=-H M('-W.PT*7-W+G-T87)T.PT*69OB`H:6YT(ET97)S(#T@,#L@:71EG,\ M(#(U,#`P.R!I=5RRLK*7L-@D)=%X:4-A8B!C86))1`](ES5%X:2AI M=5RRD[#0H)6EF*-A8DE$+F,@(3T@,E[#0H)0EWFET96QN*-A8DE$ M*3L-@D)?0T*7T-@ES=RYS=]P.PT*51I8VMS('1I;65486ME;B`]('-W M+G!E96L[#0H)=W)I=5F;XH(B5S7'0ER(L,C4P,#`L=EM951A:V5N+G1O M4V5C;VYDR%F;]A=D[#0H)WNF5S970[#0H-GT-@T*+RHJ#0HJ(ES M5%X:2!D971EFUI;F5S(EF(%N(EN=5G97(@%SV5D('1O(ET(ES M($@=%X:2!N=6UB97(L('1H870@:7,L('1H97)E(5X:7-TPT**B!A;B!A M+!B+!C+!A;F0@9P@;F]N92!O9B!T:5M('1H92!S86UE+!S=6-H('1H M870@#0HJ(%,RMB7C,@/2!N(#UC7C,@*V1,RX@#0HJ(')E='5R;G,Z(`T* M*B!A('1AE#86(@W1R=6-T+!W:71H($L((L(,L(%N9!D(EF(9O M=6YD+B!I9B!O;FQY(]N92!S;VQU=EO;B!T;R!X7C,K5XS('=AR!F;W5N M9P@#0HJ(,@86YD(0@=VEL;!B92!Z97)O+B!)9B!N;VYE('=EF4@9F]U M;F0L('1H96X@82!A;F0@8B!W:6QL()E('IEF\@87,@=V5L;X@#0HJ('!A MF%M971EG,Z(`T**B!N(ES(%N(EN=5G97(@=AA=!IR!T;R!B92!C M:5C:V5D(9OB!T87AI(YU;6)EBUN97-S+B`-BHO#0IT87AI0V%B(ES M5%X:2AI;G0@;BE[#0H):6YT(QI;6ET(#T@8W5B95)O;W1;]OBAN*2`M M(#$[#0H):6YT(AI=',@/2`P.R`-@EI;G1;72!R97-U;'1S(#T@6S`L,PP M+#!=.PT*69OB`H:6YT(D@/2`P.R!I(#P@;EM:70[(DK*RD@PT*0EI M;G0@F5S(#T@;B`M(DJ:2II.PT*0ED;W5B;4@8W5B95)O;W0@/2!R97- M7B@Q+S,N,D[#0H)6EN=!N96%R97-T26YT(#T@8V%S=AI;G0I(AC=6)E M4F]O=`K(#`N-2D[#0H)61O=6)L92!D:69F(#T@*-U8F52;V]T(T@;F5A MF5S=$EN=D@*B`H8W5B95)O;W0@+2!N96%R97-T26YT*3L-@D):68@*1I M9F8@/`Q92TQ,D@PT*0D):68@*AI=',@/`R(8F(')EW5L='-;,5T@ M(3T@:2D@PT*0D)7)EW5L='-;:ETR`J(#)=(#T@:3L-@D)0ER97-U M;'1S6VAI=',@*B`R(L@,5T@/2!N96%R97-T26YT.PT*0D)?0T*0D):ET MRLK.PT*0E]#0H)?0T*7)E='5R;B!T87AI0V%B*XLF5S=6QTULP72QR M97-U;'1S6S%=+')EW5L='-;,ETLF5S=6QTULS72D[#0I]#0H-B\O+R!F M:6YDR!T:4@;%R9V5S=!I;G1E9V5R('@@W5C:!T:%T('A,R`\(X@ M#0II;G0@8W5B95)O;W1;]OBAI;G0@;BE[#0H)9]U8FQE(-U8F52;V]T M(#T@;B!7B`H,2\S+C`I.PT*6EN=!CD9L(#T@8V%S=AI;G0I(-U8F52 6;V]T.PT*7)E='5R;B!CD9L.PT*?0`` ` end -- _ vita es estrany spir.wikidot.com
Re: Best way in D2 to rotate a ubyte[4] array
On 03/10/2011 12:55 AM, Jonathan M Davis wrote: I don't know of anything more efficient than: ubyte[4] bytes = [1,2,3,4]; bytes = bytes[$-1] ~ bytes[0..$-1]; // Rotate left I'm stunned that this works. I'd even consider reporting it as a bug. You're concatenating a ubyte[] ont a ubyte... This works for other arrays as well. dmd understands. Denis -- _ vita es estrany spir.wikidot.com
Re: I seem to be able to crash writefln
On 03/10/2011 12:19 AM, Joel Christensen wrote: This is on Windows 7. Using a def file to stop the terminal window coming up. win.def EXETYPE NT SUBSYSTEM WINDOWS bug.d import std.stdio; import std.string; void main() { auto f = File( z.txt, w ); scope( exit ) f.close; string foo = bar; foreach( n; 0 .. 10 ) { writefln( %s, foo ); f.write( format( count duck-u-lar: %s\n, n ) ); } } output (from in z.txt): count duck-u-lar: 0 What do you mean, crashing writefln? What do you get on the terminal? About the file, there seems to be a bug --but unrelated to writefln. The file is closed, I guess because of scope(exit), before the output stream is flushed. If this is the right interpretation, then there is a precedence issue; scope's action should not be performed before the func's own action is actually completed. Denis -- _ vita es estrany spir.wikidot.com
Re: using enums as key in associative array
On 03/08/2011 09:26 AM, Wilfried Kirschenmann wrote: enum deviceType {cpu, gpu} auto execDeviceSuffix = [deviceType.cpu:.cpu, deviceType.gpu:.gpu]; The way to get what you want to work in this case is to use a module constructor. So, you'd do something like this: string[deviceType] execDeviceSuffix; static this() { execDeviceSuffix[deviceType.cpu] = cpu; execDeviceSuffix[deviceType.gpu] = gpu; } The module constructor will be run before main does, so execDeviceSuffix will be properly filled in by then. I didn't get to the point where module constructors are introduced in Andrei's book yet. I really like this idea ! I found a similar workaround which used an useless class so that I could use the static constructor but this is even better ! This is a very nice feature, yes. But I personly see it as a workaround for the limitation that dmd, apparently, is not able to correctly evaluate many kinds of assignment expressions. And it's ugly when one has hordes of definitions -- the module is (mainly) a piece of data description: all symbols must first be declared /outside/, then redefined /inside/ static this(). Else, D would be a great data-definition language, in addition to its other qualities, thank to its literals for everything (and conversely its standard to!string for everything, which needs improvements). Think a static Lua. Denis -- _ vita es estrany spir.wikidot.com
Re: using enums as key in associative array
On 03/08/2011 03:48 PM, Jonathan M Davis wrote: I really don't understand your problem with module constructors. They're fantastic. I may be wrong, but I think this point of view is a where I can from statement. C's char* are fantastic when you have never used a PL with builtin strings. There are languages in which you don't need to list twice everything just to have them available at import time. // data definition X foo; Y bar; Z baz; ... static this { foo = ...; bar = ...; baz = ...; ... } Denis -- _ vita es estrany spir.wikidot.com
Re: Templated struct doesn't need the parameterized type in return type definitions?
On 03/08/2011 06:20 PM, Steven Schveighoffer wrote: On Tue, 08 Mar 2011 12:06:08 -0500, Andrej Mitrovic n...@none.none wrote: import std.stdio; import std.traits; import std.exception; struct CheckedInt(N) if (isIntegral!N) { private N value; ref CheckedInt opUnary(string op)() if (op == ++) { enforce(value != value.max); ++value; return this; } this(N _value) { value = _value; } } I didn't know you could define a return type of a templated struct without defining the type it is parameterized on. I mean this line: ref CheckedInt opUnary(string op)() if (op == ++) I thought for sure I always had to write the parameterized type like so: ref CheckedInt!(N) opUnary(string op)() if (op == ++) So I guess this really isn't a question but more of a oh, I didn't know you could do that. In fact I rarely see this kind of code in Phobos, most of the time the parameterized type is specified in these types of cases. Is this feature described somewhere, because I must have missed it if it is? It is described, but not directly. Look on this page: http://www.digitalmars.com/d/2.0/template.html From there we have these two descriptions: If a template has exactly one member in it, and the name of that member is the same as the template name, that member is assumed to be referred to in a template instantiation: template Foo(T) { T Foo; // declare variable Foo of type T } void test() { Foo!(int) = 6; // instead of Foo!(int).Foo } If a template declares exactly one member, and that member is a class with the same name as the template: template Bar(T) { class Bar { T member; } } then the semantic equivalent, called a ClassTemplateDeclaration can be written as: class Bar(T) { T member; } Also note that structs have the same description. So if you think about it, your code is equivalent to: template CheckedInt(N) if(isIntegral!N) { struct CheckedInt { ... } } If you look at it this way, it makes complete sense that within the struct that's within the template, the struct can refer to itself without the specific instantiation parameters. I think this should really be laid out properly in the docs. I discovered this trick while writing dcollections by accident and thought it so awesome that I changed all my code which self-returned (quite a bit). -Steve I don't share your enthusiasm, Steven, for this feature (which I did not know). In fact, I tend to consider it a mis-feature. Yet another syntactic special-case for special cases in the language. In this case, there are even 3 ways to write the same thing: CheckedInt CheckedInt!N CheckedInt!(N) And note these variants are low-level ones, morphological rather than syntactic properly speaking. Denis -- _ vita es estrany spir.wikidot.com
Re: Empty field doesn't exist for arrays, right?
On 03/08/2011 06:56 PM, Andrej Mitrovic wrote: module test; struct MyArray(T) { private T[] data; bool opCast(T)() if (is(T == bool)) { return !data.empty; } } void main() { auto foo = MyArray!(int)(); auto state = foo ? true : false; } test.d(13): Error: undefined identifier module test.empty test.d(20): Error: template instance test.MyArray!(int).MyArray.opCast!(bool) error instantiating This is straight from the book. Did .empty exist for arrays before? Perhaps this was just a typo in the book, and it was supposed to be: bool opCast(T)() if (is(T == bool)) { return data.length != 0; } Also, that error message *really* needs to improve. It's not module 'test' which is missing the method, it's 'data'. This is one of the most confusing error messages that I know of and it pops up all the time. Agreed. But do you understand why dmd throws that error, anyway? I'm not sure, the following may be plain shit. My guess is, since UFCS (universal function call syntax) exists for arrays, when dmd decodes data.empty and does not find any empty slot on 'data' or on its type, it tries rewriting it into empty(data). Right? then, to execute that, it looks for an empty func in the module, which it does not find... thus the message. Note that if one of your imports happened to hold an empty func, either it would execute by plain chance, or you would get a type error! HTH Denis -- _ vita es estrany spir.wikidot.com
Re: Static Associative Array
On 03/07/2011 03:22 AM, Peter Lundgren wrote: == Quote from Jonathan M Davis (jmdavisp...@gmx.com)'s article On Sunday 06 March 2011 14:05:04 Peter Lundgren wrote: Can you define an associative array in a way that can be evaluated at compile time like you can with non-associative arrays? I'm pretty sure not. I think that it's currently suffering the same fate as stuff like classes and is not yet able to be CTFEed. Some day... - Jonathan M Davis If not, then what is the D way to initialize a static field of a struct or class a la Java's static initializer blocks? I don't mind constructing the associative array at run-time if I have to, but I can't afford to do it more than the once needed. Use the module's static this () {...} clause: int[string] aa; static this () { aa = [a:1, b:2, c:3]; } unittest { foreach (k,v ; aa) writefln(%s -- %s, k,v); } Note: you can have as many such ckauses as you like. Denis -- _ vita es estrany spir.wikidot.com
Re: Template type parameters with their own type parameters
On 03/05/2011 04:02 AM, Peter Lundgren wrote: I have a function that I think should look something like this: MyStruct!T myFunc(T)(MyStruct!T x, ...) { ... return MyStruct!T(...); } and the closest I can get to is: T myFunc(T)(T x, ...) { ... return T(...); } which works, but doesn't make clear the intended use and gets in the way of overloading. How can I express the intent of the first version. Maybe I do not exactly understand your problem; anyway, the following runs fine by me: struct S (T) { T v; } S!T inc (T) (S!T s) { return S!T(s.v + 1); } unittest { auto s1 = S!int(1); auto s2 = inc(s1); assert ( s2.v == 2 ); } Could you provide (1) context (2) example (3) errors? Denis -- _ vita es estrany spir.wikidot.com
Re: in/out with -release
On 03/05/2011 01:58 PM, bearophile wrote: Jonathan M Davis: Asserts are for debugging, testing, and verifying code when developing, not for code which is released. If you take a look at the dmd compiler, it's released with asserts in, and they give all those nice error messages I put in Bugzilla :-) lol! I have a similar problem in designing the implementation of a toy language: the issue is that users of the runtime are, for instance, lib developpers, which own users are developpers in the source language beeing implemented, for their own final users... This makes it rather abstract to think at what is, or should be, the realisation of an error spit by the runtime. It cannot be a normal error from the implementation language, and also not an error of the source language. I had to write my own // error system. Denis -- _ vita es estrany spir.wikidot.com
Re: Overriding in operator
On 03/04/2011 05:01 PM, Magnus Lie Hetland wrote: I'm writing a collection with functionality for membership checking. I thought it would be nice to use the in operator. In the docs for std.collections I surmise that this is the standard way to go. From the source code, I see there's no special opIn, but that it can be done with the more general... bool opBinary(string op)(T k) if (op == in) { ... } Here T is, of course, a compile-time argument of the surrounding struct or class. So ... this is used in the the Phobos source in the DMD 2.052 distro (if I'm not mistaken), but I can't get dmd 2.052 to accept it? I keep getting the error message Error: rvalue of in expression must be an associative array, not Foo!(uint). I guess either that this is a recent feature -- I didn't see it mentioned in Andrei's book -- and that my Phobos source is too recent for my dmd ... or that I'm doing something wrong elsewhere in my code, preventing the operator overloading to take force. Suggestions/solutions?-) Didn't even know 'in' can be defined with opBinary... I use opIn_r ('r' for right side, since the container stand on the right of the expression) everywhere, and it works fine. Denis -- _ vita es estrany spir.wikidot.com
Re: Overriding iteration
On 03/04/2011 05:43 PM, Steven Schveighoffer wrote: On Fri, 04 Mar 2011 11:29:08 -0500, Magnus Lie Hetland mag...@hetland.org wrote: From what I understand, when you override iteration, you can either implement the basic range primitives, permitting foreach to destructively iterate over your object, or you can implement a custom method that's called, and that must perform the iteration. The destructiveness of the first option can, of course, be mitigated if you use a struct rather than a class, and make sure that anything that would be destroyed by popFront() is copied. What I'm wondering is whether there is a way to do what Python does -- to construct/return an iterator (or, in this case, a range) that is used during the iteration, rather than the object itself? That's exactly how to do it. I'm thinking about when you iterate directly over the object here. As far as I can see, the solution used in the std.container is to use opSlice() for this functionality. In other words, in order to iterate over container foo, you need to use foreach(e; foo[])? Is there no way to get this functionality directly (i.e., for foreach(e; foo))? I believe someone has filed a bug for this, because TDPL has said this should be possible. But with the current compiler, you can use opApply to achieve that behavior. opApply should work but it is supposed to be slower. Defining range primitives directly on the object/container cannot work as of now, unfortunately, because of a pair of bugs (conflicts in formatValue template definitions between struct/class on one hand and ranges on the other). Denis -- _ vita es estrany spir.wikidot.com
Re: Overriding iteration
On 03/04/2011 07:06 PM, Jonathan M Davis wrote: On Friday, March 04, 2011 09:13:34 spir wrote: On 03/04/2011 05:43 PM, Steven Schveighoffer wrote: On Fri, 04 Mar 2011 11:29:08 -0500, Magnus Lie Hetlandmag...@hetland.org wrote: From what I understand, when you override iteration, you can either implement the basic range primitives, permitting foreach to destructively iterate over your object, or you can implement a custom method that's called, and that must perform the iteration. The destructiveness of the first option can, of course, be mitigated if you use a struct rather than a class, and make sure that anything that would be destroyed by popFront() is copied. What I'm wondering is whether there is a way to do what Python does -- to construct/return an iterator (or, in this case, a range) that is used during the iteration, rather than the object itself? That's exactly how to do it. I'm thinking about when you iterate directly over the object here. As far as I can see, the solution used in the std.container is to use opSlice() for this functionality. In other words, in order to iterate over container foo, you need to use foreach(e; foo[])? Is there no way to get this functionality directly (i.e., for foreach(e; foo))? I believe someone has filed a bug for this, because TDPL has said this should be possible. But with the current compiler, you can use opApply to achieve that behavior. opApply should work but it is supposed to be slower. Defining range primitives directly on the object/container cannot work as of now, unfortunately, because of a pair of bugs (conflicts in formatValue template definitions between struct/class on one hand and ranges on the other). You don't _want_ range primitives directly on the container. That would mean that everything in your container goes away when you process it. Every popFront() call would be removing an element from your container. So, for insteance, you try and call find() on your container and everything before what you were looking isn't in the container anymore - and if it isn't there at all, you have an empty container. You _want_ to have a separate type which is a slice of our container and has the range primitives. Certainly, as long as, on an array-like container, you implement popFront as this = this[1..$]; or this.elements = this.elements[1..$]; then, yes, iterating on it shrinks it. (Note this works only on array-like containers; how would you shrink a tree?) But I prefere using a private index an have popFront do: ++ this.index; This is a more general iteration mechanism solution, based on current state of the object beeing iterated on. For many kinds of sequences, you needs state anyway. How else iterate over the sequence of multiples of 3, or squares of natural numbers? Now, it could very well be that foreach(v; container) should be calling opSlice on the container, allowing you to feed the container to foreach directly instead of having to slice it yourself foreach(v; container[]) but that's just syntactic sugar. You don't want to actually treat your container like a range. Ranges should be slices of containers, not containers themselves. I agree slices should be an alternate iteration mechanism (as said in TDPL). But one cannot slice a tree that easily :-) (where's my chain saw?) Denis -- _ vita es estrany spir.wikidot.com
Re: Parameterized Structs
On 03/03/2011 12:25 PM, bearophile wrote: Ali Çehreli: quote Template value parameter types can be any type which can be statically initialized at compile time, and the value argument can be any expression which can be evaluated at compile time. This includes integers, floating point types, and strings. /quote I have needed arrays as template specialization arguments few times (I have used alias to solve the problem). Allowing strings but not arrays is one limitation that I don't understand. Bye, bearophile That may be because strings are immutable? Denis -- _ vita es estrany spir.wikidot.com
Re: Parameterized Structs
On 03/03/2011 05:56 AM, Peter Lundgren wrote: Where can I go to learn about parameterized structs? I can't seem to find any literature on the subject. In particular, what are you allowed to use as a parameter? I would like to define a struct like so: struct MyStruct(T, T[] a) { ... } but I receive the following error: Error: arithmetic/string type expected for value-parameter, not T[] Are arrays not allowed? Finally managed to do it, I guess :-) bool[E] set (E : E[]) (E[] elements) { bool[E] set; foreach (element ; elements) set[element] = true; return set; } struct String (C : C[], alias characters) { alias typeof(characters) S; //~ alias ElementType!S C; // BUG! returns dchar bool[C] klass = null; private C[] s; this (S s) { this.klass = set!S(characters); this.def(s); } void def (S s = null) { if (s.length == 0) { this.s = s; return; } foreach (ch ; s) { if (ch !in this.klass) { auto message = format( '%s' not in allowed class of characters , ch); throw new Exception(message); } } this.s = s; } string toString () { return format(String!(%s,\%s\)(\%s\), S.stringof, characters, this.s); } } unittest { auto s = String!(string, abcde)(); writeln(s); s.def(eca); writeln(s); s = String!(string, abcde)(ace); writeln(s); s = String!(string, abcde)(fgh);// -- error writeln(s); } Some notes: * set is here to speed up character lookup among allowed klass (else, O(N) in array). * C: C[] in struct template is redondant, since C[] is typeof(characters). It is only needed to declare the set 'klass', because of a bug: ElementType!string returns dchar!!! Thus, it is would not be possible, I guess, to declare klass's type in the struct definition. * You must pass an init string (even if ) to call this() and construct klass. Because of another bug: there cannot be parameter-less constructors for structs. Also, set cannot be defined on toplevel of the struct def auto klass = set!S(characters); because it's not a constant according to dmd. (It is, in fact). Thus, I guess we must construct it inside this(). Denis -- _ vita es estrany spir.wikidot.com
Re: comparing pointers passed to and returned from funcs
On 03/02/2011 02:24 PM, Steven Schveighoffer wrote: On Tue, 01 Mar 2011 18:11:00 -0500, bearophile bearophileh...@lycos.com wrote: http://d.puremagic.com/issues/show_bug.cgi?id=5678 I think there is a general bug where any time the compiler uses an enum, it simply replaces the expression declared for the enum. So basically enum TRUE = new DElement(true); void main() { auto delem1 = TRUE; auto delem2 = TRUE; assert(delem1 is delem2); // fails } gets morphed into this: void main() { auto delem1 = new Delement(true); auto delem2 = new Delement(true); assert(delem1 is delem2); // fails } Obviously this works great when the enum is a value type or a string literal (which is created at compile time). However, it is not so great for things like AAs, array literals, objects, or structs. I think there are a few of these bugs in bugzilla, and there should be at least a tracker, and if not, they should all be combined. This is a serious problem in D, and really creates havoc (both performance-wise and semantically). I don't anticipate there is an easy fix. Essentially, I'd say enum is completely useless except for builtin types and strings. Thank you Steven Bearophile. This solves my problem. I first did not get Bearophile's answer about run/compile-time constants (I mean enums). I thought the time when they are created is irrelevant, isn't it? Anyway, placing the constant defs inside a module's static this () {...} block does what I mean. It does, in fact, ensure *unicity*. But I don't really understand the relation with Steven's explanation above: why/how does the fact that a constant's def is inside static this() prevent the compiler to rewrite it like shown above? Also, I basically don't understand why dmd does that anyway: it's obviously un-ecological ;-) Denis -- _ vita es estrany spir.wikidot.com
Re: Mixins: to!string cannot be interpreted at compile time
On 03/01/2011 07:58 AM, Peter Lundgren wrote: I'm trying to use mixins to generate an array of numbers that are coprime to a statically known value. I've tried the following, but I receive the error: Error: to(i) ~ , cannot be interpreted at compile time string makePossibleAValues(string name, byte m) { string result = immutable byte[] ~name~ = [; foreach (i; 0 .. m) { if (coprime(i, m)) { result ~= to!string(i) ~ , ; } } return result ~ ];; } bool coprime(ulong a, ulong b) { return gcd(a, b) == 1; } ulong gcd(ulong a, ulong b) { while (b) { auto t = b; b = a % b; a = t; } return a; } mixin(makePossibleAValues(aValues, 26)); makePossibleAValues(aValues, 26) produces the correct result, immutable byte[] aValues = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25, ];, at runtime and I know to!string can be used in mixins. Any idea as to why this particular code is having trouble with to!string? Not sure because I never use string mixins, but I guess the answer is precisely what the error says. Why don't you believe it? makePossibleAValues() obviously returns a runtime value, so mixin() cannot evaluate it, I guess. Denis -- _ vita es estrany spir.wikidot.com
comparing pointers passed to and returned from funcs
Hello, It seems to be the kind of stupid issue that will make you laugh about me. But I cannot grasp and want to move forward anyway; so, let us be bold and take the risk ;-) I'm modeling a little dynamic language. Elements (values, objects) are pointers to structs (actually tagged unions) allocated on the heap. I have a problem in passing and returning those pointers to and from primitive procedures. Precisely, unlike in D, Logical (boolean) operations only accept Logical elements true/false (called TRUE/FALSE on implementation side for obvious reason): enum TRUE = new DElement(true); enum FALSE = new DElement(false); So, I thought I could write those operations by comparing pointers directly, eg: Element not (Element operand) { // checks type operand.checkLogical() return (operand == TRUE) ? FALSE : TRUE; } ... assert ( not(TRUE) == FALSE ); This fails! It even fails doubly... When I call not(TRUE), TRUE (the pointer) inside the func is not equal to the global constant. Thus, not always returns FALSE. And in fact this is also wrong, because I have the same problem on the return value as well: the FALSE returned is not equal to the global FALSE. But the pointed structs are ok. Each one holds a D boolean of the correct value (a member called 'logical'). Thus, the following succeeds: Element not (Element operand) { // checks type returns the 'logical' member auto log = operand.checkLogical(); return (log) ? FALSE : TRUE; } ... assert ( not(TRUE).logical == false ); Here, I operate on the structs instead of on the pointers, both to perform the operation and in the assert. What I understand is: all happens like if D would copy the pointed structs on parameter passing and on return. I thought D would only copy the pointers (in both directions), which would let me compare said pointers directly. What do I miss? It is not a serious problem since the workaround is easy and not very costly. But I wish to understand why I cannot operate on constant 'identity'. As said above, this must a trivial issue I simply cannot guess... Thank you, Denis -- _ vita es estrany spir.wikidot.com
type set
Hello, I have a template condition that looks like this: T check (T) () if ( is(T == DLogical) || is(T == DNumber) || is(T == DText) || is(T == DList) || is(T == DUnit) ) { ... } Is there a way to factor out such an expression using a kind of type set? If only for cleaning the code; but also because such a set may get long. T check (T) () if (is (T in validTypeSet)) { ... } Denis -- _ vita es estrany spir.wikidot.com
Re: type set
On 02/28/2011 02:32 PM, Steven Schveighoffer wrote: On Mon, 28 Feb 2011 08:22:58 -0500, spir denis.s...@gmail.com wrote: Hello, I have a template condition that looks like this: T check (T) () if ( is(T == DLogical) || is(T == DNumber) || is(T == DText) || is(T == DList) || is(T == DUnit) ) { ... } Is there a way to factor out such an expression using a kind of type set? If only for cleaning the code; but also because such a set may get long. T check (T) () if (is (T in validTypeSet)) { ... } This should probably work: template isOneOf(X, T...) { static if(!T.length) enum bool isOneOf = false; else static if(is(X == T[0])) enum bool isOneOf = true; else enum bool isOneOf = isOneOf!(X, T[1..$]); } T check(T) () if(isOneOf!(T, DLogical, DNumber, DText, TList, DUnit)) { ... } Not sure if this exists in std.traits or not, but that's where I'd look. -Steve Waow, great anyway! Didn't even know one can write variadic type/template param lists. By the way, the block of the function is a series of static if-s, one for each allowed type. Is there any static switch? Or any other nicer way to write it than: T check (T) () if ( is(T == DLogical) || is(T == DNumber) || is(T == DText) || is(T == DList) || is(T == DUnit) ) { TypeCode type; static if (is(T == DLogical)) if (this.code == LOGICAL) return this.logical; else type == LOGICAL; static if (is(T == DNumber)) if (this.code == NUMBER) return this.number; else type == NUMBER; static if (is(T == DText)) if (this.code == TEXT) return this.text; else type == TEXT; static if (is(T == DList)) if (this.code == LOGICAL) return this.list; else type == LOGICAL; static if (is(T == DUnit)) if (this.code == UNIT) return this.unit; else type == UNIT; // type error throw new TypeError(type, this); } This func type-checks and returns the current value of a tagged union. I would be very pleased with a mapping from types to type codes (tags). I can't do without the type param, I guess, because it's the return value's type... or can I? But the discriminating code of the union cannot be the type itself (*), instead it's a plain code. I thought at using TypeInfo-s as codes, which can then be mapped from types using typeid(). But according to sizeof, this makes the code weigh 1 word instead of one byte. Denis (*) Indeed. Else it would be a template generating N distinct types, which is precisely the opposite of what a union provides. -- _ vita es estrany spir.wikidot.com
Re: type set
On 02/28/2011 03:50 PM, Steven Schveighoffer wrote: On Mon, 28 Feb 2011 09:27:36 -0500, spir denis.s...@gmail.com wrote: By the way, the block of the function is a series of static if-s, one for each allowed type. Is there any static switch? Or any other nicer way to write it than: T check (T) () if ( is(T == DLogical) || is(T == DNumber) || is(T == DText) || is(T == DList) || is(T == DUnit) ) { TypeCode type; static if (is(T == DLogical)) if (this.code == LOGICAL) return this.logical; else type == LOGICAL; static if (is(T == DNumber)) if (this.code == NUMBER) return this.number; else type == NUMBER; static if (is(T == DText)) if (this.code == TEXT) return this.text; else type == TEXT; static if (is(T == DList)) if (this.code == LOGICAL) return this.list; else type == LOGICAL; static if (is(T == DUnit)) if (this.code == UNIT) return this.unit; else type == UNIT; // type error throw new TypeError(type, this); } There is a final switch, but I don't know if that works on types. You may be stuck with static if. When doing things like this, I'd recommend using a mapping template. For example: private template typeCode(T) { static if(is(T == DLogical)) enum typeCode = LOGICAL; else static if(is(T == DNumber)) enum typeCode = NUMBER; ... else static assert(0); } then you almost can use this to generate the right code: if(this.code == typeCode!T) { static if(is(T == DUnit)) return this.unit; else static if(... } That's it! This actually builds an the equivalent of an AA which keys are types. I was looking for such a functionality for a while already. I am in fact *contantly* annoyed in D by the fact there are no types (I mean at runtime). On the other hand, this forces me looking for workaround, to express my models in distorted ways, which lets me discover unusual features and idioms in D's semantic dark corners ;-) You can probably replace the inner static if with a mixin, if you name your union members properly (i.e. if you can generate the name of the union member based on its type name or code, like DUnit dunit_val). Yeah, I could, as shown by the code above: lang type Xyz -- code XYZ -- D impl type DXyz -- union member xyz. Could not be more regular, I guess ;-) But as you may know, I 100% against string mixins. I prefere keeping the mapping explicite without string sorcery. (Precisely, in the toy lang I'm starting to realise, one could do that trivially by manipulating the AST, without any dark magic. But this is another story...) But at least it gives you an idea of how this can be done efficiently. Plus avoiding large repetitive static ifs can save you from tedious copy-pasting bugs like the one in your DList branch ;) Good catch, Steve! And thank you again. PS: Is it your email client that eats whitespace (see my code above)? Denis -- _ vita es estrany spir.wikidot.com
Re: Multiple assignment
On 02/26/2011 01:56 AM, bearophile wrote: Is this program showing a bug in multiple assignments (DMD 2.052)? void main() { int i; int[2] x; i, x[i] = 1; assert(x == [1, 0]); // OK int j; int[2] y; y[j], j = 1; assert(y == [0, 0]); // Not OK } At the end of the program I expect y to be [1,0] instead of [0,0]. I'm far to be a C expert, but that looks like very normal C semantics, ain't it? with all its stupidity, indeed... I would enjoy an error in both cases. (not enough rvalues) Denis -- _ vita es estrany spir.wikidot.com
Re: Multiple assignment
On 02/26/2011 04:26 AM, Steven Schveighoffer wrote: Let me fix that for you: func(j++, y[j]) That should be illegal: a statement used as expression, but keeping it's effect anyway, and not the least kind of, namely an assignment, meaning a change of the program state. Denis -- _ vita es estrany spir.wikidot.com
Re: How do you test pre-/post-conditions and invariants?
On 02/26/2011 12:24 PM, Magnus Lie Hetland wrote: However, I could always add a call to my unit test, run it, and see it crash -- and then comment it out. Doesn't seem like the prettiest way to handle things, but it's OK, I guess together with the idea of making the contracts super-simple (and to test any functionality they use separately). With named unittests, you could also have one of them check failure cases, and just comment out its call. Denis -- _ vita es estrany spir.wikidot.com
override to!string
Hello, Imagine I have the following custom type: alias float[] Numbers; Is it possible to override to!string for Numbers so that it outputs eg like; (1.1 2.2 3.3) ? I can indeed override/specialise toImpl or formatValue for the custom type, but those overrides are simply ignored (tested). Denis -- _ vita es estrany spir.wikidot.com
implicite deref on array element access? (indexing)
Hello, I thought it worked, just like implicite deref on (struct, class) member access. But I cannot have it work: auto a = [1,2,3]; auto pa = a; writeln((*pa)[2]); // ok writeln(pa[2]); // segfault Denis -- _ vita es estrany spir.wikidot.com
Re: How do you test pre-/post-conditions and invariants?
On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote: Or, more generally, how do you test asserts (which is what I'm using in my preconditions etc.)? As far as I can see, collectException() won't collect errors, which is what assert() throws -- so what's the standard way of writing unit tests for preconditions that use assert? (I.e., test that they will, in fact, throw when you break them.) See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html. Denis -- _ vita es estrany spir.wikidot.com
Re: implicite deref on array element access? (indexing)
On 02/25/2011 04:43 PM, Steven Schveighoffer wrote: On Fri, 25 Feb 2011 10:15:52 -0500, spir denis.s...@gmail.com wrote: Hello, I thought it worked, just like implicite deref on (struct, class) member access. But I cannot have it work: auto a = [1,2,3]; auto pa = a; writeln((*pa)[2]); // ok writeln(pa[2]); // segfault Because indexing a pointer like ptr[n] is the equivalent of *(ptr + n). This is how it is in C. Fun fact, you can avoid array bounds checks (if you know the index is valid) by doing arr.ptr[n] All right! This is what I did not get. Thank you, Steve. Too bad. Anyway, in the meanwhile I have opted for another approach. (FWIW, in Oberon implicite deref works on array indexing just like on struct [record] member access.) Denis -- _ vita es estrany spir.wikidot.com