Closed Araq closed 3 years ago
noSideEffect instead of noSideffect
noSideEffect instead of noSideffect
Well, you can write it any way you want, for example n_O_s_I_d_E_e_F_f_E_c_T
, who doesn't love case insensitivity :)
Can it be like an overload to the push
?, the same but instead of cast
use push
,
improve it to take arguments, and you dont need to add new syntax, docs, etc to the language.
@juancarlospaco well, push itself is not unsafe, but usage of pragmas for code blocks is unsafe, because you lie to the compiler about the code effects. So with cast
you'll be easily able to search for unsafe features used in code bases
Well, you can write it any way you want, for example n_O_s_I_d_E_e_F_f_E_c_T , who doesn't love case insensitivity :)
I believe the point is that noSideEffect
has three e
s.
Can we have a way to deprecate or test that these (and other) cast
calls are gratuitous or do I have to manually alter the code and re-run the compiler to check?
Well, you can write it any way you want, for example n_O_s_I_d_E_e_F_f_E_c_T , who doesn't love case insensitivity :)
I know you're joking but that has little to do with case insensitivity, all that case sensitivity does is that it enforces you to be consistent in your n_O_s_I_d_E_e_F_f_E_c_T spelling. This is valid code in C/C++/Java/C#/etc:
int n_O_s_I_d_E_e_F_f_E_c_T = 0;
if (n_O_s_I_d_E_e_F_f_E_c_T != 0) { ... }
In fact, sensitivity allows for much more cowboy coding styles:
int n_O_s_I_d_E_e_F_f_E_c_T = 0;
float n_O_s_I_d_E_e_f_F_E_c_T = 0.0;
if (n_O_s_I_d_E_e_F_f_E_c_T != 0) { ... }
Here are my thoughts even though it might be too late now already:
Very good idea in general. I'm just not sure about the word cast
. It is so strongly connected to "type casting" that I even misread the RFC upon first skimming, and I find it awkward to explain what the pragma does using the word "cast". Some alternatives:
{.override(noSideEffect).}:
This would be the natural choice, because in natural language the pragma is best explained as overrides the compiler's side effect analysis. However override
also has many connotations and people may e.g. use it as a custom pragma for inheritance.{.enforce(noSideEffect).}:
Possible, but could be misunderstood, because within the block "noSideEffect" is exactly not enforced -- it is only enforced to the outside.{.pretend(noSideEffect).}:
I like that a lot. "Pretending" expresses the unsafe aspect, should be a rather rare identifier, and thus, cannot be confused with much. In terms of grepping this would allow to grep for unsafe type cast
s and unsafe pretend
s in isolation.@bluenote10 We considered these alternative names but in the end cast
did win because it's already known to be unsafe and also because technically the block is casted to a proc with the given properties.
cast did win because it's already known to be unsafe
Depending on the developer's background, a "cast" is much less unsafe compared to an effect system override. For a Rust developer, a cast is as innocent as 16 as i8
, and nothing like unsafe
.
also because technically the block is casted to a proc
I don't think naming should focus on technical internals, but express what is relevant from a user perspective.
I can relate to the confusion that came up in https://github.com/nim-lang/RFCs/issues/302. In this case: {.pretend(tags: not Dangerous).}
would result in a sentence that makes intuitive sense in plain English, whereas {.cast(tags: not Dangerous).}
simply confuses me.
I think it is because the "cast" has no association to the "block" it is operating on. We would have to read it as "cast the block so that the visible tags are not dangerous". But one confuses the object with the predicate: "cast the tags to not dangerous ...", however it isn't the tags that get cast, it's the block. With the "pretend" variant this association problem doesn't arise: "pretend the tags are not dangerous in the following block".
The "technical details" are more objective than opinions about what is "confusing". When I started programming the "for" keyword was super confusing. Everything is confusing for somebody, it's not an interesting statement.
This is a proposal to add
{.cast(noSideEffect).}:
to Nim and to deprecate the existing{.noSideEffect.}:
block syntax.Rationale
Easier to grep for unsafe language constructs, allows for extensibility, enables a better
async
macro.Details
I propose to support all of the following:
{.cast(noSideEffect).}:
{.cast(gcsafe).}:
{.cast(raises: [E1, E2, ...]).}:
{.cast(tags: [Tag1, Tag2, ...]).}:
In combination with the new
getRaisesList
this should allow Nim'sasync
macro to become precise about the effects an async proc can produce.