Replies: 14 comments
-
The traditional way I've seen this dealt with is with two methods - a public kickoff method, and a private recursive method.
Does this really warrant simplification through a language change? |
Beta Was this translation helpful? Give feedback.
-
@yaakov-h and now that we have local functions it can be slightly better:
p.s. Just read the whole OP and noticed that the poster already posted it. :D |
Beta Was this translation helpful? Give feedback.
-
Just an idea, to solve the duplication problem it might be possible to come up with something like this:
The Would be equivalent to the following code:
|
Beta Was this translation helpful? Give feedback.
-
I like the proposed concept, despite the existence of workarounds. It's a much cleaner way to address a fairly common need. |
Beta Was this translation helpful? Give feedback.
-
Though the syntax would conflict with #804 (parameter properties). Here's an idea: public static IEnumerable<int> Fibonacci(int a, int b, int n, local List<int> list = null)
{ ... } |
Beta Was this translation helpful? Give feedback.
-
If we are into rewriting the example code, then expression-bodied members, for the win: public static IEnumerable<int> Fibonacci(int a, int b, int n) =>
FibonacciCore(a, b, n, new List<int>(new int[] { a, b }));
private static IEnumerable<int> FibonacciCore(int a, int b, int n, List<int> list) =>
list.AddAndReturn(b) is var newList && newList.Count < n
? FibonacciCore(b, a + b, n, newList)
: newList; 😆 However, I actually really like this proposal. I often write such public-private method pairs and using Of course, tail recursion optimisation would be nice too here 😉 |
Beta Was this translation helpful? Give feedback.
-
local functions can already achieve what you want and I think its clean enough. who said you cant use local variables inside enclosed local functions?
works perfectly fine. without need to redefine signature. |
Beta Was this translation helpful? Give feedback.
-
Hi guys, the OP here. For those of you who've suggested using local functions to solve this problem, did you see my workaround? From the responses I'm seeing, it seems to have divided opinions, though I concur with @bondsbw that Does it warrant a language change? - Well, I don't think there'd be any need to change the CLR; something like this could just be checked at compile time, thus it would essentially just be syntactic sugar. But that's not what you asked, right? Does it warrant a language change? - I don't know. I feel like this should be discussed extensively by the community, and decided by @MadsTorgersen and his team. |
Beta Was this translation helpful? Give feedback.
-
@MkazemAkhgary Didn't know you can do that, it actually works. |
Beta Was this translation helpful? Give feedback.
-
@MkazemAkhgary I think I find your workaround the most elegant of them. Perhaps this is enough. |
Beta Was this translation helpful? Give feedback.
-
I don't like this for the reason that it leaks implementation details into the signature of the method. There's no mechanism within the CLR through which this kind of parameter can be enforced and a compiler check is a weak defense at best. There are many compilers in the ecosystem which would all have to be modified to recognize and enforce the rule. Down-level versions of C# would blissfully ignore the constraint. The only way the compiler could provide any kind of airtight safety would be to silently emit another overload that doesn't accept the "private" members, but that could collide with other explicitly defined overloads. In my opinion local functions are a suitable workaround. The entire reason local function scope is hoisted is to enable recursive scenarios like this. |
Beta Was this translation helpful? Give feedback.
-
I assumed this wouldn't leak, but would effectively be rewritten into the local function equivalent. |
Beta Was this translation helpful? Give feedback.
-
I assumed so as well, but then you have the problem of overloads. |
Beta Was this translation helpful? Give feedback.
-
The workaround doesn't seem hacky to me. It seems like it exactly expresses the intent. There is the actual visible method that people can use. And there is hte internal method that can do what you want. Trying to merge them doesn't seem to buy much. Indeed, this is how i often do things with methods and local functions. The method exposes what i want, and local functions allow me to have a little internal space where i can do these sorts of machinations. I'm also skeptical of the problem as stated:
The local function is, by definition, only exposed locally to your method. It seems very overblown to have to protected that local function from your own method. Is there really that big a chance that you'll miscall this? It seems like for that to happen, you'd need a massively complex method to begin with. And, in that case, other refactorings would be more beneficial first before actually adding this language feature. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
@series0ne commented on Wed Nov 29 2017
Scenario
Consider the following method that implements the Fibonacci algorithm:
This allows me to pass Fibonacci arguments
a
andb
, an iteration countn
, and an optional argumentlist
to append Fibonacci values to (used explicitly within the method).Example
Problem
The method leaks an implementation detail (the list) and allows any populated list to be passed in, thus yielding invalid results:
Solution
A method parameter could allow
private
modification, provided that:default
argument.This would prevent leaking implementation details of the method to the outside, whilst allowing the parameter to be set internally; for example:
As illustrated from the example above, the
list
argument can be set explicitly from inside the method, however the following would raise a compilation error:Workaround
As of C# 7.0, it's possible to use a local method, however this just wraps the current method inside another method that does not expose the
list
parameter:I don't particularly like the workaround, because it requires duplicated, but different parameter names, and it just seems a bit...hacky.
@HaloFour commented on Wed Nov 29 2017
Language proposals belong on the CSharpLang repository.
@series0ne commented on Wed Nov 29 2017
@HaloFour can this be migrated?
Beta Was this translation helpful? Give feedback.
All reactions