For example:
func f(n:Int) -> (errorValue:Int) {
...
}
print(f(5).errorValue)
For example:
func f(n:Int) -> (errorValue:Int) {
...
}
print(f(5).errorValue)
Although I agree that 1-tuples should support external and internal parameter names, your example is not a case for them. Your function should throw, instead.
(I'm not sure but I think I read somewhere that the ability to name 1-tuples was removed because some people got confused or something ...)
I too agree that 1-tuples should support external and internal parameter names, and as previously discussed in an earlier thread, I wish the "tuple-concept" as a whole was more consistent and uniformly reused/incorporated throughout the language (eg argument lists, pattern matching, etc). This would (AFAICS) result in fewer and simpler rules that are applicable to a lot of different parts of the language, making it more expressive while being less complicated.
In its current state, the "reusable tuple-concept" feels like something that is half baked (with a lot of these strange exceptions) and it sets up expectations that are sometimes met, and sometimes not.
Just because there's no such thing in Swift! 1-tuple does exists. (Int) is only Int, there no diference!
There was some support in the first betas, but never became part of the language.
This just add boilerplates into the language!
var a:(Int) = 2
var b:Int = 2
var c = a * b // Should this be allowed? The tuple should be automatically unwrapped?.A lot of discussion was made last year, and the conclusion of the Swift team is: Tuples should be formed by two or more elements. A parenthesis around any elements is just a parenthesis.
Yes, that "unwrapping" is what Jens and I are saying should happen.
Swift has no conclusions, only decisions. Unlike other languages, we get migrators instead of having to live with bad decisions forever. This particular decision is wrong, and it will be overturned as people learn that what we want is better. 🙂
Here's just one of the bugs that are probably due to all the current (Xcode 7.1 beta 3) tuple related inconsistencies / non-uniformities:
enum Foo {
case Bar(isNice: Bool, number: Int)
case Baz(number: Int)
}
let barArgs = (isNice: true, number: 1234) // Compiles
let bazArgs = (number: 1234) // Compiles
let a = Foo.Bar(barArgs) // Compiles
let b = Foo.Baz(bazArgs) // Error: Missing argument label 'number:' in callNote that those associated values look an awful lot like tuples (as does many other things in Swift), so user's will expect them to follow the simple rules of the powerful "tuple concept" in Swift. But in reality there's no such concept or rules. Or that concept is diffuse rather than powerful, and those rules are full of exceptions and special cases.
IMHO: What could have been an easy to learn, powerful and elegant system/concept, is currently a fragmented/broken mess that is hard to understand, learn, explain and motivate.
protocol Protocol {
typealias ParameterList
// What's the point of even requiring an internal parameter name here?
// It isn't enforced.
static func function1(lie: ParameterList)
static func function2(lie: ParameterList)
static func function3(lie: ParameterList)
}
extension Protocol where Self.ParameterList == Int {
static func function3(_: ParameterList) {}
}
struct A: Protocol {
typealias ParameterList = Int
// This all compiles, but I can't enforce the parameter naming,
// via the typealias, like I want.
static func function1(one: ParameterList) {}
static func function2(two: ParameterList) {}
}
struct B: Protocol {
typealias ParameterList = (name: String, number: Int)
// Compiles! But I don't have access to name or number.
// I have to name the parameter, gimping some of the potential power of typealiases.
static func function1(_: ParameterList) {}
// Yeah, Xcode should tip me to use (ParameterList),
// but this should still count towards Protocol. It doesn't.
static func function2(name: String, number: Int) {}
// This is not considered the same as the above.
// The ability to have both is useless.
static func function2(_: ParameterList) {}
static func function3(_: ParameterList) {}
}
// I used the typealias to avoid repeating parameters,
// and to make Protocol work across more types,
// not because I love parentheses!
B.function1((name: "", number: 3))
Yes, that's ... inconsistent, I've filed radars on some of those. I guess you've also discovered that the extra parenthesis are not required if B and A had instead been built using a generic struct with ParameterList = T, as long as the type argument is not given in the form of a typealias (don't ask me why).
The following shows what I mean, I'm using the initializer here, but I'm pretty sure it holds for static and normal methods too. Note also that it works no matter what parameter names are given in the calls (except for the last line which is considered an error as if just to make sure there's an inconsistency within the inconsistency):
protocol Fooable {
typealias Value
init(_: Value)
}
struct Foo<T> : Fooable {
let v: T
init(_ v: T) { self.v = v; print(T.self) }
}
let b = Foo(1, "two", 3.0) // OK, prints (Int, String, Double))
let c = Foo(1, "two") // OK, prints (Int, string)
let d = Foo(1) // OK, prints Int
let e = Foo(x: 1, y: 2, z: 3) // OK, prints (Int, Int, Int)
let f = Foo(x: 1, y: 2) // OK, prints (Int, Int)
let g = Foo(x: 1) // Error: Extraneous argument label 'x:' in callAnd look at this:
struct Foo<T> {
init(_ v: T) { print(T.self) }
}
typealias Foo1 = Foo< (number: Int, name: String) >
typealias ParamList = (number: Int, name: String)
typealias Foo2 = Foo<ParamList>
let a = Foo1(number: 1, name: "bla") // OK
let b = Foo2((number: 1, name: "bla")) // Must have one (or more) extra parens, else error.
print(Foo1.self == Foo2.self) // Prints true, so they are the same type! Yet they can't be initialized the same way :P