Re: sorting failed error
On 07/30/2012 02:36 PM, maarten van damme wrote: For fun I started implementing a program that uses genetics algorithm's to solve the travelling salesman problem. I want to sort an array of chromosome structures according to their fitness. I now get the error: core.exception.AssertError@C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm. d(6714): Failed to sort range of type chromosome[]. Actual result is: [chromosom e([city(20, 0), city(25, 25), city(10, 65), city(50, 50), city(75, 30), city(0, 10)]), chromosome([city(10, 65), city(50, 50), city(25, 25), city(75, 30), city( ... I have no idea what is wrong with my code and the error is not very informative. Does anyone have any idea as to what the problem could be? (full code is at https://dl.dropbox.com/u/15024434/travelling_salesman.d , If it's not something obvious then I'm going to try to reduce it to something as small as possible) Maarten I'd claim it is a 32 bit specific compiler bug, but it is likely that someone will differ. reduced test case: float foo(){ auto f = 3f; return 1/f; } void main(){ assert(foo() == foo()); } The problem is presumably that one of the operands is truncated to float while the other remains at register precision. workaround: bool fitnessCompare(chromosome first,chromosome second){ auto a = fitness(first), b = fitness(second); return a>b; } (the reason schwartzSort works is because it caches the fitnesses, which is better anyway.) I realize that the code is just for fun, but I have some comments: - don't .dup stuff just in order to index directly. it never has any effect other than performance degradation. (this could be a compiler warning) - crossOver and mutate mutate their parameters in-place. I assume this is by mistake. reproduce effectively inserts every element a couple times because of this -- this is why the bug manifests reliably. (const, immutable annotations?) - make use of $ int from=uniform(0,victim.dna.length); int to=uniform(0,victim.dna.length); swap(victim.dna[from],victim.dna[to]); => swap(victim.dna[uniform(0,$)], victim.dna[uniform(0,$)]); - sort is in-place workers=array(sort!(fitnessCompare)(workers)); => sort!fitnessCompare(workers) - mark local functions static if they do not need to access the enclosing context. - use size_t for array iteration variables (if necessary) for(int x=0;x for(size_t x=1;x=2 is guaranteed, but it is an error prone pattern. - another way to do it is to drop the loop completely and to use ranges instead: return zip(cities,cities.drop(1)) .map!(a=>distance(a.expand)) .reduce!"a+b"; The benefit is that this is now obviously correct. You might also want to consider not building up the cities array and computing the terms at the boundary explicitly instead: return distance(city(0,0), victim.dna[0]) + distance(victim.dna[$-1], city(0,0)) + zip(victim.dna, victim.dna.drop(1)) .map!(a=>distance(a.expand)) .reduce!"a+b"; The goal is to craft the shortest code possible that is still efficient and easy to follow. - type deduction? further comments whose application does not lead to immediate benefit: - in contracts are better specified in their dedicated section to push the requirements onto the caller. - consider for(;;) as a means for indefinite looping. - the convention is upper case for type names
Re: sorting failed error
On 07/30/2012 03:52 PM, monarch_dodra wrote: ... Your looks OK, and I doubt you are mutating. I only see floating point gotchas: If a chromosome travels nothing, then his fitness is 1/0 = NaN. 1/0 evaluates to Inf NaN then compares false with everything, making it un-transitive, and potentially breaking your cmp. COuld you try the algo with "return 1/(1+travelled)". That, or because of the non-deterministic nature of floating point calculation, Floating-point computation is deterministic. I'd create an array containing all the fitnesses, and sort using that. This should avoid any "re-evaluation error".
Re: sorting failed error
On 07/31/2012 12:30 AM, maarten van damme wrote: 2012/7/31 Timon Gehr: ... further comments whose application does not lead to immediate benefit: - in contracts are better specified in their dedicated section to push the requirements onto the caller. - consider for(;;) as a means for indefinite looping. - the convention is upper case for type names Thank you very much for this criticism, I'm relatively new to programming and these mistakes/points are the kind off things you can't learn from reading a book or two. I'm glad to help. I have one little question about one of the last points though why use for(;;)? Well, as stated, there is no benefit. As far as I can tell this simply reduces readability from while(true). That is entirely a matter of preference. Is there any reason for this? I like it more because it says "loop". while(true) says: "loop as long as 'true' still holds", which is silly.
Re: Detector for unused variables
On 07/31/2012 11:55 AM, Minas wrote: I agree that having the compiler make warnings about unused variables is a really good idea!!! Java has it and when I program in eclipse it's really useful because the editor can highlight the particular lines. An editor can be configured to point it out even if it is not in the language, if it is considered useful.
Re: Why must bitfields sum to a multiple of a byte?
On 07/31/2012 06:57 PM, Era Scarecrow wrote: On Tuesday, 31 July 2012 at 16:48:37 UTC, Andrej Mitrovic wrote: On 7/31/12, Era Scarecrow wrote: I wonder, is it really a bug? If you are going to have it fill a whole size it would fit anyways, why even put it in as a bitfield? You could just declare it separately. I don't really know, I'm looking at this from a point of wrapping C++. I haven't used bitfields myself in my own code. I'd say it's not a bug since C/C++ is free to reorder the fields you'd need to tinker with it anyways; HOWEVER if you still need to be able to have it then who's to stop you from doing it? I think more likely a flag/version or some indicator that you didn't make a mistake, such as making them depreciated so it complains to you. Kinda like how you can't make assignments in if statements or do useless compares, it's an error and helps prevent issues that are quite obviously mistakes. This is obviously a mistake in the bitfield implementation. What else could be concluded from the error message: std\bitmanip.d(76): Error: shift by 32 is outside the range 0..31 Requesting a 32 bit or 64 bit member on the other hand is not a mistake, and it is not useless, therefore the analogy breaks down. (Also IMO, the once-in-a-year wtf that is caused by accidentally assigning in an if condition does not justify special casing assignment expressions inside if conditions. Also, what is an useless compare?)
Re: Detector for unused variables
On 08/01/2012 12:38 PM, bearophile wrote: Regan Heath: Indeed. IIRC Walter's rationale on things like this has always been that they belong in 3rd party tools. Walter is not always right. It's why the DMD front end is available for use, so people can create tools like this, syntax highlighters, re-formatters, dependency tree diagrams, or... you name it. Detecting unused variables is a core feature, No. This mustn't be part of the language. http://d.puremagic.com/issues/show_bug.cgi?id=7989 it belongs in the compiler, like compile-time array bound tests and other errors currently detected by DMD. This allows everyone to use it with minimum work, so everyone enjoys it, and it requires less work to be implemented because the compiler already does lot of analysis. It is not an error. Making things that are not errors illegal is prone to introduce bugs into code using __traits(compiles). This can be a warning at best.
Re: How to use "read_bool"?
On 08/03/2012 06:17 AM, Zeh wrote: Hi, i am just a newbie trying learn D. But, i get having some trouble with "read_bool". More specifically on program of this lesson: import std.stdio; import std.conv; import std.string; void main() { write("How many are we? "); int personCount; readf(" %s", &personCount); write("How many bicycles are there? "); int bicycleCount; readf(" %s", &bicycleCount); write("What is the distance to the beach? "); int distance; readf(" %s", &distance); bool existsCar = read_bool("Is there a car? "); bool existsLicense = read_bool("Is there a driver license? "); When i try compile this, i get the following errors: hello.d|43|Error: undefined identifier read_bool| hello.d|44|Error: undefined identifier read_bool| ||=== Build finished: 2 errors, 0 warnings (0 minutes, 0 seconds) ===| So, someone know what's happening? What is the correct way to use the Read_bool? Thanks for everyone! presumably read_bool is part of the tutorial. Otherwise you may use this: bool read_bool(){ auto str = readln()[0..$-1]; switch(str){ case "true", "y", "ye", "yes": return true; case "false", "n", "no": return false; default: throw new Exception("please answer yes or no"); } }
Re: NotNull Parser
On 08/03/2012 12:38 PM, Namespace wrote: In context with my post here: http://forum.dlang.org/thread/gajrorlwnrriljxnx...@forum.dlang.org#post-egvyqwkcqjglhrvujkar:40forum.dlang.org I wrote the last days a NotNull Parser. What is this? The NotNull Parser generate for parameter statements with a following "?" valid preconditions. Example: [code] void foo(Object? o) { // do something with o } [/code] will convert into The notation 'T?' is normally used for a nullable type.
Re: Return doesn't really return
On 08/04/2012 06:23 PM, Jacob Carlborg wrote: I have a piece of code that looks like this: https://github.com/jacob-carlborg/dstep/blob/master/clang/Visitor.d#L168 If I change that "first" function to look like this: @property ParamCursor first () { assert(any, "Cannot get the first parameter of an empty parameter list"); foreach (c ; this) return c; assert(0); } Then the last assert is hit. The return statement ends the foreach-loop but it doesn't return from the function. I have not been able to create a small test case for this. Have I done a mistake somewhere or is this a bug in DMD? Mac OS X, DMD 2.059 or 2.060. int opApply (Delegate dg) { auto result = clang_visitChildren(cursor, &visitorFunction,cast(CXClientData) &dg); return result == CXChildVisitResult.CXChildVisit_Break ? 1 : 0; // culprit }
Re: Return doesn't really return
On 08/04/2012 08:54 PM, Jacob Carlborg wrote: On 2012-08-04 19:08, Timon Gehr wrote: int opApply (Delegate dg) { auto result = clang_visitChildren(cursor, &visitorFunction,cast(CXClientData) &dg); return result == CXChildVisitResult.CXChildVisit_Break ? 1 : 0; // culprit } Yes, right. I forgot about that. The Clang API doesn't really have a way to represent the difference between "break" and "return" in D. The Clang API works like this: * Return 0 - Stop visiting children * Return 1 - Continue visiting children * Return 2 - Recursively visit the children It doesn't really seem to be a way to map the difference between the break and return codes that D uses to the Clang API. Anyone got an idea for a workaround bugfix. or should I just continue to use "break" and never use "return"? Return the exit code by reference: Pass a tuple of delegate and return value to the visitorFunction per the CXClientData pointer and make the visitorFunction store the exit code inside the return code field. Then return that from opApply.
Re: How to use "read_bool"?
On 08/04/2012 03:01 AM, Zeh wrote: Thanks for the help, but i tryed both solutions posted and still not working. :/ I get erros to compile the code posted by simendsjo. I try modify at my own, but without success. The code suggest by Timon Gehr compiles, but not work. Works for me. Maybe readln behaves differently on windows?
Re: Why __traits(compile,...) fails here?
On 08/07/2012 03:52 PM, Philippe Sigaud wrote: On Tue, Aug 7, 2012 at 12:42 PM, Zhenya wrote: Template alias parameters do not accept built-in types. The trick is: - A template type parameter (like (T)) recognizes types - A template alias parameter(like (alias a)) recognizes names, symbols. A built-in type is 'purely' a type. It's a keyword, and hence it's not a symbol ('int' cannot be a D identifier) A user-defined type is *both* a type and a symbol (because it has a name) ... Yes, but note that this distinction does not make any sense. alias int Int; // works isType!Int // 'Int' is clearly a symbol, yet the instantiation fails. alias declarations should just accept built-in types. If someone for some obscure reason needs to exclude them, template constraints are good enough. There is no reason to make built-in types behave specially here.
Re: overloading a function taking a void[][]
Try this: template digest(Hash) if(isDigest!Hash){ digestType!Hash digest(Range)(Range data) if(!is(Range:void[][]) && isInputRange!Range && __traits(compiles,digest!Hash(ElementType!(Range).init))){ //implementation detail } digestType!Hash digest()(scope const(void[])[] data...){ // templated as a workaround //implementation detail } // ... (maybe more overloads) }
Re: overloading a function taking a void[][]
On 08/08/2012 09:11 PM, Johannes Pfau wrote: Am Wed, 08 Aug 2012 18:53:05 +0200 schrieb Timon Gehr: Try this: template digest(Hash) if(isDigest!Hash){ digestType!Hash digest(Range)(Range data) if(!is(Range:void[][])&& isInputRange!Range&& __traits(compiles,digest!Hash(ElementType!(Range).init))){ //implementation detail } digestType!Hash digest()(scope const(void[])[] data...){ // templated as a workaround //implementation detail } // ... (maybe more overloads) } Clever, but doesn't seem to work. I can't create an instance of it, even when explicitly specifying the types. Well, I have done similar things in the past. The general concept should work. BTW: This is a working version, but it does cause template bloat: http://dpaste.dzfl.pl/d42a58aa Maybe this helps: http://dpaste.dzfl.pl/ed2e8e5d
Re: Convert little imperative code to functional coding style
Is this what you are looking for? import std.stdio; import std.range: iota; import std.algorithm: map, filter, joiner; import std.typecons : tuple; import std.math : sqrt, floor; void main(){ immutable limit = cast(size_t)floor(sqrt(1_000.0)); auto r = iota(2,limit).map!(m=>iota(1,m-1).map!(n=>tuple(m,n))).joiner .filter!(t=>2*t[0]*(t[0]+t[1])==1_000) .map!(t=>(t[0]^^4-t[1]^^4)*(2*t[0]*t[1])); writeln(r.front); }
Re: Optional extra return value? Multiple return values with auto?
There is no compiler bug. You cannot pass immutable/rvalue by reference to mutable.
Re: Specialize mixin templates
On 08/11/2012 11:42 PM, Henning Pohl wrote: A struct takes a mixin template as argument: struct S(alias Mixin) { mixin Mixin; } How to specialize a mixin template like this one to pass to S? mixin template MixinTemplate(T) { } S(MixinTemplate!float); // Something like this This is a way to do it: struct S(alias Mixin){ mixin Mixin; } mixin template MixinTemplate(T){ } mixin template MixinTemplateFloat(){ mixin MixinTemplate!float; } S!MixinTemplateFloat s;
Re: Iterating through enumeration
On 08/12/2012 01:54 PM, bearophile wrote: Era Scarecrow: But that problem goes away if you turn it into a small array right? (And pass the array to the foreach to cycle over) So throwing that idea out there you get... foo[] array; foreach(m; std.traits.EnumMembers!foo) array ~= m; foreach(m; array) { //not compiler-time expansion like above } Often better (but every time builds an array on the heap): foreach (m; [EnumMembers!Foo]) { // Not a static foreach } Bye, bearophile This builds the array once at compile time: static immutable members = [EnumMembers!Foo]; foreach(m; members){ }
Re: Convert little imperative code to functional coding style
On 08/10/2012 09:59 PM, Nathan M. Swan wrote: On Friday, 10 August 2012 at 18:26:56 UTC, Timon Gehr wrote: Is this what you are looking for? import std.stdio; import std.range : iota; import std.algorithm : map, filter, joiner; import std.typecons : tuple; import std.math : sqrt, floor; void main(){ immutable limit = cast(size_t)floor(sqrt(1_000.0)); auto r = iota(2,limit).map!(m=>iota(1,m-1).map!(n=>tuple(m,n))).joiner .filter!(t=>2*t[0]*(t[0]+t[1])==1_000) .map!(t=>(t[0]^^4-t[1]^^4)*(2*t[0]*t[1])); writeln(r.front); } Ugh! I guess functional isn't always the best ;) In an attempt to destroy that guess I have uncovered the following compiler bug: http://d.puremagic.com/issues/show_bug.cgi?id=8542
Re: char ***argc problems.
On 08/12/2012 10:33 PM, Andrew wrote: I'm attempting to create a wrapper for MPI, however, MPI_Init wants to read the arguments for main(): MPI_Init(int *argv, char ***argc); How do I get this last level of pointer reference? So far, I have: void main (string[] args) { auto argarr = new char*[args.length]; foreach(i, a; args) argarr[i] = (a.dup ~ '\0').ptr; int argc = to!(int)(argarr.length); MPI_Init(&argc, argarr.ptr); } Any ideas? -Andrew Maybe like this? import std.algorithm, std.array, std.conv; void main(string[] args){ auto argarr = args.map!(a=>(a ~ '\0').ptr).array; int argc = to!(int)(argarr.length); auto argv = argarr.ptr; MPI_Init(&argc, &argv); args = argv[0..argc].map!(to!string).array; // ... }
Re: char ***argc problems.
On 08/12/2012 11:38 PM, Andrew wrote: On Sunday, 12 August 2012 at 20:57:34 UTC, Timon Gehr wrote: On 08/12/2012 10:33 PM, Andrew wrote: I'm attempting to create a wrapper for MPI, however, MPI_Init wants to read the arguments for main(): MPI_Init(int *argv, char ***argc); How do I get this last level of pointer reference? So far, I have: void main (string[] args) { auto argarr = new char*[args.length]; foreach(i, a; args) argarr[i] = (a.dup ~ '\0').ptr; int argc = to!(int)(argarr.length); MPI_Init(&argc, argarr.ptr); } Any ideas? -Andrew Maybe like this? import std.algorithm, std.array, std.conv; void main(string[] args){ auto argarr = args.map!(a=>(a ~ '\0').ptr).array; int argc = to!(int)(argarr.length); auto argv = argarr.ptr; MPI_Init(&argc, &argv); args = argv[0..argc].map!(to!string).array; // ... } I don't know why I didn't think of this: auto argv = argarr.ptr; Which fixed it. Unfortunately, using args.map! doesn't work, because it returns an immutable, which MPI_Init can't take. oops. auto argarr = args.map!(a=>(a.dup ~ '\0').ptr).array; Thanks for the help -Andrew
Re: Sudoku Py / C++11 / D?
On 08/15/2012 12:31 AM, bearophile wrote: http://www.reddit.com/r/cpp/comments/y6gwk/norvigs_python_sudoku_solver_ported_to_c11/ http://nonchalantlytyped.net/blog/2012/08/13/sudoku-solver-in-c11/ His C++11 port is 316 lines long: https://gist.github.com/3345676 How many lines for a (not golfed) D translation of the original Python code? Bye, bearophile Probably not what you want, but solves sudoku quite well: dpaste.dzfl.pl/69669b05
Re: Sudoku Py / C++11 / D?
On 08/16/2012 03:56 AM, maarten van damme wrote: solving sudoku's well too : http://dpaste.dzfl.pl/903e34b5 I have one question though, how can you make it find all possible solutions? Keep on backtracking when you find one until there are no more possibilities to explore. (i.e. get rid of the return value of 'fill')
Re: Matrix Multiplication benchmark
On 08/16/2012 03:15 PM, Matthias Pleh wrote: I've created a simple 4x4 Matrix struct and have made some tests, with surprising results. (although I've heard from similar results in c++) struct mat4 { float[4][4] m; mat4 opMul(in mat4 _m); } mat4 mul(in mat4 m1, in mat4 m2); I've tested this 2 multiplication functions (overloaded and free). Result (100_000 times, windows7 64bit, 32bit build): DMD: (dmd -O -inline -release) opMul: 20 msecs mul : 1355 msecs GDC: (gdc -m32 -O3 -frelease) opMul: 10 msecs mul : 1481 msecs Why this huge difference in performance? Note that you have missed to provide the full benchmark code listing.
Re: Sudoku Py / C++11 / D?
On 08/16/2012 09:52 PM, maarten van damme wrote: I've now ran in something odd. Using a slight variant from my program on dpaste (can't upload modified version atm but changes are minimal) it takes 0.6 seconds to solve the hard puzzle the python version took 180 seconds for. This is because the python version happened to choose an unlucky search order. Sudoku is NP-complete after all, so it is not surprising that programs have a bad worst case run time. Yet on the last puzzle, the impossible one, python takes 1800 seconds to figure out it's impossible yet mine takes over 3885 seconds. Where is this slowdown coming from? This is because your specific solution is slow. Mine takes <20ms on the 'hard' puzzle and ~13s on the impossible one. (~2.4 GHZ intel x86_64 machine, with gdmd -O -release -inline -noboundscheck.) There is a constant factor between those two solutions.
Re: Sudoku Py / C++11 / D?
On 08/16/2012 11:51 PM, maarten van damme wrote: > This is because your specific solution is slow. > > Mine takes <20ms on the 'hard' puzzle and ~13s on the impossible one. > (~2.4 GHZ intel x86_64 machine, with gdmd -O -release -inline -noboundscheck.) > There is a constant factor between those two solutions. I've compiled it using dmd on my latitude e5500 which is not that fast so I don't think it's that slow... Compiled and run in the same environment, your solution takes 0.26s on the 'hard' one, whereas mine takes 0.0013s. Your solution takes ~1600s on the impossible one whereas mine takes ~13s. Besides, lets say mine is five times slower, Hard facts say that it is at around 100x-200x slower. 3000 seconds is still waaay to much. Sounds reasonable to me. When I'm back able to get my laptop to use my crapy data connection I'll compare. Do you have some optimization ideas by the way? First of all, getting rid of the dynamic allocations is low hanging fruit. Then you'll have to reduce the number of times you recompute the same information. Update/restore the possibilities array as you update/restore the solution attempts. Do this for the whole board at once and use a compact representation of possibilities.
Re: Sudoku Py / C++11 / D?
On 08/17/2012 01:13 AM, maarten van damme wrote: great, going to play around with it tomorrow. Caching the possibilities is going to look really ugly but you're right, it's going to give quiet a boost in performance. I'm also going to format your source code a bit more and see if I can follow it's logic as it seems to be way more efficient. (although compilation is failing here, I'm running dmd 2.059 and it gives "can't stride on chunks!(short)) Works for me both with DMD 2.060 and GDC with the 2.059 front end. would using short or bytes increase performance compared to integers? Using less memory sometimes increases performance, but here it is not significant. if so, why did you use shorts instead of bytes? Because I need 9 bits per entry to keep track of all the combinations of possibilities.
Re: How create a operator tree?
On 08/17/2012 10:38 AM, Namespace wrote: o_O I was hoping that there is a shorter way than this. I hacked together the following little parser (not extensively tested). http://dpaste.dzfl.pl/e616692e It transforms the input expression into polish notation, ignoring space characters. Note that it is significantly shorter than the regex attempt. It handles numbers, unary +, -, binary +, -, *, /, ^, where ^ associates to the right, as well as nested parentheses. It should be trivial to extend. (in this case you might want to generate the switch cases automatically from the operator precedence table.)
Re: How create a operator tree?
On 08/17/2012 02:55 PM, Timon Gehr wrote: On 08/17/2012 10:38 AM, Namespace wrote: o_O I was hoping that there is a shorter way than this. I hacked together the following little parser (not extensively tested). http://dpaste.dzfl.pl/e616692e It transforms the input expression into polish notation, ignoring space characters. Note that it is significantly shorter than the regex attempt. It handles numbers, unary +, -, binary +, -, *, /, ^, where ^ associates to the right, as well as nested parentheses. It should be trivial to extend. (in this case you might want to generate the switch cases automatically from the operator precedence table.) (the first while loop is superfluous)
Re: Non-immutable char[] doesn't change?
On 08/18/2012 02:15 PM, Salih Dincer wrote: This may be the solution...:) char[] b = cast(char[])"abc".dup; // ok, unique reference Sorry... You don't need the cast in this case. Topic: It is not a bug, but it might be surprising because the behaviour of typeid is different with polymorphic types. Typeid on a class object gives you back the RTTI structure of the value's type, while typeid on anything else gives you back the RTTI of the statically determined variable type. The reason this works this way is because class objects are the only objects which actually carry runtime type information with them.
Re: Sudoku Py / C++11 / D?
On 08/20/2012 10:43 PM, maarten van damme wrote: Still it comes nowhere near beating timons solution. Is the logic of that documented somewhere because I don't understand it. Try this: http://dpaste.dzfl.pl/23b1b6e2
Re: template and constraints
On 08/20/2012 11:52 PM, bioinfornatics wrote: I got a little problem with these code: double div(T a, U b)() if( a > 0 && b > 0 ){ // not works T and U unknwn identifier return a / b; } double div(T,U)(T a, U b) if( a > 0 && b > 0 ){ // not works, a and b not known at compile time return a / b; } double div(double a, double b)() if( a > 0 && b > 0 ){ // works but not generic return a / b; } _ The only one who works is a not generic! they are a way? or i need to write for each parameter type? Alias parameters. auto div(alias a, alias b)().
Re: reduce!"a+b"(R) syntax question
On 08/21/2012 07:05 PM, Andrew Spott wrote: When I'm doing an anonymous function for something like reduce, how are the arguments determined? Is it alphabetical? Can I use any names (reduce!"d-c"(R)?), or are the names defined in the function "reduce"? They are defined here: http://dlang.org/phobos/std_functional.html#binaryFun This syntax isn't really documented at all in the language reference, which makes it a little bit of guess work. This is not part of the language, it is a library artefact: http://dlang.org/phobos/std_algorithm.html 'Many functions in this module are parameterized with a function or a predicate. The predicate may be passed either as a function name, a delegate name, a functor name, or a compile-time string. The string may consist of any legal D expression that uses the symbol a (for unary functions) or the symbols a and b (for binary functions). These names will NOT interfere with other homonym symbols in user code because they are evaluated in a different context. The default for all binary comparison predicates is "a == b" for unordered operations and "a < b" for ordered operations.'
Re: Sudoku Py / C++11 / D?
On 08/21/2012 05:52 PM, maarten van damme wrote: > On 08/20/2012 11:49 PM, Timon Gehr wrote:> On 08/20/2012 10:43 PM, maarten van damme wrote: Still it comes nowhere near beating timons solution. Is the logic of that documented somewhere because I don't understand it. Try this: http://dpaste.dzfl.pl/23b1b6e2 Thank you very much, this makes everything more clearer. I'm not very familiar with binary operators so the comments help out a lot. Would you mind it if I shamelessly copy your solution of using shorts to store possibilities in? Not at all. I'm also a bit confused. How come the int's you change from a square passed from squ are stilled referenced to the original array? I thought it lost that reference as soon as you did any operations (like concenating) on it? The used ranges just express patterns of iteration. They replace manual for-loops. The data source has assignable elements, and the relevant range operations in Phobos all propagate this capability to their result.
Re: inout functions
On 08/24/2012 12:14 AM, Piotr Szturmaj wrote: Hi, I found this code of std.range.iota's Result struct: @property inout(Value) front() inout { assert(!empty); return current; } What's the purpose of inout on parameterless functions? It is a method of a struct, therefore it is not parameterless, but has a hidden parameter. 'inout' qualifies the implicit 'this' reference. Inside the method body, typeof(this) is inout(Result).
Re: struct init property
On 08/24/2012 09:39 AM, nocide wrote: Am 23.08.2012 19:15, schrieb nocide: struct has no default constructor and instances are initialized with the init property. Can I declare or override the init property for a custom defined struct? Ok, the initializer forks fine for me, but I've encounterd following situation: (simplified code) // This compile fine struct Foo { union { struct { int a = 1, b = 2, c = 3, d = 4; } float[4] e; } } // but this doesn't compile struct Foo { union { struct { int a, b, c, d; } float[4] e = [ 1.0f, 2.0f, 3.0f, 4.0f ]; } } Foo f; // Error: struct main.Foo overlapping initialization for struct Is this a bug? Yes.
Re: Sudoku Py / C++11 / D?
On 08/24/2012 09:32 PM, maarten van damme wrote: I've distiled what I understood from your source and the resulting executable managed to solve the impossible one in 27 seconds while your source takes 41 seconds. It is 10s vs 13s with GDC on my machine.
Re: Check for ctfe
On 08/25/2012 02:06 AM, cal wrote: I saw something on the forum not too long ago about statically checking to see if the current function is being executed at compile time, but can't seem to find it now. Can it be done? (Like static if (__ctfe__) or something) if(__ctfe)
Re: Check for ctfe
On 08/25/2012 02:15 AM, bearophile wrote: cal: I saw something on the forum not too long ago about statically checking to see if the current function is being executed at compile time, but can't seem to find it now. Can it be done? (Like static if (__ctfe__) or something) It's named __ctfe, but unfortunately it's an (immutable) run-time value. When you use it you rely on the dead code elimination optimization done by the compiler. Bye, bearophile Which is basically guaranteed to be performed.
Re: Sudoku Py / C++11 / D?
On 08/25/2012 01:01 AM, Timon Gehr wrote: On 08/24/2012 09:32 PM, maarten van damme wrote: I've distiled what I understood from your source and the resulting executable managed to solve the impossible one in 27 seconds while your source takes 41 seconds. It is 10s vs 13s with GDC on my machine. I have inlined some ranges. http://dpaste.dzfl.pl/4a7e4038 I now measure 10.5s vs 6.7s (GDC) and 20s vs 12s (DMD).
Re: Sudoku Py / C++11 / D?
On 08/25/2012 02:38 AM, Timon Gehr wrote: On 08/25/2012 01:01 AM, Timon Gehr wrote: On 08/24/2012 09:32 PM, maarten van damme wrote: I've distiled what I understood from your source and the resulting executable managed to solve the impossible one in 27 seconds while your source takes 41 seconds. It is 10s vs 13s with GDC on my machine. I have inlined some ranges. http://dpaste.dzfl.pl/4a7e4038 I now measure 10.5s vs 6.7s (GDC) and 20s vs 12s (DMD). I meant to paste this: http://dpaste.dzfl.pl/8fa23a97
Re: Sudoku Py / C++11 / D?
On 08/25/2012 02:51 AM, Chris Cain wrote: On Friday, 24 August 2012 at 23:14:02 UTC, maarten van damme wrote: http://en.wikipedia.org/wiki/File:Sudoku_puzzle_hard_for_brute_force.jpg It occurs to me that one of the main reasons why this particular puzzle would be hard for brute force is that the first line is blank and more than half of the second line is blank, and it seems like it is designed to have as many choices as possible before a set square is encountered. I bet it could be solved much quicker by a computer by doing it in reverse. I've got some ideas, maybe I'll write a solution to this myself. :) FWIW both mine and Maarten's solution require a trivial amount of time to solve it.
Re: Check for ctfe
On 08/25/2012 12:53 PM, Minas Mina wrote: Why is it "if( __ctfe )" and not static if.. ? Both branches need to be compiled in order to have both a ctfe and a runtime version.
Re: Reading bytes and converting to int
On 08/26/2012 04:19 PM, Tommi wrote: On Saturday, 25 August 2012 at 20:58:47 UTC, Jonathan M Davis wrote: auto buf = file.rawRead(new ubyte[](4)); Could we somehow skip making the temporary buffer, and read from the file directly into an existing variable. Can we make a slice of one element that points to an existing value. import std.stdio; struct BigValue // has no indirection { int m_value1; int m_value2; long m_value3; // ... } BigValue g_bigValue; void fun() { auto file = File("filename"); // How to create a slice of size 1 which references g_bigValue? BigValue[] refToBigValue /* = ? */ ; auto refToBigValue = (&g_bigValue)[0..1]; buffer = file.rawRead(refToBigValue); }
Re: opUnary overloading
On 08/26/2012 10:33 PM, cal wrote: I have a struct wrapping a union of an int and a float, and want to overload opUnary for this struct: struct Value { enum Type { INT, FLOAT } Type type; union { int i; float f; } this(int _i) { i = _i; type = Type.INT; } this(float _f) { f = _f; type = Type.FLOAT; } auto opUnary(string s)() if (s == "-") { if (type == Type.INT) return -i; if (type == Type.FLOAT) // If i comment this out, I get an int back return -f; // as expected assert(0); } } Value v1 = Value(25); assert(v1.type == Value.Type.INT); auto neg = -v1; writeln(typeof(neg).stringof); // this returns float, when it should return int The part I don't understand is this: in the opUnary method, if I comment out the second if conditional (if (type == Type.FLOAT)) then when doing the negation on v1 I get an INT as expected. If I don't comment this code out, I get a float. When commented out, I get back -25 as an int, which i expect. When not commented out, I get back -nan, which suggests to me that it is returning the (uninitialized) float from the union, not simply giving me back the int as a float. Could someone explain this? Compiler bug. http://d.puremagic.com/issues/ Also see: http://d.puremagic.com/issues/show_bug.cgi?id=8307 I assume the compiler fails to add an implicit conversion node into the AST because at the point where -i is returned, the return type is still assumed to be 'int'. What you are observing is not type coercion, but an x87 FPU stack underflow.
Re: float[] → Vertex[] – decreases performance by 1000%
On 08/28/2012 06:35 PM, David wrote: Am 28.08.2012 17:41, schrieb bearophile: David: The arrays are 100% identical (I dumped a Vertex()-array and a raw float-array, they were 100% identical). I hope some people are realizing how much time is being wasted in this thread. Taking a look at the asm is my suggestion still. If someone is rusty in asm, it's time to brush away the rust with a steel brush. Bye, bearophile You're right, but I also said, that I don't care anylonger, I found a workaround, I can live with it. I generally tend to ignore dmd bugs and just workaround them, I don't have the time to track down every stuipid bug from a ~8k codebase. Thanks anyways for your help. Use this to create a minimal test case with minimal user interaction: https://github.com/CyberShadow/DustMite
Re: float[] → Vertex[] – decreases performance by 1000%
On 08/29/2012 01:26 AM, David wrote: Use this to create a minimal test case with minimal user interaction: https://github.com/CyberShadow/DustMite Doesn't help if dmd doesn't crash, or? It doesn't help a lot if compilation succeeds, but you stated that you generally tend to ignore dmd bugs. Most dmd bugs make compilation fail.
Re: Call a function on an entire slice
On 08/29/2012 03:38 PM, monarch_dodra wrote: D provides ways to operate on an entire (sub) slice: int[] a = ... ; a[] *= 5; //Multiply everything by 5. a[0 .. 2] = 3; //Set indexes 0 to 1 to the value 3. I was wondering if there was any way to do this for a specified function? struct S { void foo() { writeln("foo"); } } void bar(S s) { writeln("bar"); } void main() { S[5] a; a[].foo(); //undefined identifier 'foo' a[].bar(); //cannot implicitly convert expression (a[]) of type S[] to S }; I know I can just foreach it, but it doesn't quite have the same expressive power. Yes it does. If the built in arithmetic types have this power, why not functions? Because the built-in arithmetic vector operators are supported by hardware.
Re: Assigning global and static associative arrays
On 09/02/2012 03:45 PM, monarch_dodra wrote: On Saturday, 1 September 2012 at 09:16:30 UTC, Jonathan M Davis wrote: [SNIP] so it looks like not only do all instances of the same string enum use the same memory, but another enum with the same string literal shares it as well. So, only one is allocated. And on Linux at least, as I understand it, the string literals go in ROM. But it may be that the above code functions differently in Windows, since it _doesn't_ put string literals in ROM. [SNIP] FYI: I get the exact same behavior in Windows. Not that it matters, but it sounded like you were asking. I'm a bit confused now though: Why would someone want to use an enum when they could use a static immutable instead? If I understood correctly, the enum will *always* be inlined (doesn't create any actual symbols). But if you use a static immutable, then the compiler will create an actual symbol, but probably inline it away if it judges that is a better choice anyways... Is there *any* scenario where one would choose the enum over the static immutable...? - If there is no need to access it at run time. - Type deduction.
Re: Assigning global and static associative arrays
On 09/02/2012 06:26 PM, monarch_dodra wrote: On Sunday, 2 September 2012 at 16:20:16 UTC, Timon Gehr wrote: On 09/02/2012 03:45 PM, monarch_dodra wrote: FYI: I get the exact same behavior in Windows. Not that it matters, but it sounded like you were asking. I'm a bit confused now though: Why would someone want to use an enum when they could use a static immutable instead? If I understood correctly, the enum will *always* be inlined (doesn't create any actual symbols). But if you use a static immutable, then the compiler will create an actual symbol, but probably inline it away if it judges that is a better choice anyways... Is there *any* scenario where one would choose the enum over the static immutable...? - If there is no need to access it at run time. - Type deduction. -Type deduction: Not really, I can just declare it as "immutable auto". enum x = 2; void main(){ auto y = x; y = 3; } -no need to access it at run time. I guess.
Re: typeof(enum)
Accidentally replied to your private email first. On 09/08/2012 12:55 AM, Minas wrote: import std.stdio; enum PI = 3.14; void main() { writeln(typeid(typeof(PI))); } It prints "double". Shouldn't it be immutable(double). No. auto x = PI; x++; I think it would make more sense, as it is a constant. It never makes sense to have mutable values, but their type may still allow mutation of variables of that type. Plus, it could be shared among threads. The symbol PI does not exist at runtime.
Re: int[3][4]*
On 09/08/2012 04:19 AM, bearophile wrote: Ellery Newcomer: alright what's the deal? This is one of the "clean" ways to do it: void main () { static struct Mat { int[3][4] m; alias m this; } Mat* fooz = new Mat; fooz[1][3] = 5; This may corrupt your heap. } Bye, bearophile I prefer this: void main(){ alias int[3][4] fooz; int[3][4]* i = (new fooz[1]).ptr; } But I think the original example should just work.
Re: int[3][4]*
On 09/08/2012 01:21 PM, bearophile wrote: Timon Gehr: This may corrupt your heap. I usually don't put the alis this... I prefer this: void main(){ alias int[3][4] fooz; int[3][4]* i = (new fooz[1]).ptr; } This allocates past the size of the array, the information to append to the array of fooz. It's a very little amount of memory. Since some weeks, if you allocate a single struct that contains a single fixed size array, that memory is not allocated. Bye, bearophile Wasn't aware that this got fixed. Thanks!
Re: since when was this valid syntax?
On 09/08/2012 04:11 PM, Ellery Newcomer wrote: alias enum int e; It is valid according to the grammar and DMD ignores meaningless attributes. scope shared @disable @trusted package final override deprecated extern __gshared synchronized pure nothrow ref static abstract immutable alias auto final override deprecated extern __gshared synchronized enum pure nothrow ref static abstract @safe @disable scope int e;
Re: since when was this valid syntax?
On 09/08/2012 06:44 PM, bearophile wrote: Timon Gehr: It is valid according to the grammar and DMD ignores meaningless attributes. Do you know why? No reason. Is it just a unfinished part of dmd, or Walter believes this is an acceptable design for a compiler? Jonathan would say he has more important things to do. In years I have never heard a comment from him on this bad situation. I'd design it differently as well. But this is the kind of thing that can be ignored indefinitely without hurting the programmer more than once. A similar issue is that the compiler actually won't detect clashing function overloads, leaving the error report up to the linker.
Re: since when was this valid syntax?
On 09/08/2012 09:25 PM, Maxim Fomin wrote: On Saturday, 8 September 2012 at 16:00:44 UTC, Timon Gehr wrote: On 09/08/2012 04:11 PM, Ellery Newcomer wrote: alias enum int e; It is valid according to the grammar and DMD ignores meaningless attributes. scope shared @disable @trusted package final override deprecated extern __gshared synchronized pure nothrow ref static abstract immutable alias auto final override deprecated extern __gshared synchronized enum pure nothrow ref static abstract @safe @disable scope int e; How dmd's parser is written if it allows such things? It's the grammar that allows this. Every parser that follows the grammar would accept this.
Re: const attribute makes whole element const?
On 09/09/2012 01:16 AM, Namespace wrote: Why fail this code? without "const" on "Name" it works fine. http://dpaste.dzfl.pl/9fa0986a const fields cannot be written to. This includes the case when the entire struct is written to at once.
Re: delegate from lambda expression
On 09/10/2012 01:55 AM, bearophile wrote: Your code doesn't look good, Yes it does.
Re: delegate from lambda expression
On 09/10/2012 01:20 AM, timotheecour wrote: I'd like to achieve the following: import std.stdio,std.range,std.algorithm,std.array; void main(){ auto dg=a=>a*2; auto a=iota(0,10); writeln(a.map!dg.array); } but this doesn't compile: Error: variable [...]dg type void is inferred from initializer delegate (__T26 a) { return a * 2; } , and variables cannot be of type void However this works: writeln(a.map!(a=>a*2).array); but I want to reuse dg in other expressions (and avoid repeating myself) Also, I want to avoid using string litteral enum dg=`a*2` as in my case dg is much more complicated and this is cleaner without a string IMHO. My questions: 1) why can't the compiler infer the type int(int) for dg? Because it can't. D unfortunately does not have powerful type inference. 2) how to convert a lambda a=>a*2 to a delegate or function? Those need full type information. The lambda as shown is generic. 3) if 2 is not possible, how to achieve what I'm trying to do WITHOUT having to make the type explicit as in "int delegate(int) dg=(int a){return a*2;}"? template ID(alias a){ alias a ID; } void main(){ alias ID!(a=>a*2) dg; auto a=iota(0,10); writeln(a.map!dg.array); } 4) is there a way to have template delegates, and what's the syntax in this simple example? Already shown.
Re: filter out compile error messages involving _error_
On 09/10/2012 01:52 AM, timotheecour wrote: Can we filter out compiler errors involving _error_ as template parameter? Clearly the error is coming from upstream so there's no need to even show those. eg: Error: template mypackage.mymodule.myfunction cannot deduce template function from argument types !()(_error_) You can file all instances of this you can find as 'diagnostic' bugs.
Re: inconsistent behavior with implicit imports
On 09/10/2012 01:47 AM, timotheecour wrote: This works: import std.stdio; void main(){ writeln(std.conv.to!double(1)); } This doesn't compile: import std.stdio; void main(){ std.stdio.writeln(std.conv.to!double(1)); } =>Error: undefined identifier std So it seems for conv, import std.conv is not needed, but for writeln, import std.stdio is needed. Why? I assume because std.stdio imports std.conv, but not vice versa. Also, I always get link errors when using those "implicit imports" for my own modules and using "rdmd". Is there a way to allow this without link errors in the following (using rdmd) ? void main(){ mypackage.mymodule.myfun(0); } which would behave as: import mypackage.mymodule; void main(){ myfun(0); } This is a quirk of DMD, not a language feature. You can file the implicit import behaviour as a bug.
Re: filter out compile error messages involving _error_
On 09/10/2012 02:14 AM, Jonathan M Davis wrote: On Monday, September 10, 2012 01:52:52 timotheecour wrote: Can we filter out compiler errors involving _error_ as template parameter? Clearly the error is coming from upstream so there's no need to even show those. eg: Error: template mypackage.mymodule.myfunction cannot deduce template function from argument types !()(_error_) They're useful, because they give you the instantiation chain, and it makes it clear why each instantiation is failing. Yes, what you ultimately need to fix is what's resulting in _error_, but that doesn't mean that the rest is useless (like knowing _where_ the template was instantiatied from and what arguments were used to instantiate it). If you don't want to see those, then use grep -v _error_ on the compiler's output. - Jonathan M Davis Don has expressed the desire to weed those out completely.
Re: delegate from lambda expression
On 09/10/2012 02:56 AM, bearophile wrote: timotheecour: What was wrong with it and what would you suggest to improve it? Nothing serious, I just suggest to give a bit more air to your code, adding a space around operators, after commas, etc. Otherwise your code risk looking like Timon's code ;-) Which is usually extremely beautiful. This is not a liability. I have also compiled the code with -property. Some people don't like this. The choice is yours, but you need to express an informed choice. Will the way I'm skipping "()" ever be deprecated? Who knows. People disagree on this :-) (That means it is here to stay.) One of the points of UFCS was to avoid writing too much parentheses Where did you read this? He most definitely has a point there.
Re: const attribute makes whole element const?
On 09/10/2012 02:05 AM, Namespace wrote: I had never problems with that in C++. clang++ sez: error: cannot define the implicit default assignment operator for 'S', because non-static const member 'x' can't use default assignment operator If I have members which are const because they are assigned only one time and needs no other assignment, why should I declare this member not as const? You can, but then you have to provide your own assignment operator and you have to work around the aforementioned bug that implies the assignment operator is not invoked for associative array index assignments. In the example I know exactly that I assign only one time a name to this struct, so why I should not declare it as const? Other example: you have a unique birthday date. This is const you cannot change it like a name or a telephone number. Therefore I cannot be default-assigned to.
Re: since when was this valid syntax?
On 09/10/2012 07:07 AM, Ellery Newcomer wrote: On 09/08/2012 09:01 AM, Timon Gehr wrote: On 09/08/2012 04:11 PM, Ellery Newcomer wrote: alias enum int e; It is valid according to the grammar I don't believe you. Show me the derivation. The grammar as shown on dlang.org indeed seems not to allow this, but it is out of date as it also wouldn't allow alias extern(C) void function() fun;
Re: auto limitation?
On 09/11/2012 08:57 PM, Maxim Fomin wrote: I think it is UB rather than a bug. No, this is a bug. The spec says that return types must match exactly. Exactly. If it was UB, the spec would say the behaviour is undefined if they don't match exactly. AFAIK auto is a feature to infer return type, not to magically adjust to multiple incompatible types.
Re: auto limitation?
On 09/11/2012 09:29 PM, Namespace wrote: On Tuesday, 11 September 2012 at 19:27:40 UTC, Timon Gehr wrote: On 09/11/2012 08:57 PM, Maxim Fomin wrote: I think it is UB rather than a bug. No, this is a bug. The spec says that return types must match exactly. Exactly. If it was UB, the spec would say the behaviour is undefined if they don't match exactly. AFAIK auto is a feature to infer return type, not to magically adjust to multiple incompatible types. So what? Should my code work or not? According to the spec it should fail compilation.
Re: access enclosing type from shared static this()
On 09/19/2012 09:37 PM, "Øivind" wrote: I want to access the type of the enclosing struct in in a shared static initializer.. How do I do that? The following code will not compile: mixin template MsgMixin(T ...) { static string getName(this M)() { return M.stringof; } shared static this() { import std.stdio; writeln("register " ~ getName()); } } struct MsgTestMsg { mixin MsgMixin!(); } I get the following error messages: src/main.d(40): Error: template main.MsgTestMsg.MsgMixin!().getName does not match any function template declaration src/main.d(40): Error: template main.MsgTestMsg.MsgMixin!().getName(this M) cannot deduce template function from argument types !()() If not possible, just getting the name of the enclosing struct would help a lot! -Øivind use typeof(this), eg: mixin template MsgMixin(T ...) { shared static this() { import std.stdio; writeln("register " ~ typeof(this).stringof); } }
Re: tuple(tuple(1)) fails to compile, but tuple(tuple(1),1) works
On 09/21/2012 01:04 AM, timotheecour wrote: inconsistent: auto a1=tuple(tuple(1));//CT error auto a2=tuple(tuple(1),1);//works bug? Yes. In general, if there is a compile time error other than a static assertion failure that points to Phobos code, you can assume that it is a library bug.
Re: function is not function
On 09/21/2012 10:41 PM, Ellery Newcomer wrote: On 09/21/2012 01:17 PM, bearophile wrote: pragma(msg, is(typeof(a) == function)); // nope! code in pyd suggests this evaluated to true once upon a time. I don't think it ever did. It is just very easy to get wrong.
Re: Testing for template argument being result of takeExactly
On 09/23/2012 01:54 AM, Jonathan M Davis wrote: I'm trying to test whether a template argument is the type returned by takeExactly, and I haven't been able to sort out the template voodoo required yet. It would be a lot easier if I had a variable to work with, but I just have the type, and the fancy is expression required to pull it off is fancy enough that I haven't been able to sort it out yet. At present, I have this: import std.range; import std.stdio; template Hello(R) if(is(R r == U, V, V w, U = typeof(takeExactly(w, 1 { alias R Hello; } void main() { auto str = "hello"; auto t = takeExactly(str, 3); writeln(t); Hello!(typeof(t)) h = t; writeln(h); } I need Hello to instatiate if R is the type returned by takeExactly and fail to instantiate otherwise. At present, the code gives these compilation errors: q.d(15): Error: template instance Hello!(Result) Hello!(Result) does not match template declaration Hello(R) if (is(R r == U,V,V w,U = typeof(takeExactly(w,1 q.d(15): Error: Hello!(Result) is used as a type q.d(16): Error: template std.stdio.writeln does not match any function template declaration q.d(16): Error: template std.stdio.writeln(T...) cannot deduce template function from argument types !()(_error_) So, clearly I don't have the is expression right, and this is seriously pushing the edge of my knowledge of is expressions. So, any help would be appreciated. Thanks. - Jonathan M Davis import std.range, std.traits; import std.stdio; template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){ alias R Hello; } void main(){ auto str = "hello"; auto t = takeExactly(str, 3); writeln(t); Hello!(typeof(t)) h = t; writeln(h); }
Re: Testing for template argument being result of takeExactly
On 09/23/2012 03:48 PM, Andrei Alexandrescu wrote: On 9/23/12 8:47 AM, Timon Gehr wrote: import std.range, std.traits; import std.stdio; template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){ alias R Hello; } That's the nicest. Well, I noticed it is not entirely correct as takeExactly special cases sliceable inputs. Therefore, the guard also passes for ranges that have a sliceable member called _input of the same range type. The correct guard therefore would be: if(hasSlicing!R || is(typeof(R._input.takeExactly(2)) == R)) or if(!hasSlicing!R && is(typeof(R._input.takeExactly(2)) == R)) depending on what the goal is. Regarding availability of "_input", I meant to make it available systematically as "input" for ranges where the notion makes sense. Andrei This seems to be reasonable.
Re: Testing for template argument being result of takeExactly
On 09/23/2012 10:57 PM, Ali Çehreli wrote: ... Also, I think your code should have passed a range like R.init to takeExactly, not R, which is a type: takeExactly(R.init, 1) I don't know why your code compiles. See discussion here: http://d.puremagic.com/issues/show_bug.cgi?id=8220
Re: Testing for template argument being result of takeExactly
On 09/24/2012 09:41 AM, monarch_dodra wrote: ... Regarding the ".init" issue, I hadn't thought of that, but it can be worked around pretty easily with an is(R r): template Hello(R) if ( is(R r) && is(typeof(takeExactly(r, 1))) && is(R == typeof(takeExactly(r, 1))) ) { alias R Hello; } After that, I guess it is indeed one implementation detail vs the other. I don't think this does what you think it does. The 'is(R r)' declares r to be an alias for R. So 'r' is a type in that code snippet. Also, is(typeof(takeExactly(R, 1))) && is(R == typeof(takeExactly(R, 1))) can be written in a more compact way as is(typeof(takeExactly(R, 1)) == R) IMO, it really depends on whether or not you'd want "int[]" to be considered the return type of a takeExactly :/ Maybe it is, maybe it ain't.
Re: Testing for template argument being result of takeExactly
On 09/25/2012 08:41 AM, monarch_dodra wrote: On Monday, 24 September 2012 at 22:13:51 UTC, Timon Gehr wrote: On 09/24/2012 09:41 AM, monarch_dodra wrote: > [SNIP] I don't think this does what you think it does. The 'is(R r)' declares r to be an alias for R. So 'r' is a type in that code snippet. Darn :( Also, is(typeof(takeExactly(R, 1))) && is(R == typeof(takeExactly(R, 1))) can be written in a more compact way as is(typeof(takeExactly(R, 1)) == R) Technically, no: That was my first try, and as mentioned in the first reply, this returns true when the types of takeExactly and R are equal comparable, but does not make sure they are the actually the same types. ... I assume you messed up the parentheses. is(typeof(takeExactly(R, 1) == R)) // test for equal-comparable is(typeof(takeExactly(R, 1)) == R) // test for type identity alias float flt; static assert(is(typeof(1==flt))); static assert(!is(typeof(1)==flt));
Re: Testing for template argument being result of takeExactly
On 09/26/2012 03:50 PM, monarch_dodra wrote: On Wednesday, 26 September 2012 at 13:19:13 UTC, Timon Gehr wrote: On 09/25/2012 08:41 AM, monarch_dodra wrote: On Monday, 24 September 2012 at 22:13:51 UTC, Timon Gehr wrote: On 09/24/2012 09:41 AM, monarch_dodra wrote: > [SNIP] I don't think this does what you think it does. The 'is(R r)' declares r to be an alias for R. So 'r' is a type in that code snippet. Darn :( Also, is(typeof(takeExactly(R, 1))) && is(R == typeof(takeExactly(R, 1))) can be written in a more compact way as is(typeof(takeExactly(R, 1)) == R) Technically, no: That was my first try, and as mentioned in the first reply, this returns true when the types of takeExactly and R are equal comparable, but does not make sure they are the actually the same types. ... I assume you messed up the parentheses. is(typeof(takeExactly(R, 1) == R)) // test for equal-comparable is(typeof(takeExactly(R, 1)) == R) // test for type identity alias float flt; static assert(is(typeof(1==flt))); static assert(!is(typeof(1)==flt)); Yes sorry. I miss read that. Kind of weird though, could you explain why: struct S{}; is(typeof(takeExactly(S, 1)) == S) //false is(S == typeof(takeExactly(S, 1))) //Error: template std.range.takeExactly does not match any function template declaration I was under the understanding that == was a commutative operation. Not the case in an is block? It is special syntax, not an == operator. is-expressions suppress errors in the first argument only.
Re: Testing for template argument being result of takeExactly
On 09/26/2012 05:08 PM, Andrei Alexandrescu wrote: On 9/26/12 9:50 AM, monarch_dodra wrote: struct S{}; is(typeof(takeExactly(S, 1)) == S) //false is(S == typeof(takeExactly(S, 1))) //Error: template std.range.takeExactly does not match any function template declaration Neither should work. The expression should be takeExactly(S.init, 1). Andrei http://d.puremagic.com/issues/show_bug.cgi?id=8220 https://github.com/D-Programming-Language/dmd/pull/1007
Re: template condition
On 09/27/2012 03:01 PM, Namespace wrote: Is there any difference between these two code snippets: #1: struct Foo(T : Object) { #2: struct Foo(T) if (is(T == class)) { ? I ask because I prefer option #1, but I see most often in Phobos variant #2. Yes there is: struct S{ Object o; alias o this; } #1 accepts S, #2 does not.
Re: Struct assignment, possible DMD bug?
On 09/29/2012 06:26 PM, Maxim Fomin wrote: On Saturday, 29 September 2012 at 16:05:03 UTC, ixid wrote: This behaviour seems inconsistent and unintuitive: void main() { int[3] a = [1,2,3]; a = [4, a[0], 6]; struct S { int a, b, c; } S s = S(1,2,3); s = S(4, s.a, 6); assert(a == [4,1,6]); assert(s == S(4,4,6)); } Setting the struct writes s.a before evaluating it while the reverse is true of the array assignment. Using DMD 2.0.60. GDC does what I'd expect and gives both as 4,1,6. I think this is notorious "i = ++i + ++i". There is only one mutating sub-expression. Statement s = S(4, s.a, 6) writes to s object and simultaneously reads it. http://dlang.org/expression.html states that assign expression is evaluated in implementation defined-manner and it is an error to depend on things like this. No evaluation order of the assignment expression can possibly lead to this result. This seems to be a DMD bug.
Re: Struct assignment, possible DMD bug?
On 09/30/2012 12:51 AM, Ali Çehreli wrote: On 09/29/2012 11:16 AM, Timon Gehr wrote: > On 09/29/2012 06:26 PM, Maxim Fomin wrote: >>> S s = S(1,2,3); >>> s = S(4, s.a, 6); >>> >>> assert(a == [4,1,6]); >>> assert(s == S(4,4,6)); >>> } >>> >>> Setting the struct writes s.a before evaluating it while the reverse >>> is true of the array assignment. Using DMD 2.0.60. GDC does what I'd >>> expect and gives both as 4,1,6. >> >> I think this is notorious "i = ++i + ++i". > > There is only one mutating sub-expression. But that mutation is happening to an object that is also being read inside the same expression. This is one of the definitions of undefined behavior, not a compiler bug. >> Statement s = S(4, s.a, 6) writes to s object and simultaneously reads >> it. >> http://dlang.org/expression.html states that assign expression is >> evaluated in implementation defined-manner and it is an error to depend >> on things like this. > > No evaluation order of the assignment expression can possibly lead to > this result. This seems to be a DMD bug. The compiler seems to be applying an optimization, which it is entitled to as long as the language definition is not violated. Technically there is no language definition to violate. If we are using the same object both to read and write in the same expression, then we should expect the consequences. No. Why? Disclaimer: I assume that D's rules are the same as C and C++ here. C and C++ do not have struct literals and if I am not mistaken, constructor invocation is a sequence point. Besides, this does not make any sense, what is the relevant part of the standard? int c = 0; c = c+1; // c is both read and written to in the same expression
Re: liittle question about reduce
On 09/30/2012 01:04 AM, bioinfornatics wrote: hi, int[] list = [ 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; why this do not works ? list.reduce!( (a,b) => a + b )( 0 ); // sum all elements but by this way that is ok: reduce!( (a,b) => a + b )( 0, list ); // sum all elements Because of the parameter order. 0.reduce!((a,b)=>a+b)(list); // works
Re: Functional vs simple code
On 10/02/2012 10:48 PM, ixid wrote: Without optimization the range and algorithm method takes about 10 times as long as the simple code below it, with no array bounds checking and optimization it takes six times as long. Why is the difference so huge? I'd expect a moderate overhead but that's a big difference. module main; import std.stdio, std.algorithm, std.range, std.datetime; enum MAX = 10_000_000UL; void main() { StopWatch sw; sw.start; auto sum1 = MAX.iota.map!(x => x * x).reduce!"a + b"; sw.peek.msecs.writeln("msecs"); sum1.writeln; sw.start; ulong sum2 = 0; foreach(i;0..MAX) sum2 += i * i; sw.peek.msecs.writeln("msecs"); sum2.writeln; } $ cat ixidbench.d module main; import std.stdio, std.algorithm, std.range, std.datetime; enum MAX = 10_000_000_000UL; void main() { StopWatch sw; sw.start; auto sum1 = MAX.iota.map!(x => x * x).reduce!"a + b"; sw.stop; sw.peek.msecs.writeln("msecs"); sum1.writeln; sw.reset; sw.start; ulong sum2 = 0; foreach(i;0..MAX) sum2 += i * i; sw.stop; sw.peek.msecs.writeln("msecs"); sum2.writeln; } $ ldmd2 -O -release -inline ixidbench.d -ofixidbench $ ./ixidbench 6528msecs 7032546979563742720 7518msecs 7032546979563742720
Re: Functional vs simple code
On 10/03/2012 12:11 AM, Timon Gehr wrote: ... $ cat ixidbench.d module main; import std.stdio, std.algorithm, std.range, std.datetime; enum MAX = 10_000_000_000UL; void main() { StopWatch sw; sw.start; auto sum1 = MAX.iota.map!(x => x * x).reduce!"a + b"; sw.stop; sw.peek.msecs.writeln("msecs"); sum1.writeln; sw.reset; sw.start; ulong sum2 = 0; foreach(i;0..MAX) sum2 += i * i; sw.stop; sw.peek.msecs.writeln("msecs"); sum2.writeln; } $ ldmd2 -O -release -inline ixidbench.d -ofixidbench $ ./ixidbench 6528msecs 7032546979563742720 7518msecs 7032546979563742720 $ gdmd -O -release -inline ixidbench.d -ofixidbench $ ./ixidbench 11250msecs 7032546979563742720 11233msecs 7032546979563742720
Re: Question about anonymous delegates.
On 10/03/2012 03:53 PM, Sharp wrote: I found something what I don't understand. Here is a simplifed code with comments: http://dpaste.dzfl.pl/a914d11a I creating anonymous delegates, whose function is to modify their parameter. Their parameters are different class references. I pass these class references to anonymous delegates, but the delegates obtain only the last passed class reference. Thanks for your answers. class Num { int a; } void main(){ auto nums = new Num[10]; alias void delegate() Func; auto funcs = new Func[10]; // workaround for http://d.puremagic.com/issues/show_bug.cgi?id=2043 ahead: for(int i = 0; i < 10; ++i) (){ Num num = nums[i] = new Num(); int i=i; // fix for bug in your code funcs[i] = {num.a = i;}; }(); foreach(num; nums) { assert(num.a == 0); } foreach(func; funcs) { func(); } foreach(i, num; nums) { assert(num.a == i); } }
Re: Function pointer variable not recognized as function by is-operator
On 10/07/2012 10:35 AM, Jonathan M Davis wrote: On Sunday, October 07, 2012 10:25:41 Tommi wrote: The following compiles, which I'm pretty sure must be a bug, right? Just checking to be sure I won't be polluting the bug tracker. void main() { auto f = (int i) {}; static assert (!is(f == function)); // should fail static assert (!is(f == delegate)); } It's not a bug. is(f == function) checks for functions, not function pointers. http://stackoverflow.com/questions/11067972 - Jonathan M Davis Actually is(f==function) checks whether or not f is a function type. The ==function part is unimportant, because f is not even a type.
Re: Using inout in delegates
On 10/05/2012 04:09 PM, Ali Çehreli wrote: ... This workaround makes the compiler happy: void foo (inout(int)[] arr) { auto a = (inout int) { auto b = arr[0]; }; } But probably not what you want. :/ IIRC, inout has bugs and incomplete implementation. I think this should be in the bug database. Ali The original behaviour is to be expected and the workaround exploits a compiler bug. The correct way to get rid of the compile error is: void foo(inout(int)[] arr){ auto a = { const b = arr[0]; } // or int b = arr[0]; }
Re: Calling un-overridden class method
On 10/13/2012 04:22 AM, H. S. Teoh wrote: ... // PROBLEM #1: due to PROBLEM #1, this causes an // infinite recursion that eventually overflows // the stack. ... I'm sure it does :). @topic: yes this is a bug.
Re: Operator overloading through UFCS doesn't work
On 10/13/2012 06:02 PM, Maxim Fomin wrote: ... Different groups of people have different mind and same things produce different sense on them. From my point of view operator overloading methods are special functions and not treating them as candidates for UFCS does make more sense. I do not understand how an operation that happens to be called '+' is fundamentally different from an operation that is called 'add'. Even if you convince in your opinion, language addition without applied purposes makes no benefit. I guess the functionality could be achieved in DMD mostly by removing code. (Code for good error messages excluded!)
Re: Operator overloading through UFCS doesn't work
On 10/13/2012 10:15 PM, Jonathan M Davis wrote: ... construct is using syntactic sugar such as UFCS, because _all_ of that syntactic sugar must be lowered to code which _isn't_ syntactic sugar anymore. That is not what lowering means. It would be far more expensive to have to continually make passes to lower code over and over again until no more lowering was required than it would be to just have to lower it once. ... It does not have to be implemented it in an inefficient way. It is actually simpler for a sane compiler implementation to make UFCS apply to lowered overloaded operators than to restrict it. You're reading way to much into what TDPL is saying. It's simply telling you about how the compiler goes about translating code which uses operators such as +, >, or = into the functions that you used to overload them. It's _not_ telling you that it'll do UFCS on overloaded operator functions. It is telling us that a+b is transformed to a.opBinary!"+"(b) UFCS applies to a.opBinary!"+"(b). Heck, technically, TDPL never really says that D _has_ UFCS. It talks about the member call function syntax for _arrays_ (which D had for ages before it had UFCS), not for types in general. It's only very recently that full UFCS has been added to the language. Exactly, so what is the point? If TDPL does not talk about the UFCS feature, then TDPL not talking about UFCS in the context of one specific case certainly cannot be used as an argument to justify that it should not apply in that case. Both overloaded operators and UFCS use lowering to generate different code which the compiler then compiles, By using the same strategy recursively, otherwise it is not called lowering. but they _aren't_ mixed and they will _never_ be mixed. If it had _ever_ been intended that it be possible to overload operators as free functions, then we'd simply have made it so that you could declare a free function like auto opBinary(string op)(Foo foo, Bar bar) { ... } in the first place without requiring that it be a member function. You can. But it _was_ required to be a member function, and it would make no sense to allow a new feature to circumvent that restriction. If it was supposed to be circumventable, then the restriction wouldn't have been put there in the first place. This argument is even less convincing in the context of an informally specified language with a somewhat buggy reference compiler.
Re: Operator overloading through UFCS doesn't work
On 10/14/2012 12:36 AM, H. S. Teoh wrote: On Sun, Oct 14, 2012 at 12:12:01AM +0200, Timon Gehr wrote: On 10/13/2012 10:15 PM, Jonathan M Davis wrote: [...] but they _aren't_ mixed and they will _never_ be mixed. If it had _ever_ been intended that it be possible to overload operators as free functions, then we'd simply have made it so that you could declare a free function like auto opBinary(string op)(Foo foo, Bar bar) { ... } in the first place without requiring that it be a member function. You can. But it _was_ required to be a member function, and it would make no sense to allow a new feature to circumvent that restriction. If it was supposed to be circumventable, then the restriction wouldn't have been put there in the first place. This argument is even less convincing in the context of an informally specified language with a somewhat buggy reference compiler. OK, before this thread devolves into a shouting match, I'd like to understand what was the rationale behind this restriction. What were the reasons behind not allowing a non-member function to overload an operator? What are the pros and cons considered at the time, and how do they weigh now? Or was it just a matter of not being implemented because nobody thought about it at the time? T Afaik free-function operator overloads (but not in the context of UFCS) were considered and turned down because D did not want to get amidst discussions about adding Koenig lookup. UFCS does not do Koenig lookup.
Re: Operator overloading through UFCS doesn't work
On 10/15/2012 01:00 PM, Artur Skawina wrote: ... An overloaded operator is just another normal method; you get the same type of problems when dealing with "normal" methods - eg in types having an "alias this" - an UFCS "method" must take precedence over one reachable via the alias - just like in the overloaded op case. The only sane alternative would be disallowing UFCS for types with an "alias this" (which would be a severe limitation). ... Just no. Why make symbol lookup even more complicated just in order to add an strange exception to the language that either enables new forms of hijacking or would be a severe limitation?
Re: Operator overloading through UFCS doesn't work
On 10/16/2012 05:57 PM, Maxim Fomin wrote: ... At NG discussion it may look nice to define some type and then add operator overloading methods Operator overloading is not magic, so your statement can be shortened to ... and then add methods Which is still not correct, because that is not what UFCS does. but as soon as you import some other modules, authors of which also consider UFCS operators a good idea, Who has stated that? It just does not make sense to explicitly ban them, as they are not special. everything breaks including namespace conflict The usual disambiguation procedures apply. (Which are broken in DMD at the moment, because module-scope private symbols can cause conflicts.) Infix operators are not special. It is just notation. as well as loosing ability to manipulate that type within built-in expression as well. I did not get that.
Re: Operator overloading through UFCS doesn't work
On 10/14/2012 09:14 AM, Maxim Fomin wrote: On Sunday, 14 October 2012 at 07:01:30 UTC, Tommi wrote: Actually, it seems that alias this has precedence over UFCS. So, a free function opUnary wouldn't ever suit better than an actual method opUnary of the thing referred to by that alias this. http://dpaste.dzfl.pl/d0a4431d Free function doesn't suit better than actual method. The issue is absence of the actual method. opUnary method has priority over alias this, which does make sense because alias this is chosen only when it is impossible to apply operation over A type. If this request is approved and compiler has opUnary definition outside type (which suits better then alias this) such function would hijack alias this. If not, there is a new case when something is going special than at usual cases and only for the purpose of writing operator overloading methods outside the body of the type. The goal must be to get rid of all special behaviour that can result in strange interactions. Add the suitable operator function templates to built-in types. Always rewrite operators to operator function calls. Problem solved. (And people are already asking for custom constant folding procedures, even without having this in place to use as a supporting argument.)
Re: Operator overloading through UFCS doesn't work
On 10/14/2012 09:01 AM, Maxim Fomin wrote: On Saturday, 13 October 2012 at 19:50:02 UTC, Timon Gehr wrote: On 10/13/2012 06:02 PM, Maxim Fomin wrote: ... Different groups of people have different mind and same things produce different sense on them. From my point of view operator overloading methods are special functions and not treating them as candidates for UFCS does make more sense. I do not understand how an operation that happens to be called '+' is fundamentally different from an operation that is called 'add'. The first one is an operator, which sometimes, may be rewritten to function call, the second one is a function call. What is the difference between an operator and a function call? Is it important? int add(int a, int b){ return a+b; } // or conversely (not valid syntax): int (int a)+(int b){ return add(a,b); } Even if you convince in your opinion, language addition without applied purposes makes no benefit. I guess the functionality could be achieved in DMD mostly by removing code. (Code for good error messages excluded!) I don't understand what you are trying to say. Anyway, you can write a pull request and propose it at github. It would be interesting to see reaction of others. Built-in types shouldn't be special except maybe that the parser recognises related keywords. It should go like this: a + b => a.opBinary!"+"(b); // opBinary_r woes left out, // but would require treatment a + b => __add(a,b); // if a and b of built-in type a.opBinary!"+"(b) => __add(a,b); // if a and b of built-in type Where __add(a,b) is the representation of an AST node of a built-in add operation involving operands a and b. All the code in DMD that supposedly tries to make up for this kind of inconsistencies (and sometimes fails, because it does not catch all the ways the language features interact) can be gotten rid of.
Re: Operator overloading through UFCS doesn't work
On 10/17/2012 01:51 PM, Maxim Fomin wrote: On Wednesday, 17 October 2012 at 11:11:26 UTC, Timon Gehr wrote: On 10/14/2012 09:14 AM, Maxim Fomin wrote: On Sunday, 14 October 2012 at 07:01:30 UTC, Tommi wrote: Actually, it seems that alias this has precedence over UFCS. So, a free function opUnary wouldn't ever suit better than an actual method opUnary of the thing referred to by that alias this. http://dpaste.dzfl.pl/d0a4431d Free function doesn't suit better than actual method. The issue is absence of the actual method. opUnary method has priority over alias this, which does make sense because alias this is chosen only when it is impossible to apply operation over A type. If this request is approved and compiler has opUnary definition outside type (which suits better then alias this) such function would hijack alias this. If not, there is a new case when something is going special than at usual cases and only for the purpose of writing operator overloading methods outside the body of the type. The goal must be to get rid of all special behaviour that can result in strange interactions. Add the suitable operator function templates to built-in types. Always rewrite operators to operator function calls. Problem solved. ... You have a struct with alias this to int without overloaded operators. It (say, struct.d) contains code with structure increments. Some other module (say bob.d), which import the structure, defines function supposed to overload opUnary. If operators are always rewritten to function calls, now function should be called in module bob.d, as well as in struct.d if they are compiled together. It certainly not what author of struct.d expected. The case can be even more interesting, if alias this in struct.d were absent at a time when bob.d was written and at some point of future Bob is updating his sources. Members do not cause conflicts with free functions. Alias this takes precedence as it is a member of the type. What is the issue?
Re: Operator overloading through UFCS doesn't work
On 10/17/2012 01:32 PM, Maxim Fomin wrote: On Wednesday, 17 October 2012 at 11:00:05 UTC, Timon Gehr wrote: On 10/16/2012 05:57 PM, Maxim Fomin wrote: ... At NG discussion it may look nice to define some type and then add operator overloading methods Operator overloading is not magic, so your statement can be shortened to ... and then add methods Which is still not correct, because that is not what UFCS does. It is not correct as long as you cavil at lexis, however the statement has room for correction. In a discussion it is crucial that both parties agree on a common set of terms and definitions. Otherwise agreement cannot be detected. but as soon as you import some other modules, authors of which also consider UFCS operators a good idea, Who has stated that? It just does not make sense to explicitly ban them, as they are not special. Who stated that they should be "explicitly banned"? Well, you did, if I got that right: On 10/13/2012 06:02 PM, Maxim Fomin wrote: From my point of view operator overloading methods are special functions and not treating them as candidates for UFCS does make more sense. (Explicitly banning UFCS operators is the same thing as not treating rewritten operators as candidates for UFCS.) I explained potential problem in previous posts. Yes, several times, but to me the argument still looks similar to the following (note that only the 'counter argument' part is related to this discussion): Issue: the 'body' keyword is not used enough to warrant keyword status, parsing could succeed without making it a full keyword. Proposed solution: make 'body' a valid identifier that is only recognised as special where it is expected to occur. Main counter argument: Two people might define a symbol using the newly available 'body' identifier, which can cause symbol conflicts. Do you agree with this reasoning, and if not, what is the fundamental difference between this and the point you are trying to convey? everything breaks including namespace conflict The usual disambiguation procedures apply. (Which are broken in DMD at the moment, because module-scope private symbols can cause conflicts.) Infix operators are not special. It is just notation. as well as loosing ability to manipulate that type within built-in expression as well. I did not get that. Again, the problem is in conflict between different declared operator overloading functions across different modules. Can you explain the usage of the term 'built-in' in this context?
Re: Returning dynamic array from the function
On 10/17/2012 10:15 PM, sclytrack wrote: On Wednesday, 17 October 2012 at 19:46:51 UTC, bearophile wrote: sclytrack: It doesn't give an error when marking the function with safe. @safe int[] create() { } I think marking it @safe is not relevant. In theory a good type system should give an error message on similar code. I don't know if D is supposed to spot similar error situations. Bye, bearophile If that's the case then they should call it safeR D instead of safe D. I think what he meant to say was that it should be illegal to do this even in @system code, not that it is OK that it passes with @safe.
Re: opCast using in template struct
On 10/18/2012 11:45 PM, bearophile wrote: Era Scarecrow: It's an easy mistake to make. Maybe the compiler should issue a warning when opAssign attempts and fails and opOpBinary is defined. This would have to be implemented very carefully. There are enough hard to reproduce symbol resolution bugs already. It does not get better by introducing hidden and unnecessary lookups. If you have strong feelings about this, then add a Bugzilla entry. There are other cases. Generally the D compiler should add some warnings that help against operator overloading mistakes. Bye, bearophile I don't think that operator overloading gives rise to distinct mistakes. For example, better error messages that just specify the expected name, as in other cases of undefined identifiers, would already fix this.
Re: opCast using in template struct
On 10/19/2012 01:05 AM, Era Scarecrow wrote: On Thursday, 18 October 2012 at 22:07:55 UTC, Timon Gehr wrote: On 10/18/2012 11:45 PM, bearophile wrote: There are other cases. Generally the D compiler should add some warnings that help against operator overloading mistakes. I don't think that operator overloading gives rise to distinct mistakes. For example, better error messages that just specify the expected name, as in other cases of undefined identifiers, would already fix this. Inside a function a badly named identifier becomes obvious since it outright tells you. But with regards to opOpAssign and other operator overloading I see the error message and I see the call but I don't see why it fails. My suggestion was something like: error: expression 'e' of type 'S' is not of arithmetic type and it does not define opOpAssign!"+". The compiler should indicate exactly why it fails. If this is not enough, then the programmer certainly deserves the headache. Then I'll try adjusting the signature on my function, not realizing it never sees it in the first place due to misspelling. If the issue _is_ with the signature, then the compiler should tell you. That is the (secondary) job of the compiler. Maybe.. A general warning when something starts with 'op(Op)?[A-Z]' 'op[A-Z]' but doesn't actually qualify as any of the override-able operators? That seems sensible... That is a lot better, but what if the typo is within the first 3 characters? :o)
Re: opCast using in template struct
On 10/19/2012 01:23 AM, bearophile wrote: Era Scarecrow: Maybe.. A general warning when something starts with 'op(Op)?[A-Z]' but doesn't actually qualify as any of the override-able operators? That seems sensible... Regarding operator overloading there are several situations worth warning the programmer of. The D compilers should be improved on this. Bye, bearophile What situations?