3 ms·
It's the same thing. It's a type with only a single value.
by jimktrains2 10y ago
It's the same thing. It's a type with only a single value.
- virtualwhys 10y agoIt's not the same thing, a value of type Unit can only produce a side effect (or do nothing at all).
- dllthomas 10y agoHow is that different from a value of type "empty tuple"?
- virtualwhys 10y agoTrue, neither are useful as values, though Unit typically conveys programmer intent (to produce a side effect), whereas the empty tuple is, in Scala at any rate, quite rare. The empty tuple: scala> val empty = Tuple1(()) empty: (Unit,) = ((),) vs. Unit: scala> val empty = () empty: Unit = ()
- vertex-four 10y agoIsn't that a tuple containing a unit, and therefore not empty?
- virtualwhys 10y agoIt's the closest you can get in Scala to represent an empty value whose type is `Tuple`.
- Sharlin 10y agoType names are irrelevant here. Unit could be called "Tuple0", or be defined as a synonym of a type named such. The semantics are identical.
- vertex-four 10y agoThe difference between an empty tuple (also known as unit) and void becomes obvious when you deal with vaguely complex trait impls. For example, if you have a trait: trait Foo { type ErrorType; fn bar() -> Result<u8, Foo::ErrorType>; } How would you specify that your type implements Foo in such a way that bar() cannot return an error? If you were to implement it using the empty tuple (unit), like this, it could actually return an error: struct Abc{} impl Foo for Abc { type ErrorType = (); fn bar() -> Result<u8, ()> { Err(()) // oops, we don't want to be able to do that! } } Instead, you can use Void here: enum Void{} struct Xyz{} impl Foo for Xyz { type ErrorType = Void; fn bar() -> Result<u8, Void> { // No way to create a Void, so the only thing we can return is an Ok Ok(1) } } Aside from the obvious power to express intent (can we return an error without any information attached, or can we not error at all?), this would allow an optimizing compiler to assume that the result of Xyz::bar() is always a u8, allowing it to strip off the overhead of the Result: fn baz<F: Foo>(f: F) { match f.bar() { Ok(v) => println!("{}", v), Err(e) => panic!("{}", e) }; } ... baz(Xyz); // The compiler can notice that f.bar() can never return a Result::Err, so strip off the match and assume it's a Result::Ok A super-smart compiler would even make sure it's not storing the data for "is this an Ok or Err" in the Result<u8, Void> at all. Finally, similarly, you can specify that certain functions are uncallable by having them take Void as a parameter.
- dllthomas 10y agoI don't think anyone is claiming Void in Scala/Haskell/Rust is equivalent to Unit in Scala/Haskell/Rust. The question here was Unit vs empty tuple. Up-thread was the question of whether C "void" is more like S/H/R Unit or S/H/R Void.
- vertex-four 10y agoUpthread was: > If Rust follows Scala then `()` is not the empty tuple, but rather Unit (void in C*). The implication is that () == Unit == void. The empty tuple and unit are essentially equivalent aside from name, void is something else.
- theseoafs 10y ago`void` in C does not have a value. You can't make a variable and put a void in it because there is no such object as "void".
- jimktrains2 10y agoYes, and () isn't void; the poster above me is wrong. Void is...the absence of a type? It's awkward. However, () and Unit are.
- Ericson2314 10y agoThat is an artificial restriction if C. Also see how ! In Rust is also loosing it's artificial restrictions.
- lomnakkus 10y agoIndeed, and there has been some talk of removing this restriction in C++ because it makes certain kinds of metaprogramming a lot more cumbersome than they should be.