4 ms·
I seem to be in the minority but I really dislike this type of sugar. I find that it always makes code harder to read because you can't disambiguate what the co
by simias 6y ago
I seem to be in the minority but I really dislike this type of sugar. I find that it always makes code harder to read because you can't disambiguate what the code is doing without some heavy context, and changes to the class can profoundly change the way the code is behaving without triggering as much as a warning.
For this same reason I really dislike that in C++ you can just implicitly drop the "this->" to target class members. You can never tell at a glance what "foo = blah" does if you don't know whether "foo" is a member of "this" or not.
I think your page demonstrates what I mean in the "nested WithStatement" example:
Foo foo;
Bar bar;
Baz baz;
f(); // prints "f"
with(foo)
{
f(); // prints "Foo.f"
with(bar)
{
f(); // prints "Bar.f"
with(baz)
{
f(); // prints "Bar.f". `Baz` does not implement `f()` so
// resolution is forwarded to `with(bar)`'s scope
}
}
with(baz)
{
f(); // prints "Foo.f". `Baz` does not implement `f()` so
// resolution is forwarded to `with(foo)`'s scope
}
}
with(baz)
{
f(); // prints "f". `Baz` does not implement `f()` so
// resolution is forwarded to `main`'s scope. `f()` is
// not implemented in `main`'s scope, so resolution is
// subsequently forward to module scope.
}
Wi
I get that sometimes it can cut on a lot of repetition, but I think I would be fine if the syntax was more explicit while still avoiding repetition, for instance:
with (some_object) {
.some_member = 1;
.some_other = 4;
not_a_member = .some_method();
}
And beyond that make it non nestable (i.e. only the first level of "with" is taken into account) to avoid the situation above with complicated overloading.
In my experience that would account for 99% of uses of `with` while making the code a lot more readable without requiring a lot of context to make sense of it.
Although frankly even that might arguably overkill, for dynamic languages or ones with type inference you might as well just do something like:
{
let v = &mut some_annoyingly.long.thing();
v.foo = bar;
v.baz();
}
It's almost the same amount of typing and you don't need any magic.
- mhh__ 6y agoThis is true however with is fairly uncommon, so as with any feature of languages that add syntax like this it's up to your judgement as to when to use it.
- TinkersW 6y agoUse syntax highlighting that differentiates between members and non members, problem solved.
- simias 6y agoThat implies a very good "smart" highlighter that has in-depth knowledge of the language, something I don't like to rely upon because it's not always available and/or working properly.
- elcritch 6y agoThe Nim `with` macro by @zevv doesn't modify functions or methods (that'd require explicit handling in the macro to do so and would be a nightmare to do correctly). Which means that example from D is not applicable to the Nim version at all. My preference is Nim over D primarily since Nim compiles to C, but also overall the community appreciates syntax sugar but also has a decent sense as to when and how to use it. Most "sugar" in Nim needs to be explicitly imported. Literally `import sugar` is one of my first lines in many files. let v = &mut some_annoyingly.long.thing(); v.foo = bar; v.baz(); In the example you list (is that Rust, or D?), if it was in C or Nim and those were structs-within-structs and not pointers/refs then `.thing` would be copied to a new `v` (if I recall the semantics correctly). So you'd end up with a weird "logic" bug where updates would disappear. The Nim `with` macro solves that by modifying the generated code,