Performance of tables slower than built in?
I am trying to create some fast sin, sinc, and exponential routines to speed up some code by using tables... but it seems it's slower than the function itself?!? The code below uses matplotlibd but is not necessary. The timing code is lower. Ideally I'd like to have quadratic interpolation and all that but if the code is going to be slower and less accurate then what is the point? Surely I'm doing something wrong? I wasn't able to test this with LDC because it's giving me linker errors for some reason. I'm also curious as to what D is using internally in the first place. The generation uses a quarter sin since the waveform is symmetric. This does slow down the code a little but I can't imagine the few ops it uses to do this is more costly than whatever is used for computing sin. import std.math; import std.range; import std.random; import std.algorithm; import plt = matplotlibd.pyplot; import std.stdio, core.stdc.stdlib; __gshared double[] QuarterSinTab; auto GenQuarterSinTab(int res = 4*100) { res++; // Add extra endpoint to make linear interpolation easier/faster alias T = typeof(QuarterSinTab[0]); if (QuarterSinTab !is null) free(QuarterSinTab.ptr); QuarterSinTab = (cast(T*)malloc(T.sizeof*res))[0..res]; res--; for(int i = 0; i < res; i++) QuarterSinTab[i] = sin(PI*(i/cast(double)res)); QuarterSinTab[$-1] = QuarterSinTab[0]; } /* Uses the tabularized quarter sine and extends it to the full range */ auto sinTab(string Method = "Linear")(typeof(QuarterSinTab[0]) x) { alias T = typeof(QuarterSinTab[0]); auto len = QuarterSinTab.length - 1; auto s = -1; auto m = x - cast(int)x; auto m2 = 1; if (x < 0) { m = m + 1; s = 1; } if ((abs(x) % 2) < 1) s = -s; auto a = m*len; auto ai = cast(int)(m*len); switch(Method) { default: case "Linear": auto f = a - ai; return s*((1 - f)*QuarterSinTab[ai] + f*QuarterSinTab[ai+1]); case "Constant": return s*QuarterSinTab[ai]; } } void main() { GenQuarterSinTab; auto x = iota(-10, 10, 0.01).map!(x => x * PI); auto y = x.map!("sin(PI*a)"); auto z = x.map!((x){ return sin(PI*x) - sinTab(x);}); //plt.plot(x, y, "r-", ["label": "$y=sin(x)$"]); plt.plot(x, z, "b-", ["label": "$y$"]); plt.xlim(-5, 5); plt.ylim(-0.001, 0.001); plt.legend(); plt.show(); import std.datetime; double xxx = 0; StopWatch sw; sw.start(); for(double i = 0; i < 1000; i++) xxx += sinTab(i); auto t = sw.peek().msecs; writeln(t); sw.stop(); writeln(xxx); xxx = 0; sw.reset(); sw.start(); for(double i = 0; i < 1000; i++) xxx += sin(PI*i); t = sw.peek().msecs; writeln(t); sw.stop(); }
EnumToFlags
I created a type that makes working with flags much easier. Please review for issues and enhancements. It would be nice to simplify the value size code. struct EnumToFlags(alias E) { import std.traits, std.conv, std.string, std.algorithm, std.array; static if (E.max < 8) alias vtype = ubyte; else static if (E.max < 16) alias vtype = ushort; else static if (E.max < 32) alias vtype = uint; else static if (E.max < 64) alias vtype = ulong; else static if (E.max < 128) alias vtype = ucent; else static assert("Cannot store more than 128 flags in an enum."); vtype value; template opDispatch(string Name) { enum opDispatch = 1 << __traits(getMember, E, Name); } auto opAssign(vtype e) { value = e; } bool opEquals(typeof(this) e) { if (e is this) return true; return (value == e.value); } auto opBinary(string op)(typeof(this) e) { auto x = typeof(this)(); mixin("x.value = this.value "~op~" e.value;"); return x; } auto opUnary(string op)() { auto x = typeof(this)(); mixin("x.value = "~op~"this.value;"); return x; } auto opCast() { return value; } auto toString() { string s; foreach(i, e; EnumMembers!E) { if (((1 << i) & value) == 1 << i) s ~= to!string(e) ~ " | "; } if (s.length > 0) s = s[0..$-3]; return s; } this(string from) { char uOp = ' '; char Op = '='; char nOp = '='; int previdx = 0; value = 0; for(int i = 0; i < from.length; i++) { nOp = from[i]; if (nOp == '!' || nOp == '~') { uOp = nOp; previdx = i + 1; continue; } if (nOp == '&' || nOp == '^' || nOp == '|' || nOp == '+' || nOp == '-' || i == from.length-1) { auto v = from[previdx..(i + ((i == from.length-1) ? 1 : 0))].strip(); vtype x = 0; foreach(j, e; EnumMembers!E) if (to!string(e) == v) x = cast(vtype)(1 << j); if (uOp == '!') x = !x; if (uOp == '~') x = ~x; switch(Op) { case '&': value = cast(vtype)(value & x); break; case '|': value = cast(vtype)(value | x); break; case '+': value = cast(vtype)(value + x); break; case '-': value = cast(vtype)(value - x); break; case '^': value = cast(vtype)(value ^ x); break; case '=': value = cast(vtype)(x); break; default: assert("Invalid EnumFlags operation `"~Op~"`."); } previdx = i + 1; Op = nOp; uOp = ' '; } } } alias value this; }; Possibly the to and from string stuff can be improved? Simply apply to a pre-existing enum.
Re: What is a concise way to test if floating point value is integral?
On Thursday, 29 August 2013 at 08:58:02 UTC, Paul Jurczak wrote: On Thursday, 29 August 2013 at 08:26:11 UTC, Jonathan M Davis wrote: On Thursday, August 29, 2013 10:07:31 Paul Jurczak wrote: On Thursday, 29 August 2013 at 07:51:40 UTC, Jonathan M Davis wrote: [..] > as any integral value in a float will fit in an > int. [..] Will it? Most of them will not fit Sure, they will. float has 32 bits, just like int, so it can't possibly hold a value larger than an int can hold. This code passes with flying colors foreach(i; int.min .. int.max) assert(cast(float)i == i); but cast to int produces nonsensical value anyway as in this example: cast(int)float.max So what? All you care about here is whether the value in the float is an integral value. float.max isn't an integral value, so it really doesn't matter if you get overflow when converting. It would have to convert back to the exact same value when converting it back to a float, and it won't. assert(cast(int)float.max == float.max); will fail. It might make more sense to use to!int if you want to use the resulting int for something, but all you're doing with it is comparing it against the original float to see if it's the same value. If anything, the fact that to!int throws would be a serious problem for what you're trying to do, because if what you're testing for is whether a float holds an integral value, throwing on overflow when converting to int would just get in your way. It should just result in false in that case (because it's not an integral value, or it wouldn't overflow), and the cast will result in false, unlike to!int. - Jonathan M Davis I should have used "integer" instead of "integral" to avoid math vs. programming language confusion. Well, float.max is an integer number! Its value is 3.40282e+38. The function I defined at the top of this page: bool isIntegral(T)(T x) {return x == round(x);} works correctly with float.max. Using cast(int) fails. I should have written it as: bool isInteger(T)(T x) {return x == round(x);} Yes, casting will not work because a float type can't be fully cast to an int without possible overflow. Your method works fine. The only issue, the issue with comparing any floating point, is tolerance. How close to an int does a float have to be to be considered an int? If you can afford to do something like `return (abs(x - round(x)) < tol)`. (remember, numerical computations can result in floating point numbers that are suppose be integers but are not(accumulation of rounding errors). Using == results in using the tolerance of a float, its minimum value) Also look at FXTRACT.
Re: How do i depend on struct composition
On Thursday, 22 August 2013 at 23:10:40 UTC, anonymous wrote: On Thursday, 22 August 2013 at 22:32:53 UTC, JS wrote: On Thursday, 22 August 2013 at 21:07:27 UTC, Mariusz `shd` Gliwiński wrote: [...] struct InnerC { void operate() { auto ptr = this-(void*).sizeof; /* do something with pointer */ } } struct Compound(Inner) { Inner a_or_b; InnerC c; } [...] If you actually nest InnerC inside Compound then it will contain a pointer(using this) to the parent. You can then use `parent` inside `operator` to access the parent which can access a_or_b. I think you're thinking of nested classes[1] here. Nested structs[2] are a little different. A nested struct is associated with a function, not with another struct. (By the way, I guess you mean `outer` instead of `parent`.) [1] http://dlang.org/class.html#nested [2] http://dlang.org/struct.html#nested Your right, I don't know why there isn't an equivalent for structs. In any case, check out http://dpaste.dzfl.pl/7f086694 and http://www.digitalmars.com/d/archives/digitalmars/D/Nested_Structs_183295.html for a solution
Re: How do i depend on struct composition
On Thursday, 22 August 2013 at 21:07:27 UTC, Mariusz `shd` Gliwiński wrote: Let me try to illustrate my question by following pseudo-code: struct InnerA { /* .. */ void* ptr; } struct InnerB { /* .. */ void* ptr; } struct InnerC { void operate() { auto ptr = this-(void*).sizeof; /* do something with pointer */ } } struct Compound(Inner) { Inner a_or_b; InnerC c; } I need to pass "c" to some subsystem which shouldn't be aware of "a_or_b" However, subsystem should be able to call function InnerB.operate() which needs access to "a_or_b". Now my questions: * Is there any way to tell subsystem, that he can't instantiate nor move InnerC * Is there any better,platform-independent way of accessing pointer from struct a_or_b ? Thanks in advance, Mariusz If you actually nest InnerC inside Compound then it will contain a pointer(using this) to the parent. You can then use `parent` inside `operator` to access the parent which can access a_or_b. if you need to return a member from a_or_b without going through a_or_b then just wrap it. I'm not sure exactly what you are trying to do but I think it can easily be done with standard techniques.
Re: Order matters on inheritance
On Thursday, 22 August 2013 at 08:45:36 UTC, Regan Heath wrote: On Thu, 22 Aug 2013 02:43:42 +0100, JS wrote: I don't know what the expected behavior is but it seems odd/wrong: http://dpaste.dzfl.pl/a390f1f4 Note that there are two issues here(almost the same). First is that A.foo isn't called and second is that the order of inheritance on A matters(: X, Y vs : Y,X). I would expect that A.foo(A) should match first and the ambiguity created from the inheritance should result in an error. I disagree that a.foo(A) should match, because.. You have a variable 'q' of type (interface) 'A' and you call method 'foo' on it. The compiler MUST only consider methods available on type (interface) 'A', which are: foo(X) foo(Y) It cannot call a.foo(A) (note 'a.foo' not 'A.foo') because while 'q' does in reality refer to an object of type 'a', you've asked it to interface to it via it's interface 'A' which does not have an overload foo(A). I do however agree that the compiler behaviour of silently selecting the foo from the first interface listed is wrong, it ought to give an error in this case IMO. Right, I forgot to add foo(A) to the interface. (I added it very quickly after the fact) It works as expected when foo(A) is added to the interface so there is no problem with that aspect.
Order matters on inheritance
I don't know what the expected behavior is but it seems odd/wrong: http://dpaste.dzfl.pl/a390f1f4 Note that there are two issues here(almost the same). First is that A.foo isn't called and second is that the order of inheritance on A matters(: X, Y vs : Y,X). I would expect that A.foo(A) should match first and the ambiguity created from the inheritance should result in an error.
Re: Is enum static?
On Tuesday, 20 August 2013 at 21:01:43 UTC, Jonathan M Davis wrote: On Tuesday, August 20, 2013 22:10:28 JS wrote: On Monday, 19 August 2013 at 18:28:10 UTC, Ali Çehreli wrote: > On 08/19/2013 03:18 AM, Borislav Kosharov wrote:> So if I > want > > to have a string constant it is a lot better to declare it > as: > > static immutable string MY_STRING = "Some string"; > > > > Because it won't be duplicated? > > enum is fine with strings. > > It is a common space optimization of the compilers not to > duplicate identical strings. The following program includes > just one "hello world" in the compiled object file: And why can't this be done with any compile time objects? AA's that are identical be collated similar to strings. It only works with string literal because they're immutable, and the compiler optimizes for that by only creating them once (it even puts them in the read- only portion of the binary in Linux). The same doesn't hold true for stuff like AAs. - Jonathan M Davis That wasn't the question, I didn't ask why D does what it does by why it can't do what it doesn't do.
Re: Is enum static?
On Monday, 19 August 2013 at 18:28:10 UTC, Ali Çehreli wrote: On 08/19/2013 03:18 AM, Borislav Kosharov wrote:> So if I want to have a string constant it is a lot better to declare it as: > > static immutable string MY_STRING = "Some string"; > > Because it won't be duplicated? enum is fine with strings. It is a common space optimization of the compilers not to duplicate identical strings. The following program includes just one "hello world" in the compiled object file: And why can't this be done with any compile time objects? AA's that are identical be collated similar to strings.
Re: more enum and pragma troubles
On Monday, 19 August 2013 at 04:37:58 UTC, captaindet wrote: On 2013-08-17 21:54, JS wrote: On Sunday, 18 August 2013 at 00:17:22 UTC, captaindet wrote: On 2013-08-17 14:36, Jesse Phillips wrote: Third you've declared a variable, bar, which will store your enumerated value, 4. Variables are not compile time, even if the value stored came from a compile time known value. yep, it completely escaped me that these are 'normal' variables. and i have realized now that i can make them known at compile time the same way as is done for other 'normal' variables, by declaring them const ;) But if they are const then what good does that do you? Just use an alias or enum in the first place? to be honest, i have not found a use case ;) highest priority was that i understood what was going on here... how did i get there? i was looking for an easy way to get pragma(msg,...) to print the given name for an enumerated value. in this example test2 or test4 instead of 2 and 4 - just like write is doing it at runtime. so i was playing around with the different variants of enum to see if i could get it working somehow.. and got sidetracked in the end i stuck to manifest constant enums storing the enumerated values and found that pragma( msg, to!string(foo) ); is doing the trick. /det I had the same issues, it is not an issue with logic but with the weird way dmd works(pragma is handled very early on and before ctfe's are completely parsed). Remember you can use ctfe's to format strings any way you want and even do logic and other stuff but you can't use pragma's inside the ctfe on ctfe variables(because as far as pragma is concerned, they are run time at that point). module main; import std.stdio, std.conv; template foo(alias T) { string foo(string s) { string x = to!string(T) ~ s ~ ""; //pragma(msg, x); // pragma see's x as a run time variable(or rather pragma is executed before x is truly defined) return x; } } int main(string[] argv) { pragma(msg, foo!("asf")("xxx")); // note, it prints what the commented pragma is suppose to print, but this one works!!! Because it is outside the ctfe and foo!(...) can be computed at compile time readln(); return 0; } I really believe the issue is with the compiler and is a bug. Somehow x gets marked as run time, probably because ctfe's are suppose to work at run time too... even though in this instance it is being used at compile time. (so it should work)
Re: how to get enclosing function as symbol ? (eg: __function__.stringof ==__FUNCTION__)
On Sunday, 18 August 2013 at 01:52:50 UTC, Timothee Cour wrote: Is there any way to get the enclosing function as symbol ? I'd like something like that: alternative names would be: __function__ __context__ auto fun(alias caller=__function__)(){ //caller represents fun1!double return ReturnType!caller.init; } T fun1(T)(T x){ assert(__function__.stringof==__FUNCTION__); alias fun=__function__; assert( is(ReturnType! __function__) == T); return fun(); } void main(){fun1!double();} use a string mixin?
Re: more enum and pragma troubles
On Sunday, 18 August 2013 at 00:17:22 UTC, captaindet wrote: On 2013-08-17 14:36, Jesse Phillips wrote: Third you've declared a variable, bar, which will store your enumerated value, 4. Variables are not compile time, even if the value stored came from a compile time known value. yep, it completely escaped me that these are 'normal' variables. and i have realized now that i can make them known at compile time the same way as is done for other 'normal' variables, by declaring them const ;) But if they are const then what good does that do you? Just use an alias or enum in the first place?
Re: more enum and pragma troubles
On Saturday, 17 August 2013 at 05:22:53 UTC, captaindet wrote: are these bugs or expected behavior? (2 issues, see code below) i thought enums are just compile time copy&paste magic so i cannot think of a reason why it should not be available at compile time... if buggy, what is broken, enum (really bad) or pragma(msg,...) (worse enough)? and are they in bugzilla already? (looked but nothing caught my eye) if expected behavior, can someone pls explain. cheers /det import std.stdio; enum Test{ test2 = 2, test4 = 4 } enum foo = Test.test2; Test bar = Test.test4; pragma( msg, foo ); // why does it print: cast(Test)2 // it should be: test2 // or at least simply: 2 It is 2! Notice the 2 at the end? The cast is just mumbo jumbo due to the the compiler deals with the stuff. You can remove the casts manually if you don't like them. // pragma( msg, bar ); // Error: variable bar cannot be read at compile time Because bar is not a compile time constant. It is an runtime object. pragma can't display certain things that it doesn't know about due to the way the compiler works. It's unfortunate in some cases that it simply doesn't work correctly, in others, such as this, it works as expected. You could argue that the compiler should know that bar is known at compile time up to the pragma, and I would agree... but the compiler simply isn't that smart. void main(){ writeln( typeof(foo).stringof, " = ", foo ); // prints as expected: Test = test2 writeln( typeof(bar).stringof, " = ", bar ); // prints as expected: Test = test4 } these print the value at runtime. In this case the compiler is already out of the picture. Basically pragmas are evaluated during compile time, if the compiler can't figure out the value(or is too stupid) then it can't print them and throws an error. In fact, even in CTFE stuff pragma doesn't function like one would hope. This again, is due to the way the compiler works. Just a quirky and unfortunate way that the d compiler works.
Re: Recommended ways to handle final classes
On Friday, 16 August 2013 at 15:47:21 UTC, Joseph Rushton Wakeling wrote: On 08/16/2013 05:40 PM, JS wrote: Can you describe how this helps? Sure, if you use A the compiler should be able to optimize method calls but you can't use A in inheritance because it is a final class. e.g., The point is, you should be able to use _A for inheritance, A for performance, and they both have the same functionality. Or am I mistaken? You can't get them both at the same time though, which you might just make _A final. The whole point of inheritance is to treat derived classes as if they were base classes. e.g., code was designed to use class _A, you come along, extend _A to A, but "trick" to the code to use your A(even though it thinks it's an _A). Now, when you use your final class A where _A's are suppose to be, there can be no optimization made by the compiler(unless it can determine the object really is an A). e.g., class _A { void foo() { writeln(); } } final class A : _A { } ... _A a = new A; ... a.foo(); // can't be inlined because a's type is not CT final. A aa = new A; ... aa.foo(); // can be inlined because aa's type is final(no need for vtable) The only difference is that a is _A and aa is A. So when you use your final class with inheritance, it becomes useless because it gets treated as the base class, which is not final. When one does _A a = new A; a is of type _A regardless of what we actually stick in a as far as what the compiler see's(unless it's real smart but then, final is not needed). A final class is simply to stop someone from deriving from it. The compiler can make optimizations based on this info IF it knows that the object is from a final type. Here is a more real world example class Shape { } final class fShape : Shape { } class Rectangle : Shape { } final class fRectangle : Rectangle { } Shape s = new fRectangle; // useless, just use Rectangle, the compiler will probably never know s is an fRectangle. (it might in some cases but probably not worth it) That is the oop way, this is not: fShape s = new fRectangle; // invalid, fRectangle is not derived from fShape. // compiler knows s is a final class and can make optimizations on it. Because we can't assign concrete shapes to fShape(because they have to derive from them, but can't because the class is final), it becomes useless to use(no way to do oop). To do oop you have to have derivation from base classes, but final stops that. Hence your two goals(being able to use oop and being able not to(using final) are mutually exclusive). The only way it can be useful is if the compiler can determine if an object is final at compile time... but if it can do this then it doesn't need to be final in the first place(it will still be able to inline methods).
Re: Recommended ways to handle final classes
On Friday, 16 August 2013 at 15:12:03 UTC, Joseph Rushton Wakeling wrote: Hi all, I'm writing some class-based code and so my concerns have turned to the issue of final classes vs. inheritance. Suppose that you want a particular class to be able to act as a base class, but also to perform at top speed. Is the following kind of pattern worth considering: class _A { // ... implementation, with virtual functions } final class A : _A { // ... don't add anything! } ...? Or are there other recommended ways to handle how to get speed while still allowing the option of inheritance? Thanks & best wishes, -- Joe Can you describe how this helps? Sure, if you use A the compiler should be able to optimize method calls but you can't use A in inheritance because it is a final class. e.g., A a = new _A; // wrong _A a = new A; // right, but a will use virtual functions. The final class only prevents class B : A AFAIK but the vtable is still intact.
Re: double.init is real.nan, is it a bug?
On Thursday, 15 August 2013 at 04:01:28 UTC, bsd wrote: Hi all, I think this is a bug, but if not I'm very confused and would like some clarification. When checking double values that could be nan or unassigned I have to check both double.init and double.nan. But double.init IS double.nan. --- void main() { // passes but I believe it is checked during compile assert(double.init is double.nan); double val; std.stdio.writeln( to!string(val) ); // writes "nan" to console assert(val is double.init); // passes assert(val is double.nan); // << FAILS (unexpectedly for me anyway) } --- Why does assert(val is double.nan) fail? Given: a) double.init is double.nan b) val is double.init c) to!string(val) sees val as a nan I also found this confusing: --- void main() { assert(double.init is double.nan); // passes expected assert(double.init is float.init); // passes, unexpected assert(double.init is real.init); // passes, unexpected assert(double.init is real.nan); // passes, unexpected assert(double.init is float.nan); // passes, unexpected } --- I don't think these should be passing...should they?? I'm on fedora 19, dmd 2.063.2 extracted from the ZIP Thanks There is the issue with order on is. Try reversing them and see if you get the same results. I imagine for floats and doubles are interchangeable for nans(both are nan, regardless of the encoding used).
Re: Templated structs / variant values
On Wednesday, 14 August 2013 at 22:28:13 UTC, Marek Janukowicz wrote: I need to have a generalized "settings" functionality that should work like this: * I need to be able to add this to a class * each setting has its name, description, type and default value * I need to iterate over all settings for given object API would more or less look like: class A { ... here I somehow define a setting called "maxTime" } A a = new A(); auto b = a.settings["maxTime"].value; // b would contain default value, because it wasn't set explicitly yet string s = a.settings["maxTime"].description; // s would contain setting description a.settings["maxTime"].value = 10.seconds; // This would only work if maxTime setting is of type duration foreach( name, value; a.settings ) ... Now the problem that I have is with storing those settings. What I've come up with so far are either Variants or templated structs (either really templated and type parametrized structs returned from template functions). The problem with variants is that I don't know how to force the value to be of certain type (variant accepts anything). As for templates and structs I tried something like: auto setting (string name, string description, T, T deflt)() { struct Setting { string name = name; T value; } return Setting(name, deflt); } but then I don't know if there is any way to build an array of those to be able to iterate over them. I know generally there should be some kind of "setting definition" defined on class level that would keep shared information (like names and defaults) and then per-instance data containing just actual values, but I don't really care and any solution where this shared information is copied for every instance would also be fine. I know the description above is a bit messy (it's quite late now), but hopefully you can get the picture. Any ideas how to approach this problem? I don't really follow what exactly you are trying to do. You first example is written using an associate array format which D already can handle. If you are wanting more "member" like behavior then there are several ways to go about it. e.g., 1. a.maxTime can be used by using opDispatch and redirecting it to settings["maxTime"]. 2. You can use string mixins to create your own DSL like behavior to code how you want. This is somewhat complex and there is no syntax highlighting or property error analysis but it works. If you are wanting to have default settings and specific settings for objects then it can be done. I did this once in C#. You can write a whole framework to do this. I used an AA that would lookup the value for the object(using the objects hash) and if it didn't exist it would get the parent value, if that didn't exist it would work itself up the tree until it found one. e.g., A a = new A; writeln(a.settings.maxTime); // uses opDispatch. maxTime is looked up in the global settings. If settings[a.hash~"maxTime"] exists then it's value is the maxTime setting for a. If it doesn't exist, try settings[a.parent.hash~"maxTime"], etc...
Fastest Delegate
I'm wondering how stuff like http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates?msg=1166433#xx1166433xx holds up in D? I can't quite translate it into D... anyone mind giving it a try?
Profiling Inheritance
I am trying to profile virtual functions vs delegates http://dpaste.dzfl.pl/dd10c841 Num TreeFuncPer CallsTimeTimeCall 3 1019328 456148 152049 int main._testfooA(main.A) 3 1809331 398939 132979 int main.testfooA(main.A) 3 446842 382742 127580 int main.testfooB(main.B) _testfooA is called when the delegate is null(this results in comparison that fails) testfooA is called when the delegate is not null(which results in a comparison that passes and the delegate is called). testfooB is simple virtual function calls. What is Tree Time and how does it relate to performance? (call time is obvious) Tree time is drastically different but the time per call is not (152 - 128)/128 ~= 20% slower. I was interested in using the interface final pattern to provide default behavior but it seems slower than virtual calls. I was hoping that the null delegate test would be faster but I guess the branching thrashes the cache? 1 176 176 176 int main.testfoo() If I avoid virtual functions all together then the speed differences is immense, but it is over 800x slower. Not sure if the compiler is somehow optimizing out testfoo or if virtual function calls are really that slow. I do realize that the virtual functions and delegates are not doing much but it's still quite significant.
Re: Get class size of object
On Monday, 12 August 2013 at 19:44:56 UTC, Jacob Carlborg wrote: On 2013-08-12 17:49, JS wrote: Sorry but this doesn't work. b is a B, not an A. try I a = new A; I b = new B; Right, forgot about the interface. NP, happens to all of us. Simen's method of casting to object seems to be the easiest way to get it to work.
Re: Get class size of object
On Monday, 12 August 2013 at 11:34:25 UTC, Jacob Carlborg wrote: On 2013-08-11 21:08, Simen Kjaeraas wrote: If you're looking for a no-overhead solution, then this might not be good enough. I'm surprised that a virtual function call is fine, though. How about this: interface I { size_t size (this T) () { return __traits(classInstanceSize, T); } } class A : I { } class B : I { int a; } void main () { auto a = new A; auto b = new B; assert(a.size == 24); assert(b.size == 32); } Sorry but this doesn't work. b is a B, not an A. try I a = new A; I b = new B;
Re: Get class size of object
On Sunday, 11 August 2013 at 20:03:27 UTC, Adam D. Ruppe wrote: On Sunday, 11 August 2013 at 19:58:26 UTC, Adam D. Ruppe wrote: Oh, I see it now. I think typeid(interface) gives a different set of info. Thinking about it a bit more, this makes sense because an interface is not necessarily an Object - it might also be a C++ class, or a COM object, or maybe even a slice into another vtbl if an Object implements multiple interfaces (not completely sure about the latter, I'd have to read some source, but it seems logical to me). Possibly. Since I program to interfaces, every reference I use is referenced to an interface. Needing the correct object size for implementing an allocator was not working as "expected"(at least as one would expect with classes). I could not see anything in the docs that would suggest otherwise(else the light bulb might have went off). i.e., one would expect, IMO, that tsize would work on interfaces because interfaces do not have a "size" so it should return the class size of the object. (so things work uniformly and we can program to interfaces without having to create workarounds).
Re: Get class size of object
On Sunday, 11 August 2013 at 19:06:07 UTC, Adam D. Ruppe wrote: On Sunday, 11 August 2013 at 18:33:19 UTC, JS wrote: The code below does this, but at a cost of verbosity. I don't see what the difference is in functionality - it looks to me that you just reimplemented what the compiler does automatically with typeid. The way typeid(obj) works is similar to a virtual function call internally, indeed, Class.vtbl[0] is a pointer to its TypeInfo instance. But anyway, then the typesameinfo contains functions for the class name and size, pretty similar to what you just did. What does your implementation give you that typeid() doesn't? Well, I am wrapping the stuff. But when I've tried to do essentially l the same thing before using the compiler directly, it simply did not work. If you read Simen Kjaeraas's post you will see it doesn't work directly with interfaces, which is what I was doing. Hence, either a bug or anti-feature or whatever, the issue was with D and not some weird thing I was trying to do... All this nonsense is trying to work around D doing stupid stuff. All I know is that in my code, when trying to get the actual object size, even if derived(which may change the size), I would always get 4. I was using an interface as my base type. Regardless, there are now two solutions and I have to go back to my production code and figure out which one works best for my situation.
Re: Get class size of object
BTW, I hope that if you want to be added to the ignore list on my side, you use the script and do the same. I know some will want everyone to see their irrelevant posts but I won't see it and so you will never get a response from me and it just clutters up the NG and distracts from D.
Re: Get class size of object
On Sunday, 11 August 2013 at 19:08:58 UTC, Simen Kjaeraas wrote: On 2013-08-11, 20:33, JS wrote: I think you're missing the point to some degree(I realize there is a diff between an object and a type, but I should be able to easily get the class size of an object at run time regardless if the object is typed as a base class). The code below does this, but at a cost of verbosity. Here is code that exactly demonstrates what I am essentially trying to do. The only drawback now is having to mixin the template for each class which I would want to automate and it would be nice to wrap the RT and CT methods in subclasses without overhead. It would appear that some information is lost when calling typeid from an interface. I would have expected this to work: interface I { final size_t size() { return typeid(this).init.length; } } class A {} class B : A, I { int a; } void test1() { I i = new B(); assert(i.size > 0); // Fails. } A bit more experimentation shows: void test2() { B b = new B(); I i = b; A a = b; assert(typeid(a) == typeid(b)); // Passes. assert(typeid(i) == typeid(b)); // Fails. assert(typeid(b).init.length > 0); // Passes. assert(typeid(i).init.length > 0); // Fails. } It appears thus that the error is in typeid(interface), which does not give the actual typeid. The workaround is as follows: interface I { final size_t size() { return typeid(cast(Object)this).init.length; } } Is this what you want? Is it good enough? I have no idea, as you're notoriously bad at describing what you want, but pretty good at attacking people. If you're looking for a no-overhead solution, then this might not be good enough. I'm surprised that a virtual function call is fine, though. I attack people because they are arrogant bastards. They do nothing to help but only contribute to the chaos. They deserve to be attacked because arrogant people are evil. In any case I think your solution might be correct. Originally I was using interfaces and do recall it working with classes but not interfaces but didn't know how to get it to work.
Re: Get class size of object
I think you're missing the point to some degree(I realize there is a diff between an object and a type, but I should be able to easily get the class size of an object at run time regardless if the object is typed as a base class). The code below does this, but at a cost of verbosity. Here is code that exactly demonstrates what I am essentially trying to do. The only drawback now is having to mixin the template for each class which I would want to automate and it would be nice to wrap the RT and CT methods in subclasses without overhead. http://dpaste.dzfl.pl/757eeb05 Note, I can easily get the class size, name, etc... by using the object or the type. import std.stdio; mixin template tObject(alias T) { override @property int classSize() { return __traits(classInstanceSize, T); }; override @property string className() { return T.stringof; }; immutable static int ClassSize = __traits(classInstanceSize, T); immutable static string ClassName = T.stringof; static T New(Args...)(Args args) { writeln(T.ClassSize); return new T(args); } } interface iObject(T) { @property int classSize(); @property string className(); } class A : iObject!A { double x; mixin tObject!A; } class B : A { double y; mixin tObject!B; double z, t; } void main() { A a = A.New(); A b = B.New(); writeln(a.classSize); writeln(b.classSize); readln; }
Re: Get class size of object
On Sunday, 11 August 2013 at 18:15:28 UTC, Timon Gehr wrote: On 08/11/2013 07:26 PM, JS wrote: On Sunday, 11 August 2013 at 17:12:48 UTC, Timon Gehr wrote: On 08/11/2013 05:28 PM, JS wrote: On Sunday, 11 August 2013 at 13:40:41 UTC, Timon Gehr wrote: On 08/11/2013 06:25 AM, JS wrote: Given an object, is there a built in way to get the size of the class the object represents? Yes. Troll. http://en.wikipedia.org/wiki/Troll_(Internet) Seriously, do you not have anything better to do with your life? No. How about you? That explains it all. How bout you get a life? Why do you hang out on my posts if you are the one that's not the troll. That's obvious. You are the _first_ guy capably trolling these newsgroups, so we are still too naive to believe that you are not receptive to rational argumentation and incapable of constructive discussion. Really? Because I won't except your help hands down. You are an arrogant bastard who thinks you know it all. When someone challenges you because they won't accept you as the god you then cry like a little bitch. I don't want any of your help The best way to not receive help is to quit asking for help. Rigghhtt... your logic is wonderful. Don't ask for help in .learn. I guess you are trying to run me off because you can't stand me huh? Well the feeling is mutual... but at least there are a few intelligent people still left in here that actually want to help for the sake of helping and not to feed their ego. so why don't you just do us all a favor and ignore any post I make? I am as confused about this as you are but I can't talk for everyone. What is _your_ motivation, 'JS'? If you think your posts are worth ignoring, simply stop making noise. Again, here is your very arrogant egotistical personality shining through(only other arrogant egotistical people will not see this). What is useless to one person is not to another. If you weren't so arrogant you would see this and let me make my posts in peace and let those that want to help me do that. Instead you rant against my posts in my thread to shut it down... but yet you call me the troll.
Re: Get class size of object
On Sunday, 11 August 2013 at 18:18:22 UTC, Dicebot wrote: On Sunday, 11 August 2013 at 17:03:04 UTC, JS wrote: This is essentially what I'm doing BUT I am trying to avoid having to repeat the exact same crap in every class because it is time consuming, verbose, and error prone. I was answering to Maxim, I don't give a fuck about your problems. THEN WHY THE FUCK DO YOU POST ON MY THREAD? You have not helped or tried to help one post. You have only ever tried to shut down any questions or suggestions I have based on your arrogant belief system that everyone and everything revolves around you... yet you continue to invade my posts. Seriously, Why can't you just leave me the fuck along and ignore my posts? Is it difficult? No, it's not. This suggests you intentionally want to make trouble. In any case, I'm through talking to you bastards. I will ignore your post from now on. In fact, I'll write a script at some point to simply remove your posts, Tim's, and others that want to act like little fucking arrogant kids that haven't got their ass kicked hard enough to realize they are not the center of the universe.
Re: Get class size of object
On Sunday, 11 August 2013 at 17:19:21 UTC, Adam D. Ruppe wrote: On Sunday, 11 August 2013 at 17:03:04 UTC, JS wrote: For those that care, here is a snippet of what I am doing. What are you actually going to use the number for? If you are going to write your own New function, you'll need the init anyway, so you aren't really paying more to get the size from it either. What's the difference between init.length and classInstanceSize? The class instance size must be known at compile time and I don't see why there will be a difference and what little testing I have done shows no difference.
Re: Get class size of object
On Sunday, 11 August 2013 at 17:12:48 UTC, Timon Gehr wrote: On 08/11/2013 05:28 PM, JS wrote: On Sunday, 11 August 2013 at 13:40:41 UTC, Timon Gehr wrote: On 08/11/2013 06:25 AM, JS wrote: Given an object, is there a built in way to get the size of the class the object represents? Yes. Troll. http://en.wikipedia.org/wiki/Troll_(Internet) Seriously, do you not have anything better to do with your life? Why do you hang out on my posts if you are the one that's not the troll. I don't want any of your help so why don't you just do us all a favor and ignore any post I make?
Re: Get class size of object
On Sunday, 11 August 2013 at 16:43:09 UTC, Dicebot wrote: On Sunday, 11 August 2013 at 16:40:48 UTC, Maxim Fomin wrote: Yes, this is answer to the question. By the way, it can be simply enum S = typeid(Whatever).init.length; If exact type is statically known, no ClassInfo is required: enum S = __traits(classInstanceSize, Whatever); This is essentially what I'm doing BUT I am trying to avoid having to repeat the exact same crap in every class because it is time consuming, verbose, and error prone. For those that care, here is a snippet of what I am doing. For those that are bitches, GTFO. Remember, I'm a troll so everything I say or do here is irrelevant, so I don't even know why you are reading this in the first place. http://dpaste.dzfl.pl/d295 Note that because it is a function call it is extremely expensive compared to a compile time literal. Disassembly shows that the actual size is a constant so the vtabl lookup and a function call is all that is required. I'd like to minimize the overhead as much as possible and, ideally not have to manually add the template mixins to each class(it would be nice if it were automated). I'm trying to reduce the costs of RT lookup as much as possible(as I feel it is not necessary).
Re: Get class size of object
On Sunday, 11 August 2013 at 15:38:04 UTC, Tobias Pankrath wrote: Is this a mathematical fact that you have proven for all languages? I'd like to see your proof if it's not bigger than what will fit in a post. That's so obvious, that you should be able to come up with one yourself. Maybe you never experienced a situation where it was clear, but that doesn't mean I need to come up with a proof, just because you are to lazy to do it yourself. No, but your simple wrong. Either you have no clue what you are talking about, don't understand the issue, or are intentionally stating falsehoods. It's very easy to manually implement a way to get the class size by just using a virtual function that returns the class size. But do you think I should have to waste my time adding the same function to every class to make it work? Of course you do.
Re: Get class size of object
On Sunday, 11 August 2013 at 09:30:32 UTC, Tobias Pankrath wrote: On 11.08.2013 06:25, JS wrote: Given an object, is there a built in way to get the size of the class the object represents? The object may be instantiated with a derived instance of the object type, so using classInstanceSize doesn't work on the type of the object. I can obviously go through the trouble of adding a class member and override it in all the derived classes. I saw tsize in object but 2.063 says it doesn't exist. There is no general way to do this at compile time in any language. Is this a mathematical fact that you have proven for all languages? I'd like to see your proof if it's not bigger than what will fit in a post.
Re: Get class size of object
On Sunday, 11 August 2013 at 13:40:41 UTC, Timon Gehr wrote: On 08/11/2013 06:25 AM, JS wrote: Given an object, is there a built in way to get the size of the class the object represents? Yes. Troll.
Get class size of object
Given an object, is there a built in way to get the size of the class the object represents? The object may be instantiated with a derived instance of the object type, so using classInstanceSize doesn't work on the type of the object. I can obviously go through the trouble of adding a class member and override it in all the derived classes. I saw tsize in object but 2.063 says it doesn't exist.
Re: Virtual templates members
On Thursday, 8 August 2013 at 17:32:56 UTC, Nicolas Sicard wrote: On Thursday, 8 August 2013 at 16:58:37 UTC, JS wrote: On Thursday, 8 August 2013 at 07:21:19 UTC, Nicolas Sicard wrote: On Thursday, 8 August 2013 at 01:48:49 UTC, JS wrote: The following code is used to reduce dependence on new and the GC. iNew is used as the replacement. The problem is, where ever New is used, it requires typing the type twice. e.g., A.New!A(...) instead of A.New(...) Is there any way to solve this issue? (iNew is suppose to provide the contract to implement a "new" like method that will allocate the class. Note there is no virtual function so no overhead) import std.stdio, std.conv; enum eNew { Default = 0, } interface iNew { final static T New(T, A...)(A args) { eNew type = eNew.Default; static if (A.length == 0 || !is(typeof(args[0]) == eNew)) alias nargs = args; else { type = cast(eNew)args[0]; alias nargs = args[1..$]; } writeln(">> ", __traits(classInstanceSize, T)); switch (type) { default: return new T(nargs); } return new T(nargs); } } class A : iNew { int t; } class B : A { int q; double d; } void main() { A a = A.New!A(); B b = B.New!B(); readln(); } Why not make it a mixin template? --- import std.stdio, std.conv; enum eNew { Default = 0, } mixin template iNew(T) { final static T New(A...)(A args) { eNew type = eNew.Default; static if (A.length == 0 || !is(typeof(args[0]) == eNew)) alias nargs = args; else { type = cast(eNew)args[0]; alias nargs = args[1..$]; } writeln(">> ", __traits(classInstanceSize, T)); switch (type) { default: return new T(nargs); } //return new T(nargs); } } class A { mixin iNew!A; int t; } class B : A { mixin iNew!B; int q; double d; } void main() { A a = A.New(); B b = B.New(); readln(); } --- Because I don't want to have to specify this in each class. iNew is suppose to be a contract. What happens if someone writes a class and forgets to add the mixin then distributes the class in a library? There's no issue with that using an interface because it results in an error. I understand the goal. But if someone forgets to add the mixin, A.New() would not compile. And the probability of mistakenly calling 'new A' might even be as high as the probability of forgetting the mixin. But it is backwards. If you are designing a class and forget, then distribute a library of that class, everyone is screwed if you forget to include the appropriate member. Not only will they not be able to call it, as you said, they won't easily be able to fix it. With interfaces, it provides the contract. With the static final, it provides a single instance(doesn't have to mixin at each class). I realize it probably doesn't matter too much in the long run but I'm asking how to make what I want work and not a workaround. It would be nice to have a This which returns the type of the interface, analogous to this, which returns the instance. After all, I could just write a standard template and use that regardless and call it directly. Then there is no need to use mixins which waste space. e.g., T New(T, A...)(A args) { } Then just New!A(...) but then I loose my interface contract, which, in this scenario isn't a huge deal but I'd like to be able to distinguish objects that have this allocation strategy pattern vs those that don't. In the future, I may want to allow the class to provide it's own allocation scheme overriding iNew.New(indirectly).
Re: Virtual templates members
On Thursday, 8 August 2013 at 07:21:19 UTC, Nicolas Sicard wrote: On Thursday, 8 August 2013 at 01:48:49 UTC, JS wrote: The following code is used to reduce dependence on new and the GC. iNew is used as the replacement. The problem is, where ever New is used, it requires typing the type twice. e.g., A.New!A(...) instead of A.New(...) Is there any way to solve this issue? (iNew is suppose to provide the contract to implement a "new" like method that will allocate the class. Note there is no virtual function so no overhead) import std.stdio, std.conv; enum eNew { Default = 0, } interface iNew { final static T New(T, A...)(A args) { eNew type = eNew.Default; static if (A.length == 0 || !is(typeof(args[0]) == eNew)) alias nargs = args; else { type = cast(eNew)args[0]; alias nargs = args[1..$]; } writeln(">> ", __traits(classInstanceSize, T)); switch (type) { default: return new T(nargs); } return new T(nargs); } } class A : iNew { int t; } class B : A { int q; double d; } void main() { A a = A.New!A(); B b = B.New!B(); readln(); } Why not make it a mixin template? --- import std.stdio, std.conv; enum eNew { Default = 0, } mixin template iNew(T) { final static T New(A...)(A args) { eNew type = eNew.Default; static if (A.length == 0 || !is(typeof(args[0]) == eNew)) alias nargs = args; else { type = cast(eNew)args[0]; alias nargs = args[1..$]; } writeln(">> ", __traits(classInstanceSize, T)); switch (type) { default: return new T(nargs); } //return new T(nargs); } } class A { mixin iNew!A; int t; } class B : A { mixin iNew!B; int q; double d; } void main() { A a = A.New(); B b = B.New(); readln(); } --- Because I don't want to have to specify this in each class. iNew is suppose to be a contract. What happens if someone writes a class and forgets to add the mixin then distributes the class in a library? There's no issue with that using an interface because it results in an error.
Virtual templates members
The following code is used to reduce dependence on new and the GC. iNew is used as the replacement. The problem is, where ever New is used, it requires typing the type twice. e.g., A.New!A(...) instead of A.New(...) Is there any way to solve this issue? (iNew is suppose to provide the contract to implement a "new" like method that will allocate the class. Note there is no virtual function so no overhead) import std.stdio, std.conv; enum eNew { Default = 0, } interface iNew { final static T New(T, A...)(A args) { eNew type = eNew.Default; static if (A.length == 0 || !is(typeof(args[0]) == eNew)) alias nargs = args; else { type = cast(eNew)args[0]; alias nargs = args[1..$]; } writeln(">> ", __traits(classInstanceSize, T)); switch (type) { default: return new T(nargs); } return new T(nargs); } } class A : iNew { int t; } class B : A { int q; double d; } void main() { A a = A.New!A(); B b = B.New!B(); readln(); }
Re: Which option is faster...
On Monday, 5 August 2013 at 13:59:24 UTC, jicman wrote: Greetings! I have this code, foreach (...) { if (std.string.tolower(fext[0]) == "doc" || std.string.tolower(fext[0]) == "docx" || std.string.tolower(fext[0]) == "xls" || std.string.tolower(fext[0]) == "xlsx" || std.string.tolower(fext[0]) == "ppt" || std.string.tolower(fext[0]) == "pptx") continue; } foreach (...) { if (std.string.tolower(fext[0]) == "doc") continue; if (std.string.tolower(fext[0]) == "docx") continue; if (std.string.tolower(fext[0]) == "xls") continue; if (std.string.tolower(fext[0]) == "xlsx") continue; if (std.string.tolower(fext[0]) == "ppt") continue; if (std.string.tolower(fext[0]) == "pptx") continue; ... ... } thanks. josé Both are slow, those trying to optimize out tolower are missing the boat. A good compiler should optimize that out. The issue is that n compare are done in those cases with each successive compare getting slower and slower. if the match is doc then it happens in one compare in both cases. If it's pptx then it is 6. So if there are many pptx matches then the code will perform slower than for doc. This can be good or bad behavior depending on if you are guarantee that your order is representative of what actually happens(many doc's few pptx's). To get O(1) behavior, you must use some sort of jump list. A hash table can provide such behavior. If there are many comparisons needed then at some point this will be, on average, faster. If performance is critical and the string length is small enough then the fastest method is to use a direct lookup table. For n character of char. It is 256^n. For n = 4, this is 4GB of memory! (This is one reason to use a hash table). Since you are not using the full ascii you could compact this a bit, say 36^n, for n = 4 it is only 1.6MB of memory. The cost is packing the strings for lookup and computing the index. One way to speed up the loop is to also compare for what is not used. In this case you can compare just on the first char. if (fext[0][0]) == "d") { ... } if (fext[0][0]) == "x") { ... } if (fext[0][0]) == "p") { ... } This pares down the results. In this case it is only 3 comparisions + 2 comparisons = 5 for pptx rather than 6. You can try and develop your own hash to get optimal amortized performance.
Re: Is this a good pattern for allocation?
On Monday, 5 August 2013 at 12:41:19 UTC, Tobias Pankrath wrote: On Monday, 5 August 2013 at 08:11:59 UTC, JS wrote: I guess you mean that I should use a template as a factory instead of an interface? I'll have to think about it to see what the pro's and con's of each are. The interface pattern should include the template pattern though. (after all, the interface is parameterized...) If you want to swap your allocators at runtime than an interface is a good solution. They are here for runtime dispatch after all. However all your allocators are forced to be classes. Coincidentally an article has been written about exactly this maybe a week ago. See http://blog.thecybershadow.net/2013/07/28/low-overhead-components/ . What I would like is some way to choose an approximate optimal allocator that can be modified at run-time if necessary. e.g., small objects can use a slab allocator. Large objects can use a buddy allocator. I can change the allocator type at application startup to something else entirely if necessary for various reasons(performance checking, memory leakage, etc...). What I would like is for classes to be able to request a certain allocator(this way, the class writer can attempt to choose the best. Later on, I can profile different allocators rather easily by just changing the factory and force the classes to use the best one found. There seems to be a lot on the specifics that I'll have to read up on but I mainly want to avoid programming myself into a corner.
Re: Is this a good pattern for allocation?
On Monday, 5 August 2013 at 07:15:30 UTC, Tobias Pankrath wrote: On Monday, 5 August 2013 at 01:47:26 UTC, JS wrote: Anyways, is this a bad or good way and how can I call Factory to get a new object? (I know that ther is .init and other stuff that can be used by Factor/New. I'm just trying to get the skeleton to compile and make sure there are not going to be major issues in the future. I wouldn't use inheritance, but something that involves a template function and std.conv.emplace and handles all of your types uniformly. The purpose of inheritance is to allow one to modify the allocation scheme if necessary and to have a common interface which looses the dependency on any standard library, D, or the GC. (e.g., instead of having to change new every place it occurs one just has to change it either in the factory or in the New method). I guess you mean that I should use a template as a factory instead of an interface? I'll have to think about it to see what the pro's and con's of each are. The interface pattern should include the template pattern though. (after all, the interface is parameterized...)
Is this a good pattern for allocation?
Trying to avoid GC dependence on my objects. interface Alloc(T) { T New(A...)(A args); //final T Factory(A...)(T, A args) { return new T(args); } } class A(T) : Alloc!(A!(T)) { static A!T New() { return new A!T();// Use GC for now // Factor(A!T); } } (I'm not sure why the static New satisfies the interface but dmd doesn't complain) Using New instead of new removes a dependence step. If I could get the factory to work, then it could be used by New to help setup the object, the factory just allocating the object while New setting it up properly. Anyways, is this a bad or good way and how can I call Factory to get a new object? (I know that ther is .init and other stuff that can be used by Factor/New. I'm just trying to get the skeleton to compile and make sure there are not going to be major issues in the future.
Re: Debugging templates!
On Saturday, 3 August 2013 at 14:04:10 UTC, JS wrote: There has to be a better way?!?!?!?! Of course, I mean string mixin's using template.. and the statement was to ask people how they went about it...
Debugging templates!
There has to be a better way?!?!?!?!
Re: Simulating sub types
On Friday, 2 August 2013 at 13:57:08 UTC, Dicebot wrote: On Friday, 2 August 2013 at 13:37:09 UTC, JS wrote: Then that doesn't help. Do you mean A.B is not visible outside the module either? Can B be instantiated and inherited when static, if not then it is no use. Yes, A will act simply as a "namespace". If B is public, it can be accessed and instantiated from other modules. All static does here is removing hidden context pointer. ok, then that is exactly what I want. Thanks.
Re: Simulating sub types
On Friday, 2 August 2013 at 12:29:02 UTC, Meta wrote: On Friday, 2 August 2013 at 11:47:46 UTC, bearophile wrote: JS: the fact remains that I can't do it in Dlang. Is tagging the inner class as static helping? class A { static class B { ... } } Bye, bearophile Just to be clear, marking the inner class as static means that B will not have a pointer to A. It is the same as defining B outside A, the difference being that B is not visible to anything outside the module. Then that doesn't help. Do you mean A.B is not visible outside the module either? Can B be instantiated and inherited when static, if not then it is no use. To be. clear I want B to behave like any ordinary "root" class(just like A), except I want to have to access it through A(logically). This creates a hierarchical way of accessing types that makes it clear how they are related to other types, but doesn't prevent them from being used in a non-hierarchical way if necessary(The way D deals with nested classes prevents this).
Simulating sub types
Nesting classes is strange to me in Dlang because it adds a parent pointer to the parent class. I don't see the point of this and it seems like an anti-feature. If we wanting that pattern we could implement it ourselves. I suppose in some cases it can be useful but in my case it breaks logical nesting. I have two classes A and B. I want B to look like it is derived or a member of A. So I want to do A.B when accessing B to explicitly signal that B is from A. e.g., class A { class B { ... BUT I do not want class B to be physically connecting to A. I would like to instantiate it outside of A. I can't do this in Dlang. Regardless of why I want to do this, the fact remains that I can't do it in Dlang. So, the question is, how can I still get the logical behavior? I've tried to put B in a module A, but this doesn't seem to work. In fact, I'm programming from interfaces, interface A { interface B { ... class C : A { class D : A.B { ... So I have for D, analogous to A.B, C.D. D will never be used, I think outside of D, except when inheriting from D to create polymorphic behavior... direct injection will be used along with factories and requiring D to be a physical child of D will just be a pain in the ass(requiring all of C to be implemented I think). Basically, D will never access the parent(they are just wrappers around tight objects. So I don't need the parent pointer, yet I'm forced to do so.
Get attributes of type by string name
how can I get the UDA's of a type that I only know by name and only in a CTFE. I would like to loop over an array of names passed to a me(I don't know their contents beforehand) and get the attributes. I've tried to use a mixin but I can't get the mixin to work on the string name... e.g., mixin("alias a = __traits(getAttributes, "~type~");");
Re: are mixin string templates with functions removed?
On Thursday, 1 August 2013 at 22:26:06 UTC, Dicebot wrote: On Thursday, 1 August 2013 at 22:04:57 UTC, JS wrote: IS A GOING TO BE IN THE BINARY?!?!?! Yes, I'm yelling... just to get the point across about the question I'm trying to get answered. HOW MANY TIMES I NEED TO ANSWER YOUR QUESTION FOR YOU TO NOTICE? Yes. UM, NO, BECAUSE YOU ARE NOT ANSWERING MY QUESTION! I don't know why it is so damn confusing... I didn't say templates, I SAID string mixins of templates. I did a test http://dpaste.dzfl.pl/d8e6ca2a http://dpaste.dzfl.pl/a43b923c What is weird, on my comp, the file sizes are exactly the same, searching for the string only shows up in the one with the template call. So It seems the dmd does not add code for string mixins(even though the function is called, it is smart enough not to add it to the binary)... unless it is somehow encrypting the template(again, I would expect the file size to be smaller... unless it does some type of alignment/padding).
Re: are mixin string templates with functions removed?
On Thursday, 1 August 2013 at 22:13:25 UTC, John Colvin wrote: On Thursday, 1 August 2013 at 22:04:57 UTC, JS wrote: IS A GOING TO BE IN THE BINARY?!?!?! Why don't you try it and see? Disassemble the object file or get your linker of choice to print out some info. I don't have any of the tools to do so at the moment. The point was to see if anyone actually knew this specifically or was just guessing on what should be... I guess I have my answer(e.g., find out yourself = I don't know).
Re: are mixin string templates with functions removed?
On Thursday, 1 August 2013 at 21:17:34 UTC, H. S. Teoh wrote: On Thu, Aug 01, 2013 at 10:06:54PM +0200, JS wrote: [...] Now are you telling me that template A() { void foo() { writeln("asdf"); } } void main() { A!().foo(); } does not create a function foo in the binary? That it is equivalent to just calling writeln("asdf"); directly? (exact same code) [...] I said that every instantiation of a template creates a copy of everything inside. Therefore, A!().foo() will create a copy of A.foo() in the binary. The template itself has no binary representation, in the sense that if you write: template A(int x) { void foo() { writeln(x); } } there is nothing in the binary corresponding with the template A, or the uninstantiated function foo. But if you instantiate A with some value of x, then you will get a copy of A.foo for every value of x that you instantiate the template with. So if you write: A!1.foo(); A!2.foo(); A!3.foo(); Then you will get 3 copies of foo() in your executable, one for each value of x. yes, I understand that... now use a template for a string mixin! template A() { string A() { ... } } ... mixin(A()); IS A GOING TO BE IN THE BINARY?!?!?! Yes, I'm yelling... just to get the point across about the question I'm trying to get answered. the function A is never used at runtime SO it should technically not be in the binary UNLESS dmd treats it as a normal template function then it will(but shouldn't)! e.g., if the compiler smart enough to realize that A(); is different from mixin(A()); (one being compile time and the other not)
Re: are mixin string templates with functions removed?
On Thursday, 1 August 2013 at 18:09:54 UTC, H. S. Teoh wrote: On Thu, Aug 01, 2013 at 07:52:28PM +0200, JS wrote: On Thursday, 1 August 2013 at 17:47:00 UTC, H. S. Teoh wrote: >On Thu, Aug 01, 2013 at 07:12:51PM +0200, John Colvin wrote: >>On Thursday, 1 August 2013 at 17:09:07 UTC, JS wrote: >>>If I have a bunch of templates that are only used for code >>>generation, are they removed in the binary(since they are >>>not >>>needed)? >> >>templates don't exist in binaries. > >Templates are like cookie molds, you use them to generate >lots of >(almost) identical cookies, but you never serve the mold to >the >customer. ;-) > > >T But what about the functions that exist in them? Like I said, cookie molds. You use the mold to press cookies, but only the cookies are served, not the mold. The mold may be very complicated, containing subcookies attached to bigger cookies, but whatever is pressed (i.e., instantiated) is what's served on the dinner plate. The mold always remains in the kitchen. template A() { void A() { B(); } void B() { } } is everything in the template removed 100% or is there junk that the compiler doesn't remove? There is nothing to remove. If you instantiated the template, then you get a copy of everything in it. The number of copies equals the number of distinct instantiations. The template itself is just a mold, an abstract entity that doesn't exist in binary form. What it does is to serve as a mold (hence, "template") to make code. So if you use to make 10 copies of the code, that's what you'll get in your executable. If your template contains 5 functions, then each instantiation produces 5 copies of those functions. Simple as that. Of course, not all code produces binary data -- enum and alias definitions don't produce any binary code, for example -- they're just logical entities that only exist at compile time. So if you have an enum inside a template, it will get copied however many times you instantiate the template, but none of those copies end up in the executable because they're just declarations, not actual code or data. Ok, I'm not talking about the template itself but what is contained in the template. It is obvious that templates can "insert" stuff into the binary. a mixin template can easily do that. Now are you telling me that template A() { void foo() { writeln("asdf"); } } void main() { A!().foo(); } does not create a function foo in the binary? That it is equivalent to just calling writeln("asdf"); directly? (exact same code) e.g., it is the same as void main() { A!().foo(); } cause when I actually debug I see a function call to foo. So, saying that templates are like cookie cutter doesn't prove anything. If I have void main() { } the binary file is is 150kB. If I add import std.stdio; It jumps to 300kB. So the linker and compiler are not removing all untouched code.
Re: Emulating enums
On Thursday, 1 August 2013 at 16:36:34 UTC, Ali Çehreli wrote: On 08/01/2013 03:29 AM, JS wrote: > On Thursday, 1 August 2013 at 05:22:46 UTC, Ali Çehreli wrote: >> On 07/31/2013 06:10 PM, JS wrote: >>> http://dpaste.dzfl.pl/dbb40dbc >>> >>> The code was pared down from a lot of string mixin code generation. I >>> nest the structs because I want a nested enums. I don't want have to >>> have eState and eStateType but eState and eState.Type. >>> >>> Having the ability to nest enums would solve my problem. >>> >>> Regardless, I can almost achieve the effect with nested structs but not >>> quite. >>> >>> In the code, I cannot assign to the struct for some reason even with >>> alias this on iB, which should make State act like the int Value. >>> >>> i.e., >>> >>> b.State.Value = Enums.State.A; >>> >>> works but >>> >>> b.State = Enums.State.A; >>> >>> doesn't >>> >>> It maybe some stupid error on my part but I can't keep my eyes open >>> enough to figure it out... >>> >>> >>> >> >> For that assignment to work, the left-hand side must be assignable. >> However, the property function State() returns Enums.eState by-value. >> >> The following has the same issue: >> >> struct S >> { >> int i_; >> >> @property int i() { >> return i_; >> } >> >> alias i this; >> } >> >> void main() >> { >> auto s = S(); >> s = 42; >> assert(s.i == 42); >> } >> >> Error: cannot implicitly convert expression (42) of type int to S >> >> To compile, i() must return an lvalue: >> >> @property ref int i() { Although, what I said seems more like a workaround because you already had a setter @property. You shouldn't need to make the getter return a reference as well... I guess... I think what is at play here is the current implementation limitation of "a single 'alias this' per type." I think 'alias this' happens to pick the getter perhaps because the getter function is defined first in the class. I don't know... Ali So, a ref'ed getter is the same as a setter? Also, it would see, I'm guessing, that using alias this on a property and having to ref will bypass the setter?
Re: are mixin string templates with functions removed?
On Thursday, 1 August 2013 at 17:53:38 UTC, Ali Çehreli wrote: On 08/01/2013 10:45 AM, H. S. Teoh wrote: On Thu, Aug 01, 2013 at 07:12:51PM +0200, John Colvin wrote: On Thursday, 1 August 2013 at 17:09:07 UTC, JS wrote: If I have a bunch of templates that are only used for code generation, are they removed in the binary(since they are not needed)? templates don't exist in binaries. Templates are like cookie molds, you use them to generate lots of (almost) identical cookies, but you never serve the mold to the customer. ;-) T I think the question is whether the instantiations of such templates are removed. If the instance is used only to initialize an enum, the function shouldn't stay in the binary. Even if the function remains, I think the linker takes care of removing unused functions. Ali I have a lot of code generation templates(only for code). I want to make sure they don't hang around in the binary(even strings they use) as there is no point and it is potentially dangerous(security issues).
Re: are mixin string templates with functions removed?
On Thursday, 1 August 2013 at 17:47:00 UTC, H. S. Teoh wrote: On Thu, Aug 01, 2013 at 07:12:51PM +0200, John Colvin wrote: On Thursday, 1 August 2013 at 17:09:07 UTC, JS wrote: >If I have a bunch of templates that are only used for code >generation, are they removed in the binary(since they are not >needed)? templates don't exist in binaries. Templates are like cookie molds, you use them to generate lots of (almost) identical cookies, but you never serve the mold to the customer. ;-) T But what about the functions that exist in them? e.g., template A() { void A() { B(); } void B() { } } is everything in the template removed 100% or is there junk that the compiler doesn't remove? Oh... and I'm not talking about theoretical... I'm talking about what dmd actually does.
are mixin string templates with functions removed?
If I have a bunch of templates that are only used for code generation, are they removed in the binary(since they are not needed)?
Re: Emulating enums
On Thursday, 1 August 2013 at 16:36:34 UTC, Ali Çehreli wrote: On 08/01/2013 03:29 AM, JS wrote: > On Thursday, 1 August 2013 at 05:22:46 UTC, Ali Çehreli wrote: >> On 07/31/2013 06:10 PM, JS wrote: >>> http://dpaste.dzfl.pl/dbb40dbc >>> >>> The code was pared down from a lot of string mixin code generation. I >>> nest the structs because I want a nested enums. I don't want have to >>> have eState and eStateType but eState and eState.Type. >>> >>> Having the ability to nest enums would solve my problem. >>> >>> Regardless, I can almost achieve the effect with nested structs but not >>> quite. >>> >>> In the code, I cannot assign to the struct for some reason even with >>> alias this on iB, which should make State act like the int Value. >>> >>> i.e., >>> >>> b.State.Value = Enums.State.A; >>> >>> works but >>> >>> b.State = Enums.State.A; >>> >>> doesn't >>> >>> It maybe some stupid error on my part but I can't keep my eyes open >>> enough to figure it out... >>> >>> >>> >> >> For that assignment to work, the left-hand side must be assignable. >> However, the property function State() returns Enums.eState by-value. >> >> The following has the same issue: >> >> struct S >> { >> int i_; >> >> @property int i() { >> return i_; >> } >> >> alias i this; >> } >> >> void main() >> { >> auto s = S(); >> s = 42; >> assert(s.i == 42); >> } >> >> Error: cannot implicitly convert expression (42) of type int to S >> >> To compile, i() must return an lvalue: >> >> @property ref int i() { Although, what I said seems more like a workaround because you already had a setter @property. You shouldn't need to make the getter return a reference as well... I guess... I think what is at play here is the current implementation limitation of "a single 'alias this' per type." I think 'alias this' happens to pick the getter perhaps because the getter function is defined first in the class. I don't know... Ali Yeah, I think I remember that being an issue before which kinda sucks as one doesn't want to have to necessarily return references. alias this should also alias all the overloads. In any case, how long has the multiple alias issue been going on? 10 years?
Named UDA's
I guess D doesn't support named UDA's directly? e.g., @(Name = "My Name", Other = .34) It would be nice to have the ability to have an "attribute" hierarchy where looking up attributes on objects could easily be done. e.g., @(Name = "s", Other = 2) struct s { @(Name = "q", Default_Value = 4) int q = 4; } which would form a hierarchy Attributes[]...[] Which @[s].Attributes = {"Name" = "s", "Other" = 2} (Key/Value pairs) @[s][q].Attributes = {"Name" = "q", "Other" = 2, "Default_Value" = 4 } (attributes are inherited Querying at runtime would be a binary search or O(1) if the object type is known. Anyways, Just an idea I had when trying to make attributes more useful.
Re: Emulating enums
On Thursday, 1 August 2013 at 05:22:46 UTC, Ali Çehreli wrote: On 07/31/2013 06:10 PM, JS wrote: http://dpaste.dzfl.pl/dbb40dbc The code was pared down from a lot of string mixin code generation. I nest the structs because I want a nested enums. I don't want have to have eState and eStateType but eState and eState.Type. Having the ability to nest enums would solve my problem. Regardless, I can almost achieve the effect with nested structs but not quite. In the code, I cannot assign to the struct for some reason even with alias this on iB, which should make State act like the int Value. i.e., b.State.Value = Enums.State.A; works but b.State = Enums.State.A; doesn't It maybe some stupid error on my part but I can't keep my eyes open enough to figure it out... For that assignment to work, the left-hand side must be assignable. However, the property function State() returns Enums.eState by-value. The following has the same issue: struct S { int i_; @property int i() { return i_; } alias i this; } void main() { auto s = S(); s = 42; assert(s.i == 42); } Error: cannot implicitly convert expression (42) of type int to S To compile, i() must return an lvalue: @property ref int i() { Ali Thanks...
Emulating enums
http://dpaste.dzfl.pl/dbb40dbc The code was pared down from a lot of string mixin code generation. I nest the structs because I want a nested enums. I don't want have to have eState and eStateType but eState and eState.Type. Having the ability to nest enums would solve my problem. Regardless, I can almost achieve the effect with nested structs but not quite. In the code, I cannot assign to the struct for some reason even with alias this on iB, which should make State act like the int Value. i.e., b.State.Value = Enums.State.A; works but b.State = Enums.State.A; doesn't It maybe some stupid error on my part but I can't keep my eyes open enough to figure it out...
Re: Alias/template for value
On Wednesday, 31 July 2013 at 11:15:31 UTC, Joseph Rushton Wakeling wrote: Hi all, When playing with the graph library code, I noticed something odd. Here's a function to calculate the neighbours of a vertex: auto neighbours(immutable size_t v) { immutable size_t start = _sumTail[v] + _sumHead[v]; immutable size_t end = _sumTail[v + 1] + _sumHead[v + 1]; if(!_cacheNeighbours[v]) { size_t j = start; foreach (i; _sumTail[v] .. _sumTail[v + 1]) { _neighbours[j] = _head[_indexTail[i]]; ++j; } foreach (i; _sumHead[v] .. _sumHead[v + 1]) { _neighbours[j] = _tail[_indexHead[i]]; ++j; } assert(j == end); _cacheNeighbours[v] = true; } return _neighbours[start .. end]; } Now, I noticed that if instead of declaring the variables start, end, I instead manually write out these expressions in the code, I get a small but consistent speedup in the program. So, I'm curious (i) Why? As I'd have assumed the compiler could optimize away unnecessary variables like this, and (ii) is there a way of declaring start/end in the code such that at compile time the correct expression will be put in place where it's needed? I'm guessing some kind of template solution, but I didn't get it working (I probably need to study templates more:-). (... knocks head against wall to try and dislodge current micro-optimization obsession ...) There is no telling, as bear said, compare the disassemblies(you can try it on dpaste and compare). I do not believe D's code generation is optimal from what I have seen(at least for DMD). It could be cache misses due to pipelining issues(the order of instructions matter) or other weird stuff. It could be that when you alias start and end, D ends up using a different algorithm that somehow changes the code generation. I don't think D's code generation is even close to being as mature as many of the common C++ compilers.
Weird bug in IFTI
http://dpaste.dzfl.pl/cdabf9fa But adding one more parameter gives an error! http://dpaste.dzfl.pl/a5cfac37 Template has no effect simply because I added an parameter with a default?!?!?!?
Re: Get template name
On Tuesday, 30 July 2013 at 11:25:38 UTC, Dicebot wrote: On Tuesday, 30 July 2013 at 11:04:10 UTC, JS wrote: 1. No, the code actually will print the message but the error shows up right after(well, depends on which error, the one I get inside templates works fine except the without the assignment/alias, no further compilation is done due to the error(but the message is printed). http://dpaste.dzfl.pl/e232e3ac And what is a stub function? http://dpaste.dzfl.pl/133230f8 http://dpaste.dzfl.pl/c4cb0dfb For some reason the code doesn't work on my machine... works in dpaste though... My machine just returns an empty string for __FUNCTION__. I think this is a bug somewhere... I'll post another post showing it.
Re: use template function without assignment
BTW, when I use mixin in my code, the error goes away but no pragma msg is produced, so it is not a solution.
Re: use template function without assignment
On Tuesday, 30 July 2013 at 20:34:32 UTC, Ali Çehreli wrote: On 07/30/2013 12:09 PM, JS wrote: > I already stated why this is not a proper example, I'm not using Pragma > in run time code(for lack of a better term). > > module main; > > import std.stdio; > > > template Pragma(alias amsg) > { > void Pragma(string file = __FILE__) > { > pragma(msg, amsg); > } > } > > template t() > { > Pragma!("help, this does not work!"); > } > > void main() > { > enum msg = "hello"; > Pragma!msg; > t!(); > } Thank you. Now we have something to work on. The program above produces the following error: Error: no identifier for declarator Pragma!"help, this does not work!" The error is fixed by adding a mixin: mixin Pragma!("help, this does not work!"); Or just assigning it to enum... both are not great solutions... Despite another error it actually works: hello help, this does not work!<-- IT WORKED Error: t!() has no effect The second error is fixed by another mixin: mixin t!(); Perhaps the example is too simplistic. Still, let's stay with it for further issues. Ali I think that such behavior should not be an error but possibly a warning, if at all. And if you cared to read what I initially posted you would realize I already explained the same thing. The example maybe more clear but I stated, maybe in some convoluted and jumped way, that Pragma doesn't work *in* templates.. "When I try to use void instead of string and do something like Pragma!(msg) I get an error that the template has no effect." and later "It's goal is to debug templates and essentially just wrapping pragma to supply the __FILE__ info automatically. e.g., instead of having to do pragma(msg, __FILE__~amsg); I want to do Pragma!(amsg); "
Re: use template function without assignment
On Tuesday, 30 July 2013 at 18:38:23 UTC, Ali Çehreli wrote: On 07/30/2013 06:16 AM, Meta wrote: > Can you post some more code that exhibits exactly the behaviour you're > describing? I can't replicate the problem you're having with the code > you provided (nor the code *I* provided). Ditto. JS, I wrote the following code for you. Could you please start with it and show us the problem that we are trying to solve. template Pragma(alias amsg) { void Pragma(string file = __FILE__) { pragma(msg, amsg); } } void main() { enum msg = "hello"; Pragma!msg; } Ali I already stated why this is not a proper example, I'm not using Pragma in run time code(for lack of a better term). module main; import std.stdio; template Pragma(alias amsg) { void Pragma(string file = __FILE__) { pragma(msg, amsg); } } template t() { Pragma!("help, this does not work!"); } void main() { enum msg = "hello"; Pragma!msg; t!(); }
Re: Get template name
On Tuesday, 30 July 2013 at 11:25:38 UTC, Dicebot wrote: On Tuesday, 30 July 2013 at 11:04:10 UTC, JS wrote: 1. No, the code actually will print the message but the error shows up right after(well, depends on which error, the one I get inside templates works fine except the without the assignment/alias, no further compilation is done due to the error(but the message is printed). http://dpaste.dzfl.pl/e232e3ac And what is a stub function? http://dpaste.dzfl.pl/133230f8 The first is what I already do, but it is messy. The second may work, it is also a bit messy(requiring an extra function) but might solve the problem...
Re: Get template name
On Tuesday, 30 July 2013 at 10:45:26 UTC, Dicebot wrote: On Tuesday, 30 July 2013 at 06:45:31 UTC, JS wrote: void f() { pragma(msg, __FUNCTION__); } template t() { pragma(msg, __FUNCTION__); } void main(string[] argv) { readln(); } the function displays main.f. The template displays nothing. I'd prefer it to display main.t! or something unique so I can use it as a hash. 1) Pragma's are printed upon instantiation. You need to use something like alias _ = t!(); to force it. 2) You may workaround it by wrapping pragma in stub function. Though I do agree that something like __ENCLOSING__ may be useful (assuming it also covers aggregates) 1. No, the code actually will print the message but the error shows up right after(well, depends on which error, the one I get inside templates works fine except the without the assignment/alias, no further compilation is done due to the error(but the message is printed). And what is a stub function?
Re: use template function without assignment
On Tuesday, 30 July 2013 at 07:12:11 UTC, Namespace wrote: On Monday, 29 July 2013 at 23:09:20 UTC, JS wrote: I have created a template Pragma that emulates pragma but better, the problem is that I have to assign it to something which is very redundant in my code: enum temp = Pragma!(msg) e.g., template Pragma(alias amsg) { string Pragma(string file = __FILE__) { pragma(msg, amsg); return ""; } } When I try to use void instead of string and do something like Pragma!(msg) I get an error that the template has no effect. It does have an effect but what it is complaining about is exactly what I want. I've tried all kinds of combinations(mixins work but I then can't ise __FILE__) and nothing works. Maybe someone has an idea. You could call your template in a static CTor: import std.stdio; template Pragma(alias amsg) { void Pragma(string file = __FILE__) { pragma(msg, amsg); } } static this() { Pragma!("foo")(); } void main() { writeln("Hello world!"); } Maybe this helps? This is useless. It's goal is to debug templates and essentially just wrapping pragma to supply the __FILE__ info automatically. e.g., instead of having to do pragma(msg, __FILE__~amsg); I want to do Pragma!(amsg); where Pragma custom formats the error or info message with the location where the message was initiated. Sticking it in a ctor will only print a message from that location.
Re: use template function without assignment
On Tuesday, 30 July 2013 at 01:19:23 UTC, Meta wrote: On Tuesday, 30 July 2013 at 01:06:39 UTC, Meta wrote: Does this code do what you want, or are there other requirements as well? void Pragma(alias amsg)(string file = __FILE__) { pragma(msg, amsg); } Actually, sorry, that's the exact same code, just with some syntactic sugar. To avoid the "expression has no effect" problem, you could use an alias instead of an enum. You're getting the error when you try to use pragma in the "global" scope, right? void Pragma(alias amsg)(string file = __FILE__) { pragma(msg, amsg); } alias temp = Pragma!("test"); In general, D doesn't have top-level expressions like what I think you want to do here. Maybe somebody else knows a way to work around that. If I use enum or alias they both have the same problem(The annoying mandatory assignment). I see the reason why it does it but I don't know it because in this case I do not want an effect. (pragma has no "effect" which is what I'm trying to emulate... works well except for that annoying quirk of having to assign it to something). BTW, is void Pragma(alias amsg)(string file = __FILE__) short for template Pragma(alias amsg) { void Pragma(string file = __FILE__) or is there some real difference? I could potential do something like template Group(alias G1) { void Group(alias G2)(int s) { writeln(s); } } Group!("x")("y")(3); // doesn't work, Group!("x")!("y")(3); // doesn't work
Re: Get template name
On Tuesday, 30 July 2013 at 06:36:12 UTC, Dicebot wrote: On Monday, 29 July 2013 at 23:02:57 UTC, JS wrote: __FUNCTION__ does not return anything when used in templates. For debugging purposes I sometimes use pragma(msg, template_name); (with template_name being the name of the template assigned an enum) It can be relatively trivial or incredibly difficult, depending on exact string output for a given template you want get and set of template types supported. I just want the current template name in the current scope. I know it seems trivial but it would help me reduce boilerplate code. I'm using it to debug and use the template name as a way to turn on debugging for specific templates if I need to analyze their behavior(lots of code generating templates that may have bugs). A similar feature would end up being needed for functions when I log functions debug output. With such a function I can just copy and paste the line to display the output rather than copy paste modify(replace the old template name with the new). I don't need the template name of a template that called it... that is different, possibly useful but not required. void f() { pragma(msg, __FUNCTION__); } template t() { pragma(msg, __FUNCTION__); } void main(string[] argv) { readln(); } the function displays main.f. The template displays nothing. I'd prefer it to display main.t! or something unique so I can use it as a hash.
use template function without assignment
I have created a template Pragma that emulates pragma but better, the problem is that I have to assign it to something which is very redundant in my code: enum temp = Pragma!(msg) e.g., template Pragma(alias amsg) { string Pragma(string file = __FILE__) { pragma(msg, amsg); return ""; } } When I try to use void instead of string and do something like Pragma!(msg) I get an error that the template has no effect. It does have an effect but what it is complaining about is exactly what I want. I've tried all kinds of combinations(mixins work but I then can't ise __FILE__) and nothing works. Maybe someone has an idea.
Get template name
__FUNCTION__ does not return anything when used in templates. For debugging purposes I sometimes use pragma(msg, template_name); (with template_name being the name of the template assigned an enum) I would like to make this more general such as pragma(msg, mixin(__FUNCTION_NAME__)); e.g., template t() { enum t = "asdf"; pragma(msg, t); } same but more general template t() { enum t = "asdf"; pragma(msg, __FUNCTION_NAME__); } (please don't ask why I would do this... this is a simple example, my case is more complex, trust me that I have a reason)
untuple a tuple
if I have something like template t(args...) { pragma(msg, args); } it prints out args in a tuple... e.g., tuple!(...) I do not want it to print out the tuple!(). I can write my own pragma and pass each arg to it (e.g., pragma(msg, arg[0], arg[1], ...)) but this is not very general and requires a lot of static if's (one for each possible n). Is it possible to "untuple"?
Re: Generic string join
On Monday, 29 July 2013 at 09:01:36 UTC, JS wrote: Here is a optimal generic string joiner that maximizes compiler optimization, allows for a variable number of arguments that can be strings or arrays of strings. http://dpaste.dzfl.pl/0a021e1f Drawbacks: 1. Static if explosion 2. Not elegant 3. Only works with RT strings or RT string arrays, would be nice to work with chars and possibly others. 4. Does not have the ability to use book ends delimitation... not difficult to do but just more bloat-code. 5. Would be nice to allow apply a lambda to each "element". Again, not hard but requires all those special cases to deal with proper delimitation due to the recursion required. 6. Requires a mixin statement... this is not pretty at all. One can't wrap the mixin in a normal function call because it defeats the purpose of optimization(CT strings will be passed as variables and not optimized by the CT). etc... While I have some code to flatten such arrays before delimitation, which would probably make it much easier, which is the way I started, the code was going to turn out to be the same in the end as the flattener, so I just modified the code(basically use string concatenation instead of tuple concatenation). Anyways, maybe someone has a good idea how to improve the code to achieve the same results. Note in in the test, every possible 3-combination is tried, which I think is good enough to prove the validity of the code. BTW, one can wrap the template to remove the mixin in #6 but this is not very satisfactory as it has a much higher performance hit for CT joining. template t(T...) { string t(string d, T args) { return mixin(tJoin!(",", args)); } } mixin(tJoin!(",", "a", "b")) is just 4 instructions max. Using t is about 10-15 times that(although I'm not sure if inlining will solve that).
Generic string join
Here is a optimal generic string joiner that maximizes compiler optimization, allows for a variable number of arguments that can be strings or arrays of strings. http://dpaste.dzfl.pl/0a021e1f Drawbacks: 1. Static if explosion 2. Not elegant 3. Only works with RT strings or RT string arrays, would be nice to work with chars and possibly others. 4. Does not have the ability to use book ends delimitation... not difficult to do but just more bloat-code. 5. Would be nice to allow apply a lambda to each "element". Again, not hard but requires all those special cases to deal with proper delimitation due to the recursion required. 6. Requires a mixin statement... this is not pretty at all. One can't wrap the mixin in a normal function call because it defeats the purpose of optimization(CT strings will be passed as variables and not optimized by the CT). etc... While I have some code to flatten such arrays before delimitation, which would probably make it much easier, which is the way I started, the code was going to turn out to be the same in the end as the flattener, so I just modified the code(basically use string concatenation instead of tuple concatenation). Anyways, maybe someone has a good idea how to improve the code to achieve the same results. Note in in the test, every possible 3-combination is tried, which I think is good enough to prove the validity of the code.
Re: static foreach and inline if
On Sunday, 28 July 2013 at 09:11:55 UTC, anonymous wrote: On Sunday, 28 July 2013 at 08:38:40 UTC, JS wrote: On Sunday, 28 July 2013 at 08:38:01 UTC, JS wrote: On Sunday, 28 July 2013 at 08:30:17 UTC, QAston wrote: On Saturday, 27 July 2013 at 17:14:35 UTC, JS wrote: I'd like to have foreach and inline if in templates: inline if is available as std.traits.Select This doesn't work for variadic args... Something Split!(Cond, targ..., split, fargs) is what I need... where split somehow signals the split between the two. Obviously I mean Select! template Wrap(Stuff ...) {alias unwrap = Stuff;} Select!(cond, Wrap!targs, Wrap!fargs).unwrap I tried to do that with tuple which is identical to your wrap but was not successful... possibly because I did not unwrap it...
Re: static foreach and inline if
The following works but is somewhat of a hack... module main; import std.stdio, std.typetuple; struct tTupleSplit { } template tIndexOf(T, args...) { static if (staticIndexOf!(T, args) < 0) enum tIndexOf = args.length; else enum tIndexOf = staticIndexOf!(T, args); } template tMin(alias a, alias b) { static if (a < b) alias tMin = a; else alias tMin = b; } template tIf(alias cond, args...) { enum sp = tIndexOf!(tTupleSplit, args); static if (cond) alias tIf = args[0..tMin!($,sp)]; else alias tIf = args[tMin!($,sp+1)..$]; } int main(string[] argv) { alias x = tIf!(false, "a", tTupleSplit, "b"); writeln(x); readln(); return 0; }
Re: static foreach and inline if
On Sunday, 28 July 2013 at 08:30:17 UTC, QAston wrote: On Saturday, 27 July 2013 at 17:14:35 UTC, JS wrote: I'd like to have foreach and inline if in templates: inline if is available as std.traits.Select This doesn't work for variadic args... Something Split!(Cond, targ..., split, fargs) is what I need... where split somehow signals the split between the two.
Re: static foreach and inline if
On Sunday, 28 July 2013 at 08:38:01 UTC, JS wrote: On Sunday, 28 July 2013 at 08:30:17 UTC, QAston wrote: On Saturday, 27 July 2013 at 17:14:35 UTC, JS wrote: I'd like to have foreach and inline if in templates: inline if is available as std.traits.Select This doesn't work for variadic args... Something Split!(Cond, targ..., split, fargs) is what I need... where split somehow signals the split between the two. Obviously I mean Select!
Array reduction
I have the following code, in which I would like to try and simplify tUnrollArgs which I find to be a mess because of all the redundant code in it(having a static ternary if would definitely simplify things. (the tIf would help if I could "box" the args in an array easily so I could allow for a false statement too). In any case, I am trying to get the tUnrollArgs2 working using the tForEach. This can simplify it a great deal. The problem is that the lambda expression must change for each argument passed to be able to handle arrays. That is, I need to be able to call tForEach like tForEach!((isAny!(args) x) { ... }, args); where isAny is sort of a compound type of all the types used in args. That is, so I can handle T and T[]. (right now I'm just using the type of the first argument, which is not always correct) Any ideas how I can solve this problem? module main; import std.stdio, std.traits; template tuple(args...) { alias tuple = args; } template tIf(alias cond) { alias tIf = tuple!(); } template tIf(alias cond, T...) { static if (T.length == 0) alias tIf = tuple!(); static if (cond) alias tIf = T; else alias tIf = tuple!(); } template tForEach(alias func, args...) { static if (args.length == 0) alias tForEach = tuple!(); else { static assert(is(typeof(func(args[0]))), "tForEach: function not valid for argument : "~typeof(args[0]).stringof); alias tForEach = tuple!(func(args[0]), tIf!(args.length > 1, tForEach!(func, args[1..$]))); } } template tUnrollArgs(args...) { static if (args.length > 0) pragma(msg, ">"~args.stringof~" : "~typeof(args[0]).stringof~" - "~Unqual!(typeof(args[0])).stringof); static if (args.length == 0) { alias tUnrollArgs = tuple!(); } else static if (is(typeof(args[0]) == string) || is(Unqual!(typeof(args[0])) == string)) { pragma(msg, "1: is string"); static if (args.length == 1) alias tUnrollArgs = tuple!(args[0]); else alias tUnrollArgs = tuple!(args[0], tUnrollArgs!(args[1..$])); } else static if (isArray!(typeof(args[0]))) { pragma(msg, "2: is array"); static if (__traits(compiles, { enum x = args[0]; })) { static if (args[0].length == 0) { pragma(msg, "2: is empty"); alias tUnrollArgs = tuple!(tUnrollArgs!(args[1..$])); } else static if (is(Unqual!(typeof(args[0])) == string)) { pragma(msg, "4: is string"); alias tUnrollArgs = tuple!(tUnrollArgs!(args[0]), tIf!(args.length > 1, tUnrollArgs!(args[1..$]))); } else { pragma(msg, "5: unrolling array"); alias tUnrollArgs = tuple!(tUnrollArgs!(args[0][0]), tIf!(args.length > 1, tUnrollArgs!(args[0][1..$], args[1..$]))); } } else { static if(args.length > 1) alias tUnrollArgs = tuple!(args[0], tUnrollArgs!(args[1..$])); else alias tUnrollArgs = args[0]; } } else alias tUnrollArgs = args; } template tUnrollArgs2(args...) { alias tUnrollArgs2 = tForEach!((Unqual!(typeof(args[0])) x) { if (is(Unqual!(typeof(x)) == string)) { return x~""; } else if (isArray!(Unqual!(typeof(x { return x~""; } }, args); } void main(string[] argv) { immutable string[] z = ["111", "222"]; auto x = ["3", "4"]; //writeln(tUnrollArgs!("qXX", ["a", "bYY"], z, x,"cTT")); //writeln( //tForEach!((string x) => x ~ "#", tUnrollArgs2!("qXX", z, "a")) //); writeln(tUnrollArgs2!("a", z, "b")); readln(); }
Re: static foreach and inline if
On Saturday, 27 July 2013 at 19:06:48 UTC, anonymous wrote: On Saturday, 27 July 2013 at 17:14:35 UTC, JS wrote: The tIf doesn't work properly but I'm not sure why [...] template tIf(bool cond, alias T) Lower case 'f' here, ... { static if (cond) alias tIF = T; else alias tIF = tuple!(); ... upper case 'F's here. Thanks... I'm glad someone can see the tree's from the forest. (I originally was going to use all caps but changed it at the last minute.
Re: Closures not yet supported in CTFE's
On Saturday, 27 July 2013 at 17:18:29 UTC, H. S. Teoh wrote: On Sat, Jul 27, 2013 at 06:47:04PM +0200, JS wrote: When I try to pass a lambda to a template, I get the subject error. (string x) => { return x~"1"; } Drop the "=>", that syntax doesn't do what you think it does. But when I jsut do (string x) => x~"1" it works Come on!!! Y'know, it would really help if you (1) show the full code that's failing, and (2) calm down before posting to the forum. I understand that compiler bugs/limitations can be very aggravating, but you're much more likely to get a helpful reply that way. The code wouldn't help because that is not where the error is at. It is because I thought => was used for lambda's as it is in C#. I don't know why there is a special syntax for a direct return. (string x) => { return x; } is trying to return a function that returns x using closure because of x is outside the inside function. (string x) { return x; } is what I was trying to do. I knew that (string x) => ...; was simple notation for return ... but didn't think I was returning a function in any way.
Re: static foreach and inline if
BTW, it works with static if's, I'm trying to use an inline if to reduce redundant code since there is no static ?:.
static foreach and inline if
I'd like to have foreach and inline if in templates: The tIf doesn't work properly but I'm not sure why template tuple(args...) { alias tuple = args; } template tIf(bool cond) { alias tIf = tuple!(); } template tIf(bool cond, alias T) { static if (cond) alias tIF = T; else alias tIF = tuple!(); } template tForEach(alias func, args...) { pragma(msg, args); static if (args.length == 0) alias tForEach = tuple!(); else { static assert(is(typeof(func(args[0]))), "tForEach: function not valid for argument : "~typeof(args[0]).stringof); pragma(msg, "1"~typeof(args[0]).stringof); alias tForEach = tuple!(func(args[0]), tIf!(args.length > 1, tForEach!(func, args[1..$]))); } } e.g., writeln(tForEach((string x) => x ~ ";", "a", "b")); should print a;b;
Closures not yet supported in CTFE's
When I try to pass a lambda to a template, I get the subject error. (string x) => { return x~"1"; } But when I jsut do (string x) => x~"1" it works Come on!!!
Re: Module-based programming
On Friday, 26 July 2013 at 11:58:13 UTC, John Colvin wrote: On Friday, 26 July 2013 at 11:42:25 UTC, JS wrote: On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote: I'm confused when it comes to modules. I've read somewhere that modules are basically 'singleton classes' and that anything that doesn't need its own state should not needlessly be put inside a class. But what if I want to create a simple OpenGL shader object. Do I create a class like this: class Shader { // Method // Method // Method // Method // Field // Field // Field } Or do I have a structure that I operate on via module methods? (C-style, basically) struct Shader { // Field // Field // Field } // Method // Method // Method // Method It's probably clear to you guys, but I'm stumped. Thanks for any answers Non-member methods require you to pass the object you want to modify... do you really want to do all that extra typing? It's your choice... you wanna program in C or C++? Is it really extra typing? Depending on how you format your code, you might just be swapping a '.' for a ',' Also, we have UFCS (universal function call syntax): "foo(x, y, z)" can be written as "x.foo(y, z)" But what about protection semantics? Access to this? Properties? Virtual functions?
Re: Module-based programming
On Friday, 26 July 2013 at 09:12:27 UTC, Land wrote: I'm confused when it comes to modules. I've read somewhere that modules are basically 'singleton classes' and that anything that doesn't need its own state should not needlessly be put inside a class. But what if I want to create a simple OpenGL shader object. Do I create a class like this: class Shader { // Method // Method // Method // Method // Field // Field // Field } Or do I have a structure that I operate on via module methods? (C-style, basically) struct Shader { // Field // Field // Field } // Method // Method // Method // Method It's probably clear to you guys, but I'm stumped. Thanks for any answers Non-member methods require you to pass the object you want to modify... do you really want to do all that extra typing? It's your choice... you wanna program in C or C++?
Re: Can't use variadic arguments to functions that use templates
On Tuesday, 23 July 2013 at 19:14:26 UTC, H. S. Teoh wrote: On Tue, Jul 23, 2013 at 08:54:12PM +0200, Jesse Phillips wrote: On Tuesday, 23 July 2013 at 16:22:38 UTC, JS wrote: >On Tuesday, 23 July 2013 at 16:15:03 UTC, Jesse Phillips >wrote: >>On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote: >>>I don't think you understand(or I've already got >>>confused)... >>> >>>I'm trying to use B has a mixin(I don't think I made this >>>clear). I can't use it as a normal function. e.g., I can't >>>seem to do mixin(B(t)). If I could, this would definitely >>>solve my problem. >>...[Code]... >What good does that do? > >What if I want to use a run-time variable in the mix? Ah, I understand now you're interested in: string concat(alias Data...)() { ... } This does not exist, but maybe it should... I don't know of a workaround to get this behavior. Is this by any chance related to that other thread about compile-time optimized join()? 'cos if it is, I've already solved the problem via templates: import std.stdio; template tuple(args...) { alias tuple = args; } /** * Given a tuple of strings, returns a tuple in which all adjacent compile-time * readable strings are concatenated. */ template tupleReduce(args...) { static if (args.length > 1) { static if (is(typeof(args[0])==string) && __traits(compiles, { enum x = args[0]; })) { static if (is(typeof(args[1])==string) && __traits(compiles, { enum x = args[1]; })) { alias tupleReduce = tupleReduce!(args[0] ~ args[1], args[2..$]); } else { alias tupleReduce = tuple!(args[0], args[1], tupleReduce!(args[2..$])); } } else { alias tupleReduce = tuple!(args[0], tupleReduce!(args[1..$])); } } else { alias tupleReduce = args; } } void main() { string x = "runtime1"; string y = "runtime2"; auto arr = [ tupleReduce!("a", "b", x, "c", "d", y, "e", "f", "g", x) ]; writeln(arr); } The output is: ["ab", "runtime1", "cd", "runtime2", "efg", "runtime1"] All compile-time readable strings in the list have been concatenated at compile-time. T Thanks, I'll check it out when I get a chance and report back. It looks like it solves the problem.
Re: Can't use variadic arguments to functions that use templates
On Tuesday, 23 July 2013 at 16:15:03 UTC, Jesse Phillips wrote: On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote: I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem. I'll stick with the reduced example, maybe you can apply it to the real world: template B(T...) { string B(T b) { string s; foreach(i, Type; T) s ~= Type.stringof ~ " " ~ b[i] ~ ";\n"; return s; } } void main() { enum forced = B("x", "a", "b"); pragma(msg, forced); mixin(forced); } What good does that do? What if I want to use a run-time variable in the mix?
Re: Can't use variadic arguments to functions that use templates
On Monday, 22 July 2013 at 16:48:56 UTC, Jesse Phillips wrote: On Sunday, 21 July 2013 at 07:22:08 UTC, JS wrote: void foo(T...)(T t) { pragma(msg, B(t)); } void main() { foo("x", "a", "b"); din.getc(); } does work. I need to have B generate compile time code so it is efficient. Your method calls an actual function at runtime so it is nearly as fast as it can be. My method doesn't make any calls, your foo is a called at runtime. There is no way to observe a function at compile time; ctfeWriteln does not exist. Also don't stringof variable v (I assume you want the value and not the symbol concatenated. template B(T...) { string B(T b) { string s; foreach(Type; T) pragma(msg, Type.stringof); foreach(v; b) s ~= v; return s; } } string foo(T...)(T t) { return B(t); } void main() { enum forced = foo("x", "a", "b"); pragma(msg, forced); din.getc(); } I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem. Here is a real world example: template VariadicLoop(T...) { pragma(msg, T); string VariadicLoop(T t) { string s; foreach(k; T) s ~= k.stringof; foreach(v; t) s ~= v; return s; } //enum tVariadicLoop = eval(); //pragma(msg, tVariadicLoop); } string join(T...)(string delim, T t) { return mixin(VariadicLoop(t)); } VariadicLoop should join the strings passed to join(producing whatever code is necessary to do this efficiently. e.g., join(",", "a", s) should result in the code for join: { return "a"~","~s; // s maybe t[1] or something } This is the most efficient way to join rather than using a foreach over an array of strings or something or another. (VariadicLoop could handle string[]'s and insert the appropriate code to join them) The goal I'm trying to solve is efficiently deal with variadic arguments that are compile time calculable along with mixing in the runtime aspect. Basically: get the compiler to do all the work it can before having it done at runtime. if we are passing string literals to join then they can be joined at compile time. If we are passing a combination of string literals, string variables, and string arrays then we deal with each part efficiently as possible.
Re: Dpaste vs dmd 2.063.2 errors
On Tuesday, 23 July 2013 at 12:59:11 UTC, monarch_dodra wrote: On Tuesday, 23 July 2013 at 12:26:31 UTC, JS wrote: http://dpaste.dzfl.pl/27ca3fbd The code compiles fine on my computer. On DPaste there is all kinds of errors(when fixing one other errors pop up. I am compiling to 32-bit binary and that is the only real difference I can see, but surely it wouldn't result in such errors? The first error: /d547/f451.d(227): Error: unterminated character constant /d547/f451.d(227): Error: unterminated character constant /d547/f451.d(227): Error: found '41U' when expecting ')' makes no sense as far as I can tell unless my expand code generation templates are messed up. If someone wouldn't mind trying to compile the code and see if the errors are similar to dpaste I'd appreciate it. (I don't want to end up writing code that is very bad(even though this is just proof of concept code) and will end up breaking) I'm getting some compile errors, because you are trying to cram a size_t into a int: Thanks. No idea about the inden error? Any idea what command line switch is used to turn on warnings and errors about casting? (I've started using -w and -wi)
Dpaste vs dmd 2.063.2 errors
http://dpaste.dzfl.pl/27ca3fbd The code compiles fine on my computer. On DPaste there is all kinds of errors(when fixing one other errors pop up. I am compiling to 32-bit binary and that is the only real difference I can see, but surely it wouldn't result in such errors? The first error: /d547/f451.d(227): Error: unterminated character constant /d547/f451.d(227): Error: unterminated character constant /d547/f451.d(227): Error: found '41U' when expecting ')' makes no sense as far as I can tell unless my expand code generation templates are messed up. If someone wouldn't mind trying to compile the code and see if the errors are similar to dpaste I'd appreciate it. (I don't want to end up writing code that is very bad(even though this is just proof of concept code) and will end up breaking)
Re: Code generation tricks
On Monday, 22 July 2013 at 21:04:42 UTC, John Colvin wrote: On Sunday, 21 July 2013 at 17:24:11 UTC, JS wrote: This seems to be a somewhat efficient string splitter http://dpaste.dzfl.pl/4307aa5f The basic idea is for(int j = 0; j < s.length; j++) { mixin(ExpandVariadicIf!("??Cs[j]??s[j..min(s.length-1, j + %%L)]::", "d", " if (r.length <= i) r.length += 5; if (j != 0) { r[i++] = s[oldj..j]; oldj = j + %%L; } else oldj = %%L; j += %%L; continue;", T)); } ExpandVariadicIf creates a series of if's for each variadic argument. There is some strange formatting(just some crap I threw together to get something working) but it boils down to generating compile time code that minimizes computations and lookups by directly using the known compile time literals passed. IMO these types of functions seem useful but ATM are just hacks. Hopefully there is a better way to do these sorts of things as I find them pretty useful. One of the big issues not being able to pass a variadic variable to a template directly which is why the formatting string is necessary(You can pass the typetuple to get the types and size but not the compile time values if they exist. I think int this case a variadic alias would be very useful. alias T... => alias T0, alias T1, etc (e.g. T[0] is an alias, T.length is number of aliases, etc...) In any case, maybe someone has a good way to make these things easier and more useful. Being able to handle variadic types and values in a consistent and simple way will make them moreful. How does this perform compared to naive/phobos splitting? I don't know... probably not a huge difference unless phobo's is heavily optimized. With just one delim, there should be no difference. With 100 delim literals, it should probably be significant, more so when chars are used. If the compiler is able to optimize slices of literal strings then it should be even better. Heres my test code that you might be able to profile if you want: http://dpaste.dzfl.pl/2f10d24a The code has a bunch of errors on it but compiles fine on mine. Must be some command line switch or something. The Expand templates simply allow one to expand the variadic args into compile time expressions. e.g., we can do if (a == b) with normal args but not with variargs... the templates help accomplish that. (I'm sure there are better ways... think of the code as proof of concept).
Re: Code generation tricks
On Monday, 22 July 2013 at 21:04:42 UTC, John Colvin wrote: On Sunday, 21 July 2013 at 17:24:11 UTC, JS wrote: This seems to be a somewhat efficient string splitter http://dpaste.dzfl.pl/4307aa5f The basic idea is for(int j = 0; j < s.length; j++) { mixin(ExpandVariadicIf!("??Cs[j]??s[j..min(s.length-1, j + %%L)]::", "d", " if (r.length <= i) r.length += 5; if (j != 0) { r[i++] = s[oldj..j]; oldj = j + %%L; } else oldj = %%L; j += %%L; continue;", T)); } ExpandVariadicIf creates a series of if's for each variadic argument. There is some strange formatting(just some crap I threw together to get something working) but it boils down to generating compile time code that minimizes computations and lookups by directly using the known compile time literals passed. IMO these types of functions seem useful but ATM are just hacks. Hopefully there is a better way to do these sorts of things as I find them pretty useful. One of the big issues not being able to pass a variadic variable to a template directly which is why the formatting string is necessary(You can pass the typetuple to get the types and size but not the compile time values if they exist. I think int this case a variadic alias would be very useful. alias T... => alias T0, alias T1, etc (e.g. T[0] is an alias, T.length is number of aliases, etc...) In any case, maybe someone has a good way to make these things easier and more useful. Being able to handle variadic types and values in a consistent and simple way will make them moreful. How does this perform compared to naive/phobos splitting? I don't know... probably not a huge difference unless phobo's is heavily optimized. With just one delim, there should be no difference. With 100 delim literals, it should probably be significant, more so when chars are used. If the compiler is able to optimize slices of literal strings then it should be even better. http://dpaste.dzfl.pl/2f10d24a The code has a bunch of errors on it but compiles fine on mine. Must be some command line switch or something.
Re: Why is size_t unsigned?
On Monday, 22 July 2013 at 12:51:31 UTC, Andrej Mitrovic wrote: On 7/22/13, JS wrote: foreach doesn't allow you to modify the index to skip over elements. It does: - import std.stdio; void main() { int[] x = [1, 2, 3, 4, 5]; foreach (ref i; 0 .. 5) { writeln(x[i]); ++i; } } - Writes: 1 3 5 Cool... This should make life easier! Thanks.
Re: Why is size_t unsigned?
On Monday, 22 July 2013 at 07:12:07 UTC, monarch_dodra wrote: On Monday, 22 July 2013 at 03:47:36 UTC, JS wrote: Doing simple stuff like for(int i = 0; i < s.length - 1; i++) fails catastrophically if s is empty. To make right one has to reduce performance by writing extra checks. Not really, you could instead just write your loop correctly. 1. Don't loop on int, you are handling a size_t. 2. Avoid substractions when handling unsigned. for(size_t i = 0; i + 1 < s.length; i++) Problem solved? Oh sure... problem solved... rrghhhtt. how about s[i - 1..n]? You going to go throw some ifs around the statement that uses that? Use a ternary if? So I'm forced to use a longer more verbose method, and also introduce bugs, because the most obvious, simplest, and logical solution, s[max(0, i-1)..n] won't work.
Re: Why is size_t unsigned?
On Monday, 22 July 2013 at 04:31:12 UTC, H. S. Teoh wrote: On Mon, Jul 22, 2013 at 05:47:34AM +0200, JS wrote: Doing simple stuff like for(int i = 0; i < s.length - 1; i++) fails catastrophically if s is empty. To make right one has to reduce performance by writing extra checks. I'm not sure if it's your intention, but your code above has an off-by-1 error (unless you were planning on iterating over one less element than there are). yeah, I know... There seems to be no real good reason why size_t is unsigned... [...] The reason is because it must span the range of CPU-addressable memory addresses. Note that due to way virtual memory works, that may have nothing to do with the actual size of your data (e.g. on Linux, it's possible to allocate more memory than you actually have, as long as you don't actually use it all -- the kernel simply maps the addresses in your page tables into a single zeroed-out page, and marks it as copy-on-write, so you can actually have an array bigger than available memory as long as most of the elements are binary zeroes (though I don't know if druntime currently actually supports such a thing)). T but a size has nothing to do with an address. Sure in x86 we may need to allocate 3GB of data and this would require size_t > 2^31 ==> it must be unsigned. But strings really don't need to have an unsigned length. If you really need a string of length > size_t/2 then have the string type implement a different length property. string s; s.length <== a signed size_t s.size <= an unsigned size_t this way, for 99.% of the cases where strings are actually < 1/2 size_t, one doesn't have to waste cycles doing extra comparing or typing extra code... or better, spending hours looking for some obscure bug because one compared an int to a uint and no warning was thrown. Alternatively, for(int i = 0; i < s.length - 1; i++) could at lease check for underflow on the cmp and break the loop.
Re: Why is size_t unsigned?
On Monday, 22 July 2013 at 03:58:31 UTC, Ali Çehreli wrote: On 07/21/2013 08:47 PM, JS wrote: > Doing simple stuff like > > for(int i = 0; i < s.length - 1; i++) fails catastrophically if s is > empty. To make right one has to reduce performance by writing extra checks. Checks are needed for program correctness. If not in source code, in compiler generated code, or the microprocessor itself. The compiler and the microprocessor would not do such things for performance reasons. It is because sometimes only the programmer knows that the check is unnecessary. > There seems to be no real good reason why size_t is unsigned... How about, every addressable memory locations must be countable? for strings themselves, I would prefer an int to be returned. The size of a string has nothing to do with it's location in memory. > Surely one doesn't require too many strings larger than 2^63 bits on an x64 > os... Agreed. > I running into a lot of trouble because of the way D deals with implicit > casting of between signed and unsigned. D is behaving the same way as C and C++ there. No, surely not... Well, at least, I never had this trouble in C#. > please don't tell me to use foreach... isn't not a panacea. I would still prefer foreach because it is more convenient and safer because of needing less code. Ali foreach doesn't allow you to modify the index to skip over elements.
Why is size_t unsigned?
Doing simple stuff like for(int i = 0; i < s.length - 1; i++) fails catastrophically if s is empty. To make right one has to reduce performance by writing extra checks. There seems to be no real good reason why size_t is unsigned... Surely one doesn't require too many strings larger than 2^63 bits on an x64 os... I running into a lot of trouble because of the way D deals with implicit casting of between signed and unsigned. please don't tell me to use foreach... isn't not a panacea.