Discussion: Better support for "Unit" #1604
Replies: 169 comments 1 reply
-
This discussion of how to implement |
Beta Was this translation helpful? Give feedback.
-
What about delegate/method group conversions? There wouldn't be conversions between |
Beta Was this translation helpful? Give feedback.
-
@Neme12 I hope not because those conversions would be expensive and there's an easy workaround: |
Beta Was this translation helpful? Give feedback.
-
@Neme12, @masonwheeler, |
Beta Was this translation helpful? Give feedback.
-
@Neme12 There will not, just like there's no conversion between |
Beta Was this translation helpful? Give feedback.
-
What about this discussion makes the language less useful? What semantic information is being removed?
What would make it any different to creating a delegate to the method group Action<string> a = () => Console.WriteLine;
Func<string, unit> f = a.Invoke; |
Beta Was this translation helpful? Give feedback.
-
The idea being that the compiler would emit that easy workaround: Action<string> a = () => Console.WriteLine;
Func<string, unit> f = a.Invoke;
// equivalent to:
Func<string, unit> f = () => {
a.Invoke();
return default;
}; Yes, you incur the cost of two delegate invocations, but that's no different than: Predicate<Person> p = person => person.IsAlive;
Func<Person, bool> f = p.Invoke; |
Beta Was this translation helpful? Give feedback.
-
The details are different but Kotlin has a similar thing. |
Beta Was this translation helpful? Give feedback.
-
Yes. But this also makes me want this feature less. There would be an implicit conversion in some places (giving the impression that
But |
Beta Was this translation helpful? Give feedback.
-
@HaloFour I'm happy with |
Beta Was this translation helpful? Give feedback.
-
You just answered your own question there. The distinction between statements and expressions, and also also the distinction between methods that return a value and methods that don't, is valuable and important. Let's not go blurring it please! |
Beta Was this translation helpful? Give feedback.
-
@masonwheeler Sounds a lot like the hallowed distinction between classes and interfaces, if you ask me. 😇 |
Beta Was this translation helpful? Give feedback.
-
@HaloFour In other words, to answer @Neme12, I don't want there to be implicit conversions from one delegate instance to another at the language level, since they invisibly opt you into using compiler-generated stubs and you lose reference equality. But once you opt in by explicitly creating a new delegate instance, such as binding to |
Beta Was this translation helpful? Give feedback.
-
What I'd really like is for However, what @HaloFour is proposing avoids that. |
Beta Was this translation helpful? Give feedback.
-
I'm not seeing the value in either. The language forcing you to use two sets of constructs based on whether or not a method returns a value is not a value to me. It's a hindrance which requires code duplication and bridging that adds no semantic value to your program. I completely agree. I'd treat it the same way as delegate conversion between delegates with matching signatures, which C# doesn't allow today due to the argument of the overhead. If that were to change I'd probably back implicit conversion as the overhead comes from the duplicate delegate invocation, not from pushing |
Beta Was this translation helpful? Give feedback.
-
Note: an example of where we did CLR work and where i think it really helped prevent problems is with 'nullable' (for value types). For example, i think it would have been pretty awful if boxing a To me, i would want the same for what i see as hte input/output stream of values. I want that to be a first class concept (which i think would almost certainly require CLR support). But that means that you'd need to do things like unify the concept of 'parameter lists' and 'tuples' and whatnot. And right now, we've already shipped tuples. The CLR is completely oblivious to them. And trying to change that would almost certainly be breaking. So just accept that the (currrent) CLR world just has no consistent view of these guys, adn i accept that that's likely to not change. It's ugly. It's unfortunate. And i truly hope a new restart would address this. |
Beta Was this translation helpful? Give feedback.
-
I'm undecided. It'd be neat to be able to pass nothing, but that seems like it could get really messy really quick, especially if Similarly, when working with There's a lot of questions here and a lot of things that the language could probably do. |
Beta Was this translation helpful? Give feedback.
-
In Kotlin, you will have to provide a value; otherwise, the compiler will throw an error. It seems like people expect more from the type than what it really represents, just my opinion about it. |
Beta Was this translation helpful? Give feedback.
-
Yes, the C# compiler would have to call the first overload. But there's nothing stopping the C# compiler from calling |
Beta Was this translation helpful? Give feedback.
-
I'd really love to be able to squash argument lists and have them treated as equal. This whole area of delegate compatibility is a mess. ( Would It's not that I don't want nice features, but I want them to work without headaches. I don't see how this singleton The reason why I'm advocating "proper" (CLR-based) And, while I've always wanted to write |
Beta Was this translation helpful? Give feedback.
-
I agree it would be cool if we had that. But may I ask what's the drawback as we do not have that. I have used the splat/unpack operator, e.g. in Python |
Beta Was this translation helpful? Give feedback.
-
This is important to consider that, with any mechanism or implementation detail aside, do we really need I may support changing CLR to accept To be clarified, I would support the effort to trying to disguise |
Beta Was this translation helpful? Give feedback.
-
C# is morphing from a rather well designed imperative OO language into a bastardized language that is copying more and more ideas from the functional world, in particular from F#. Looking over the LDT meeting minutes recently it is clear that there is a heavy bias toward functional programming features. Functional programming languages are superb and I use F# when I can at my own place of work, however the trend to morph C# into a mutation of F# must be questioned. It can also hardly help in the adoption of F# when C# is increasingly positioning itself as an alternative. Microsoft offer F# already so why strive to adapt C# to look more and more like a functional language? As I've said elsewhere dwelling on esoteric functional mechanisms while flatly rejecting rudimentary and pretty obvious enhancements (e.g. break with labels in loops) seems to amount to a program of completely transforming the language, this is silly when - if we truly desire functional concepts - we can simply begin to leverage F#. C# developers (or rather OO developers) do not design or write functional code, the C# language itself is not a functional language nor is it wise to try and make it into one especially when Microsoft already provide one! |
Beta Was this translation helpful? Give feedback.
-
F# is functional and immutable first, with object-oriented and imperative features added on top. C# is object-oriented and imperative first, with functional and immutable features added on top. Personally, I like the latter approach, which is why C# is my primary language and why I also like that functional features are being added to C#.
The basis of C# is and always will be an imperative and object oriented. But most importantly, C# is pragmatic. If a functional feature, like lambdas or pattern matching, will improve the language, it will be added to it. Also, I don't understand how "a feature I like won't be added to the language" means the language is transforming. |
Beta Was this translation helpful? Give feedback.
-
@Korporal, there is no one true programming paradigm. There are benefits to exposing many different paradigms in order to best support whatever makes your code easier to read/write. F# is a functional first language, but it is by no means a functional only language (I can use OO patterns when and where required). C# is likewise not only a imperative OO language (even if those are generally agreed to be its "primary" paradigms). It exposes many different paradigms to help you write your code. Sometimes "functional" features let you have clear cut benefits (purity and immutability allow certain optimizations that you could not otherwise guarantee were possible). Likewise, in some cases, "functional" features can hurt you (I don't want to have to write a monad to have a functional UI stack). |
Beta Was this translation helpful? Give feedback.
-
C++ also has lambdas and "unit" ( C++ doesn't have labelled loops, though. |
Beta Was this translation helpful? Give feedback.
-
If I have a custom type with an implicit conversion from action =>
{
if (action is AsyncThunk thunk)
{
thunk.Invoke(store.GetState, store.Dispatch); // No return on the following line
}
else
{
return next.Invoke(action);
}
} |
Beta Was this translation helpful? Give feedback.
-
(+1) for having built-in There are multiple great libraries like LanguageExt by @louthy (he commented above) or Reactive Extensions that already define their own Obviously there is a demand and I'm sure many people regularly creating generic code or using expressions (LINQ, fluent APIs etc.) will value it a lot. |
Beta Was this translation helpful? Give feedback.
-
... and MediatR has its own Unit type too. To avoid confusion (and "unify" them), I can't name my type Should I name it In the end, I'm just a normal library user and I can see there is a need of a |
Beta Was this translation helpful? Give feedback.
-
There is definitely an argument to be made in favour of This could enable writing switch expressions where inferred return type is _ = value switch // removing the requirement for _ = becomes very easy
{
1 => Console.WriteLine("one"),
>= 2 and < 10 => Logger.Info("two"),
_ => Debug.Print("other")
}; |
Beta Was this translation helpful? Give feedback.
-
There have been numerous proposals looking to add first-class support for a
unit
type to the language. I'd like to explore the different individual ways that the language could do this without CLR modification.This is an open discussion and I invite comments and suggestions. I'll get the ball rolling with some of the ideas I've seen in comments buried in other proposals.
Create a
unit
aliasThe family of types called
System.ValueTuple<...>
were added to the .NET 4.7 framework to support tuple literals in the C# language. There exists a version with 0 elements,System.ValueTuple
. It primarily contains static factory methods for creating instances of the other tuple structs, but it is astruct
in its own right and can be created. It is an effectively empty struct with no public fields and is suitable for representingunit
.The name, however, could leave a little to be desired. I'll continue to use
System.ValueTuple
for examples here but I'd leave that point open to discussion.Support
()
literal to meanunit
The syntax
()
could be shorthand to representdefault(unit)
:Implicit conversion from
void
tounit
The compiler could support conversion from
void
tounit
by emitting IL necessary to pushdefault(unit)
onto the stack:Assignments:
Lambdas:
Beta Was this translation helpful? Give feedback.
All reactions