News for hackers. Stuff that matters.
Re:Writing Complex Macros in Rust: Reverse Polish Notation by TheCoelacanth on Friday February 02, 2018 @01:39PM (#16292982)
It makes them more flexible in the same way that dynamic typing is more flexible. A type error that doesn't execute doesn't really exist either.

It's fine to not worry about types that don't get instantiated if you are the only person ever instantiating a template, but that's obviously not always the case. If my template doesn't typecheck for a type that someone else wrote, I don't find out about it until they send me a bug report. With typechecking before instantiating, I find out about it as soon as I write it.

Re:Writing Complex Macros in Rust: Reverse Polish Notation by kazinator on Friday February 02, 2018 @02:49PM (#16293663)
Except it's not dynamic typing; everything that goes into the output image is type checked.

> A type error that doesn't execute doesn't really exist either.

Nope; that depends on what you mean by "doesn't execute".

Provably doesn't execute? As in: it is removable, dead code?

Or: doesn't execute because it's not covered by a test case? So that it could execute if a suitable input is found?

A template-generated type that is not instantiated doesn't execute because it doesn't exist. It's not in the image. There is no possible input to the program which can exercise it.

The code is basically not written. There is no need to diagnose bugs in code that isn't written.

Making users derive template arguments from a specific type is just stupidly "blubby". That C++ has typeless template parameters is one of the few sane things about the way it supports generic programming.

> With typechecking before instantiating, I find out about it as soon as I write it.

With type checking, that same user who would have run into a problem with the "typeless template" will simply find your template useless, and roll their own. In other words, same situation as before. The type error will still be there.

If you have a template that is intennded with foo-like arguments, and the user uses them with a bar-like object, that's going to be diagnosed one way or another.

If the generic arguments are weak, it will show up as some constraint violation when the template-generate code uses the the bar-like thing as if it were foo-like.

If the generic arguments are strong, the user instead gets an error that the bar-like thing is not a suitable argument to the template, which expects a foo-like.

It's the same either way; it's all static checking at the same static time and it doesn't change the circumstances under which errors occur. It just changes the amount of discipline needed to use the generic, and the accuracy/granularity of the diagnostic ("this thing is not a foo" versus "this thing here coming from a template parameter can't be used in this way in this piece of template generated code").

It's easier for the user to adjust the bar object to make it sufficiently foo-like for a given template, than to make it completely conform to the foo type.

Re:Writing Complex Macros in Rust: Reverse Polish Notation by TheCoelacanth on Friday February 02, 2018 @05:50PM (#16294890)
> With type checking, that same user who would have run into a problem with the "typeless template" will simply find your template useless

Unless you have a bug in your template that causes it to have a type error for a type that you didn't intend for it to have a type error for.

Re:Writing Complex Macros in Rust: Reverse Polish Notation by kazinator on Saturday February 03, 2018 @01:17AM (#16296466)
If the template works (is tested with) with a foo (base class), there is no reason it wouldn't work with something derived from foo. (If not, then there is some LSP issue in the foo type hieararchy; the generic as such is working.)

You might intend (without actually testing) that the template works with some bar also, not related to foo; the user tries it and finds otherwise, due to a bug.

With the typed generic, you just declare that it's for foo, and it refuses to work with bar (whether or not it has a bug which would actually prevent that in the absence of the declaration).

All the declaring, checking, instantiation, and the rest of it are all happening in the same time: static time. There is no difference like with static versus dynamic. Static versus dynamic is due to different times: what is done before running the program, versus during.

There is no verification difference between declaring that a template parameter may be of types foo | bar, and writing a typeless template which a test module then instantiates for foo and bar. Both are declarative mechanisms at work, played out statically. Just one way is more open-ended; it's not "sealed" against new instantiations.