"I made a game using Rust"
Adrian Matoga via Digitalmars-d
digitalmars-d at puremagic.com
Wed May 10 08:50:06 PDT 2017
On Wednesday, 10 May 2017 at 15:03:19 UTC, Adam D. Ruppe wrote:
> On Wednesday, 10 May 2017 at 14:02:38 UTC, Adrian Matoga wrote:
>> Would you mind giving some examples?
>
> What bothers me on a regular basis is overloading. Basic case:
>
> $ dmd lll
> lll.d(6): Error: none of the overloads of 'foo' are callable
> using argument types (int, double), candidates are:
> lll.d(1): lll.foo(int a, int a)
> lll.d(2): lll.foo(int a, string s)
>
> Contrast that to g++:
>
> $ g++ lll.cpp
> lll.cpp: In function ‘int main()’:
> lll.cpp:7:14: error: no matching function for call to ‘foo(int,
> Foo)’
> foo(0, Foo());
> ^
> lll.cpp:7:14: note: candidates are:
> lll.cpp:1:6: note: void foo(int, char*)
> void foo(int a, char* b);
> ^
> lll.cpp:1:6: note: no known conversion for argument 2 from
> ‘Foo’ to ‘char*’
> lll.cpp:2:6: note: void foo(int, float)
> void foo(int a, float b);
> ^
> lll.cpp:2:6: note: no known conversion for argument 2 from
> ‘Foo’ to ‘float’
>
>
>
> The g++ example isn't great either... but is better because of
> this: "no known conversion for argument 2 from ‘Foo’ to ‘float’"
>
>
> It actually told me which argument didn't match! clang is
> similar:
>
> $ clang lll.cpp
> lll.cpp:7:2: error: no matching function for call to 'foo'
> foo(0, Foo());
> ^~~
> lll.cpp:1:6: note: candidate function not viable: no known
> conversion from 'Foo' to 'char *' for 2nd argument
> void foo(int a, char* b);
> ^
> lll.cpp:2:6: note: candidate function not viable: no known
> conversion from 'Foo' to 'float' for 2nd argument
> void foo(int a, float b);
>
>
>
> With the dmd one, especially on a long function, it is hard to
> tell just which argument is giving trouble. The C++ errors just
> flat out tell me which argument didn't match for each candidate.
In this simple case above, I actually prefer DMD's messages, as
there's simply less text for my eyes to read and brain to parse,
so I can quickly spot where the problem is.
I agree, though, that with longer argument lists, especially with
const vs. non-const or template constraints, trying to figure out
what's wrong could be at least frustrating.
> Templates with constraints are even worse.
>
> lll.d(3): Error: template std.algorithm.sorting.sort cannot
> deduce function from argument types !()(int), candidates are:
> /home/me/d/dmd2/linux/bin32/../../src/phobos/std/algorithm/sorting.d(1830): std.algorithm.sorting.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && (hasSwappableElements!Range || hasAssignableElements!Range) || ss != SwapStrategy.unstable && hasAssignableElements!Range) && isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range)
>
>
> What a mess! Just formatting that output might help, but I'd
> especially love it if it told me which individual boolean
> elements failed, passed, and were short-circuited. The compiler
> knows this, it had to evaluate that to figure out it didn't
> match, but it doesn't tell me.
>
> At a glance, can you even tell what I passed to the function?
>
> Bonus points would be it telling me why, for example,
> `isInputRange` failed, but I understand that is an even bigger
> problem to solve.
It's indeed painful, but I found UDAs to be useful in dealing
with it.
First, I'm sure you know Atila's concepts [1].
I also use UDAs in flod [2], so instead of checking whether the
implementation satisfies a constraint, I only check if it's
explicitly tagged with a specific UDA. Now, I immediately see
whether it's a method that I forgot to implement or just a typo,
instead of being forced to guess by a "missing overload" message.
>
> Of course, C++ doesn't have constraints so there's no
> comparison there.
>
>
> Lastly, check this out:
>
> lll.d(5): Error: function lll.foo (Color c) is not callable
> using argument types (Color)
>
> WTF, right? Well, I have a locally defined `struct Color` and
> an imported one. Same name, but different type. The error
> message doesn't tell me which one is which.
Yeah, that one was funny. :)
> These are the top 3 dmd error messages that bother me
> regularly. At runtime, little drives me more nuts than
> RangeError not telling me the index and the length. Again, it
> knows, the code checked it, but it didn't report it.
Same with assertions. I usually end up adding wrappers like
assertEqual, and the more I use them, the more I feel like
switching to something like [3] or [4], as much as I normally
prefer to keep the number of dependencies low.
I think RangeError could be solved without much effort by
changing the compiler/runtime interface at _d_arraybounds*.
Assertions are probably harder.
[1]
http://forum.dlang.org/post/eoxerbkaowxpgjubhdqq@forum.dlang.org
[2] https://github.com/epi/flod/blob/develop/source/flod/package.d
[3] https://code.dlang.org/packages/fluent-asserts
[4] http://code.dlang.org/packages/unit-threaded
More information about the Digitalmars-d
mailing list