Replies: 25 comments
-
Nope. I'd rather miss rust macros,
Looking at the definition, it runs a pattern-match on the actual tokens and produce a data structure. Oh and it doesn't stop there. There is a macro which accepts C++ code so you can embed C++ directly in a Rust program,
mind = blown. |
Beta Was this translation helpful? Give feedback.
-
In my opinion, returning from a method is an important action that should be visible in the method you're returning from. This proposal would hide that. |
Beta Was this translation helpful? Give feedback.
-
Yes it hides the return code, but this would be a developer I would opt for code clarity first. This way we can refactor a lot of checks done at the beginning of a method void T Foo(T arg1, T arg2, T arg3){
if (!boolFuncCheck(arg1))
return something
if (!boolFuncCheck(arg2))
return something
if (!boolFuncCheck(arg3))
return something
//other stuff
} that have nothing in common with core function logic and void T Foo(T arg1, T arg2, T arg3){
checkArg(arg1);
checkArg(arg2);
checkArg(arg3);
} Its clear in this code that we are sanitizing the input at the beginning, And Visual Studio will refactor a block of code with a return inside :) |
Beta Was this translation helpful? Give feedback.
-
Hiding control statements from the developer would be the antithesis of clarity. In your example exactly what would this "macro" return? What is the "invalid" value of |
Beta Was this translation helpful? Give feedback.
-
I oversimplified the example, it can be 100% more clear. Its like convention over configuration. If you stand with a pattern that And if you also have a pattern for return codes on invalid arguments you cant be more The same happens when checking return codes for functions |
Beta Was this translation helpful? Give feedback.
-
if your function is small enough and meets requirements for being inlined, jitter will do so, no worries there. ok apart from stack overhead which can be automatically solved, what else macro provides that other local functions or methods cant provide? |
Beta Was this translation helpful? Give feedback.
-
do you mean separating validation code from method? I don't think that's a good practice because then your code will be chopped into pieces and you have to follow and look for every macro you wrote and see whats going on there. if you do your self a favor, you would write validation code within the method and you would save your some time instead of trying to figure out whats going on. a good code formation is good practice. for example. (notice the blank lines. they help to distinguish between each part of method.)
|
Beta Was this translation helpful? Give feedback.
-
@MkazemAkhgary a bit OT but I hate uncessary blank lines in code files. Everyone seems to have blank lines everywhere though. |
Beta Was this translation helpful? Give feedback.
-
@stuartstein777 they are not
They help future readers to intuitively understand what parts of the code belong together, and they help your brain orientate inside the code, by making the code blocks more distinguishable. Good code uses blank lines, not all over the place, but to logically group code, at least in my opinion. |
Beta Was this translation helpful? Give feedback.
-
Agreed, they can help break code into "paragraphs of related logic". For example, I'll generally put a blank line after I've validated the method arguments but before I start doing anything else. |
Beta Was this translation helpful? Give feedback.
-
Blank lines in code serve the exact same purpose as the blank lines you use to separate paragraphs in prose. |
Beta Was this translation helpful? Give feedback.
-
You can return from the caller by throwing an exception which you would then catch where you want to "return" to. Using this as part of your normal control flow is bad practice, which means that a syntactic sugar for it would be a bad feature. |
Beta Was this translation helpful? Give feedback.
-
Using goto statements as part of your normal control flow is bad practice, which means that a syntactic sugar for it would be a bad feature. We should therefore remove Seriously, I agree that syntactic sugar for control-flow implemented using exceptions would be a bad idea in any language built atop the CLR. That's because exception handling has very poor performance on the CLR, and it would result in a language feature with horrendous performance. There are other platforms where throwing and catching an exception is extremely efficient (e.g. the Java virtual machine). On such platforms using exceptions to implement some well-structured language constructs is not a bad idea at all. |
Beta Was this translation helpful? Give feedback.
-
@gafter It's bad practice regardless of the performance, was my point. Exceptions are designed for error handling, not control flow. |
Beta Was this translation helpful? Give feedback.
-
press
Ok, I'm not sure how is this macro function related to throwing or catching an exception? macro function is simply a code snippet that gets inlined exactly where it was placed. |
Beta Was this translation helpful? Give feedback.
-
Runtime features do not have to be used for exactly what they "were designed for". Otherwise there are many things that we could never do (e.g. see #110, which "abuses" what virtual methods "were designed for"). Language designers can use runtime features in any way that is suitable to implement a language feature. Exceptions in the runtime can be used for anything you want, no matter what they were "designed for". But a language feature that translates to exception handling has to have an appropriate performance profile. That would be a problem on the CLR, which is why we don't do it. We may invest in improving that aspect of CLR performance some day, after which we might consider language features that translate to exception handling. |
Beta Was this translation helpful? Give feedback.
-
@MkazemAkhgary the person who posted this proposal said that the only difference in behavior would be that you can return from the caller. I was pointing out that you can already get that behavior but it's not a good practice. |
Beta Was this translation helpful? Give feedback.
-
Out of curiosity, is this poor performance limited to |
Beta Was this translation helpful? Give feedback.
-
Throwing an object of any type is an expensive operation. Simply adding a try/catch/finally block to your code may also affect performance (even if no exceptions are never thrown) depending on how capable the JIT compiler is (and there's a good chance that it's not very capable, navigating around various complications exception handling poses isn't trivial).
Really? Even if it does that it would be a boxed
Really? As far as I can tell from a quick experiment that is not the case. Well, maybe they're faster than in .NET but they're still terrible slow. |
Beta Was this translation helpful? Give feedback.
-
@mikedn Creating an exception object in Java in a way that captures a stack trace is slow. I suggest you retry your timing experiment with a preallocated exception. |
Beta Was this translation helpful? Give feedback.
-
@mikedn Expanding on what @gafter said, there is a key difference between the way exceptions in the JVM and CLR work. In both cases, the slowest feature of exception handling is the process of capturing a stack trace. The difference is when this occurs:
In most cases, the CLR and JVM behave equivalently for this aspect. Since exception stacks at the point where an exception is thrown are the most valuable, it's rare and often considered bad practice in Java for code to separate the exception construction from the point of throwing. I have not compared the impacts of exception filters, or the exception filtering implementation, on the overall performance of exception handling in the CLR. Remember that while this is a new feature for the C# language, it's been a part of the CLR for a long time. |
Beta Was this translation helpful? Give feedback.
-
Indeed, that makes a big difference. And so I get to learn some Java implementation details 😄
It turns out that there is more to it than that. At least in the example I put together, the JIT (or maybe the java compiler) transformed all the exception cruft into normal flow control: final static UnsupportedOperationException uex = new UnsupportedOperationException();
static void iseven(long i) {
if ((i & 1) == 0)
throw uex;
}
static int test() {
int s = 0;
for (long i = 1; i < 100000000L; i++) {
try {
iseven(i);
} catch (UnsupportedOperationException ex) {
s++;
}
}
return s;
} Now I wonder what would happen if |
Beta Was this translation helpful? Give feedback.
-
Isn't there still quite a bit of overhead in simply including |
Beta Was this translation helpful? Give feedback.
-
@HaloFour negligible |
Beta Was this translation helpful? Give feedback.
-
The problem being solved here is you missing C++ macros? 😂 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I miss c++ macros :)
A partial solution for this would be to have a Macro Function.
The only different behavior from a normal function should be that the
return statement of this function must execute the return of the caller.
So this way we have full type safety but also have control of the callers
behavior.
Example
Beta Was this translation helpful? Give feedback.
All reactions