Syntax survey for a potential RFC (please participate, especially if you don't know Rust too well :) )

You can always use fully qualified syntax to disambiguate.

let forest = <Forest as Default>::default();

If you're arguing that Forest::default() is unacceptable because of this edge case, then I propose turbofish to the rescue.

1 Like

Yes, but this only works to distinguish methods from traits. Methods implemented directly on type are always called like Forest::default().

That's why use of Forest::default to clarify that we are dealing with method with method from Default trait is very strange.

Full form <Forest as Default>::default() works, sure, but it's long and is not clear what's the advantage over traditional Default::default().

I feel like t while discussion is problematic. There is no valid case for implementing a Forest::default() that differs from Default::default(). Choosing your programming style under the assumption that you or an author of a create you're using might be a hostile actor is pointless. Just don't use code from untrusted parties.

Forest::default() is preferred because it is often challenging for humans to infer the type even when the cop l compiler is able to do so.

5 Likes

Category wise (others' have said this too) I spent more time deciding if I "regularly help others on this forum" (which isn't accurate) vs "PREFER to just learn" which also isn't accurate.

Default::default() outside of a generic impl scope makes me first think "ambiguous", but as I think more, the only valid answer is that Default is the enclosing type - it isn't immediately obvious to me at first (totally get the conversation - just giving my first reaction to the syntax). My fear is C++ scope resolution madness.

My naked intuition went to typescript ... splay operator. And the intuition reasoning was to construct a completely valid document and underlay matching fields. So I think it maps well to people from that discipline (aside from the Default:: )

1 Like

If Forest doesn't impl Default maybe? And somehow you are relying on other default features???? (Seems like a stretch)

Or perhaps when writing macros, using Self and Default may make some macro synthesizers easier to write. I use to write a lot of Java reflection synthesizer code, and it often was cleaner code to use the most generic possible base type. I use to get dinged by sonarcube in those synthesizers.

That's incorrect: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b511ec763032fe6be6fad3d37a80b978

1 Like

Sorry, my bad. Indeed NaN != NaN is true, which means x != x can be true, too, which was explicitly done to make handling of NaNs easier.

Of course no one handles them like that since all CPUs have special instruction which can be used for these purposes. But the fact that x != x means == is no longer equivalence and <= is no longer a partial order means many algorithms may produce garbage when feed list of floats with some NaNs.

BUT I write code, rather than read it. I don't disagree that there can be confusion just I don't care. Testing easily finds and easy to fix. Hard to test/fix are the bugs to get rid of.

[spoiler]
Code does not compile without impl Default for Forest so can't be a later added implementation that causes breakage. (regression bug.)

Code as written doesn't compile, sure. But Forest::default() would compile if there are impl Default for Forest and no actual Forest::default() function.

Some claim that it's still better to call that non-existing function and rely on the fact that it would, actually, call Default::default (similarly with how one calls foo.into() without fearing that Foo may, at some later date, get different into() function), but I'm not sure it's good idea: we already have Default::default() and Forest::new() for the exact same thing, adding third form sounds like an overkill.

You never go back and read code you have written? Not even when looking for those bugs you mentioned.

I have to write code that is as obvious as possible. If only so that I understand it when coming back to it weeks or months later. The problems I'm trying to solve in a programming language are complex enough for me, I don't need any extra obscurity layered on top by cleaver use of the language.

Have you never found yourself reading some code and thinking "what twerp wrote this?". Only to then realise it was yourself !

Yes.

Nope. I keep hearing that tale, but somehow, even if I look on code which I wrote 10 years ago crazy and strange parts are never mine.

I, sometimes, feel a bit ashamed by some decisions and think well… if I knew back then what I know now I wouldn't have written it in that way, but if I feel that code is just plain out weird and I have no idea how can it ever work… then it's something like this (and then it really doesn't work) or it's written by someone much more knowledgeable than me.

I have also never experienced that wonderful effect, promised to me: "when would you read your own code, comments would help you understand it" (and when I was a student I wrote pretty significant amount of comments as my professors demanded).

Either everything was easy to understand from the code or, in some cases, comments haven't explained anything because they were correct and code was wrong, but they were never needed to explain what happens in the code with one exception: when they were needed to clarify something not mentioned in the official documentation, but discovered in some other place (blog post, some kind of lecture, by experimentation of we are talking about hardware quirks). Something which wasn't part of the code but which you may forget about. These (and only these) comments are useful.

1 Like

I wonder what that means. Either you are really good and never forget anything. Or you did not learn anything about the language, platform or problem domain in all that time :slight_smile:

Ah, but that is a lot of what I'm talking about. So I guess you meant "Yep" not "Nope".

I'm somewhat inclined to agree with you there.

I like to minimise comments as much as possible. Often they are redundant. Often they are wrong or become wrong when the code gets changed and the comments forgotten about.

I like to try and make the source comment itself as much as possible. Spend some time on finding meaningful variable and function names. Factor fiddly bits of code out into functions/methods with names that tell you what they do. And so on.

I do tend to comment heavily when doing something in a new language I'm learning. Only because hat code is ind of a self tutorial and I have to remind myself what the language features do all over the place. Of course they all become redundant when/if I become familiar with the language.

< anecdote>
Some years ago I was following along a nice tutorial on the Ada language by some CS prof from America. I came to an example code that did not make any sense to me no matter which way I looked at it. The prof had commented the example with something like:

We have to do this because of the absurd way Ada implements....

Eventually I realised what the code was supposed to do and how it should be done. It was not Ada that was absurd but the prof had not understood how tagged tyoes work in Ada.

I emailed the prof about this. I don't think it ever got fixed as he replied that there was not much call for that course any longer.
< /anecdote>

2 Likes

The line in question would be likely skimmed over in a code review if appearing in someone else's (the old me's) real code. I have an expectation they know what they are doing and can point out missing tests.

I fully agree in getting the interface right. Implementation can be good enough, since everyone has their own preference; stick to what matters in find and avoiding bugs.

Fix to give context and to isolate high bug risk code. Changing working code implementation into just the same (RiiR) needs justification. (That would go far too off-topic.) Multiple ways of doing the same thing can be detrimental; Which is what I expect the RFC will achieve. Now if depreciation also gets added it may not be so bad.

Well… if code doesn't handle certain extenuating circumstances well, then I usually know and remember when I became aware of these. If code doesn't handle something that code should handle… then it's not mine.

I forget minor things which don't affect design all that much. But these don't affect design thus don't mmake me suspect my own code. I rarely forget something really crazy. E.g. consider decoding of x86-64 instructions. I can imagine case where my code would forget to correctly handle rare difference between AMD and Intel. In fact I wrote such code many times before I knew about that obscure fact.

But I would be really surprised to see my own code which would handle that difference using virtual functions (or dyn in Rust) on every instruction decoding. Because it makes no sense to handle one single (and extremely rare) wart using something so heavy and something so bad for the “happy path”.

But what happens to these comments after that happened? Do you continue to copy-paste something like

    int[] buf = new int[size](); // Parens are important to make sure buf is zero-initialized.

Dozens of times? Sorry about C++ feature, I just don't remember similar Rust feature where someone asked me to add a comment about the feature of language not about something that lies outside of language.

Yeah that is another reason not to comment language features. If you understand them correctly then there are no need for comment because anyone (even you) can look them up in the documentation. If you use them incorrectly then your comment wouldn't help anyone anyway and would just make situation worse.

Only add comments about information which is hard to obtain! Like that difference between jumps in x86-64 mode: sure, it can be obtained if you read AMD manual carefully, then Intel manual carefully, then compare them… but that's a lot of work! Neither manual ever mention existence of the other possibility, neither manual says there's difference between AMD and Intel… that one definitely deserves a comment.

But it's not about something you did but about something you have to unconditionally accept. If you feel the need to write something like that about thing that's under your control… just go and fix the code and spare the headache for the future reader.

1 Like

Ha! I'd probably comment that line as:

int[] buf = new int[size](); // Yet another example of why I don't want to use C++ anymore.

I mean, it ensure initialisation to zeros but there is not a zero mentioned anywhere. It's a bizarre, obtuse, syntax, that I'd probably try to avoid.

In general I agree with everything you say about commenting. Especially after working for years on projects that a demanded comment for every line of code almost. Which lead to masses of redundant gibberish. You the classic examples:

// Increase velocity by 1
velocity = velocity + 1;

At that point you winder if anyone is thinking about what they are doing.

Moderator note: The C++ corner cases are fascinating, but off-topic, and also dangerously close to language bashing.

3 Likes

Re: ..T::default() vs ..Default::default(), I would like to mention ..default(), of #![feature(default_free_fn)] fame.

1 Like