Unused type parameter in swift - swift

Is there a keyword to place-hold unused type parameters?
In this example, receiver does not use T of MyGen.
In Java language, it can be written MyGen<?> v.
I could not find a counterpart in swift language documents.
import Foundation
class MyGen<T: Printable> {
var value: T
init(v: T) {
value = v
}
}
func receiver(v: MyGen<WHAT_COMES_HERE>) {
println(v);
}
let s = MyGen<NSString>(v: "hello")
receiver(s)
I know that giving receiver a type parameter solves the problem, but it is not welcome because upper bound Printable is repeated as many as functions and the code has redundant information.
// This works, but not welcome
func receiver<T: Printable>(v: MyGen<T>) {
println(v);
}

In Swift, despite it not being used, you have to declare a type parameters. But, you don't need :Printable in here, You can use just T or whatever as you like.
func receiver<A>(v: MyGen<A>) {
println(v)
}
Use : for the type parameter, only if receiver requires more specialized MyGet.T. For example:
class MyGen<T: Printable> {
var value: T
init(v: T) {
value = v
}
}
// `receiver` accepts `MyGen` only if its `T` is a sequence of `Int`
func receiver<A: SequenceType where A.Generator.Element == Int>(v: MyGen<A>) {
println(reduce(v.value, 0, +))
}
let s = MyGen<[Int]>(v: [1,2,3])
receiver(s) // -> 6

Related

Extension on Array where Element is generic not compiling [duplicate]

It is legal to say this (arr is an Array):
let arrenum = Array(arr.enumerated())
So why isn't it legal to say this?
extension Array {
func f() {
let arrenum = Array(self.enumerated())
// error: type of expression is ambiguous without more context
}
}
EDIT It seems this is a workaround:
extension Array {
func f() {
typealias Tup = (offset:Index, element:Element)
let arrenum = Array<Tup>(self.enumerated())
}
}
But why is that needed? (And is it right?)
This is a known bug (SR-1789). Swift currently has a feature where you can refer to a generic type within its own body without having to repeat its placeholder type(s) – the compiler will infer them for you to be the same as the type of self.
For example:
struct S<T> {
func foo(_ other: S) { // parameter inferred to be `S<T>`.
let x = S() // `x` inferred to be `S<T>`.
}
}
extension S {
func bar(_ other: S) {} // same in extensions too.
}
This is pretty convenient, but the bug you're running into is the fact that Swift will always make this inference, even if it's incorrect.
So, in your example:
extension Array {
func f() {
let arrenum = Array(self.enumerated())
// error: type of expression is ambiguous without more context
}
}
Swift interprets the code as let arrenum = Array<Element>(self.enumerated()), as you're in the body of Array<Element>. This is incorrect, because enumerated() yields a sequence of offset-element tuple pairs – Swift should have inferred Array to be Array<(offset: Int, element: Element)> instead.
One workaround, which you've already discovered, is to explicitly specify the placeholder type in order to prevent the compiler from making this incorrect inference.
extension Array {
func f() {
let arrenum = Array<(offset: Int, element: Element)>(self.enumerated())
}
}
Another possible workaround appears to be using the fully-qualified type, for example:
extension Array {
func f() {
let arrenum = Swift.Array(self.enumerated())
}
}
as it appears Swift doesn't do the same inference for fully-qualified types (I'm not sure if you should rely on this fact though).
Finally it's worth noting that instead of doing a call to Array's initialiser, you could use map(_:) instead to avoid the issue entirely:
extension Array {
func f() {
let arrenum = self.enumerated().map { $0 }
}
}
which, like the initialiser call, will give you back an array of offset-element pairs.

Extending custom type where associated type is equal to Void

I'm in a situation where I have a custom type that contains an associatedtype. In the case where this is equal to Void, I would like to have some default behaviour (to make the call-site more convenient). I tried to boil the example down to:
protocol FooType {
associatedtype T: Any
var bar: (String) -> T { get }
}
struct Foo<T>: FooType {
let bar: (String) -> T
}
extension Foo where T == Void { // Compile error: "Same-type requirement makes generic parameter 'T' non-generic".
init() {
self.bar = { _ in return }
}
}
The idea is that, in the cases where the generic type is Void, it doesn't make sense (in my scenario) to pass in a function (named bar in the example). Therefore, I just want a default implementation for this function in this specific context.
When trying to do the above I get the Same-type requirement makes generic parameter 'T' non-generic which sounds very similar to what happens when one tries to restrict e.g. the Array type when containing specific types. A workaround for this is to introduce a protocol, but I cannot do that for Void. Is it possible to do what I want or is this currently a limitation in Swift 3?
As of Swift 3.1, the code posted in the question now works. That is, the following now works as wanted:
protocol FooType {
associatedtype T: Any
var bar: (String) -> T { get }
}
struct Foo<T>: FooType {
let bar: (String) -> T
}
extension Foo where T == Void {
init() {
self.bar = { _ in return }
}
}
let foo = Foo<String>(bar: { (t: String) in return "" })
let zoo = Foo<Void>()

Default parameter as generic type

I have protocol and his implementation written in Swift:
protocol P {
}
struct A: P {
}
Protocol is used as generic type for some function:
func foo<T: P>(param: T) {
}
func foo() {
foo(param: A())
}
Until now everything works properly. But I would like to set A() as a default parameter of given function:
func foo<T: P>(param: T = A()) {
}
Unfortunately with following error:
Default argument value of type 'A' cannot be converted to type 'T'.
Or
func foo<T: P>(param: T = A() as P) {
}
,
let a: P = A()
func foo<T: P>(param: T = a) {
}
Returns:
Default argument value of type 'P' cannot be converted to type 'T'
Or
func foo<T: P>(param: T = A() as T) {
}
Returns:
'A' is not convertible to 'T'; did you mean to use 'as!' to force downcast?
What I'm doing wrong? Where is the problem?
I do not want to use force cast like this:
func foo<T: P>(param: T = A() as! T) {
}
Thank you in advance.
You're trying to enforce a non-generic default argument in a generic function: you should probably think over what you're trying to achieve here.
For the sake of the discussion, you could include an attempted cast of A() to T in your function signature, but you'd need to change the argument type to optional to allow failed conversion (nil), e.g.
func foo<T: P>(param: T? = (A() as? T)) { }
A more sound alternative is including - in addition to your generic function - a concrete non-generic function for instances where T is A (concrete functions will take precedence over generic ones), in which case you can include the default argument of A() in the function signature of the concrete function. E.g.
protocol P { }
struct A: P { }
extension Int: P { }
func foo<T: P>(param: T) { print("called generic foo") }
func foo(param: A = A()) { print("called A specific foo") }
foo() // called A specific foo (making use of default arg)
foo(A()) // called A specific foo
foo(1) // called generic foo
Note that the non-generic foo is called even though A conforms to P (A could've made use of the generic foo): there's no conflict here as the concrete function takes precedence.
If you, on the other hand, just want your generic function to allow calling without the single argument (i.e., making use of a default argument), you can include a blueprint of a simple initializer in P, allowing you to initialize an instance of the generic type as default argument; see #Sulthan:s answer.
The only thing you need is to add a requirement for an initializer to the protocol:
protocol P {
init()
}
struct A: P {
var x: Int
init() {
x = 10
}
}
func foo<T: P>(param param: T = T()) {
}
However, you will have another problem. The type of the passed parameter decides the type of the generic so you will have to specify the generic type somehow else.

Swift 2.0 Generics and Type Safety Issues

I was doing this tutorial http://blog.teamtreehouse.com/introduction-learn-power-swift-generics and I came upon this code;
func someFunction<T, U>(a: T, b: U) {}
The problem is when I call the function using
someFunction<String, Int>(1, "Test")
I get an error saying "cannot explicitly specialize a generic function".
I then change it to
someFunction(1,b: "Test")
and now there is no error. The problem is that there is now no type safety. (Is there something wrong with the code, as it was written before swift 2.0?) What is the best way to re-introduce type safety?
The declaration is completely generic and is specifying that any two types can be used.
func someFunction<T, U>(a: T, b: U) {}
It is not that there is no type safety in Swift, this is how you express a generic without any type constraints.
You get what you ask for.
If you wanted to constrain the function to String and Int, you would have written it as
func someFunction(a:String, b:Int)
Generics are more often used with collections, protocols and classes. Basic types rarely need them :
func someFunction<T:Comparable, U:Comparable>(a:T, b:U) -> Bool
{ return (a < b) || (a > b) }
ok, see this 'self explanatory' example. try it in playground and play with it a little bit.
func foo<T>(t: T)->T {
return t
}
// here the resulting type is infered by compiler
let i = foo(1) // 1
let j: Int = foo(1) // 1
let t = foo("alpha") // "alpha"
// if you declare it self ..
//let s: String = foo(1) // error: cannot convert value of type 'Int' to expected argument type 'String'
/* this fails to compile!
func bar<T>(t:T)->Int {
return t.count
}
*/
/* this fails to compile too !!
func bar0<T:CollectionType>(t:T)->Int {
return t.count
}
*/
func bar<T:CollectionType>(t:T)->T.Index.Distance {
return t.count
}
let arr = [1,2,3]
let k:Int = bar(arr) // 3
print(k.dynamicType) // Int
// and even more interesting
let l = bar(arr)
print(l.dynamicType) // Int

Swift - how to declare a method which receives a number in a range

I want to create a function which has a number parameter that should be between 0..100 %
I thought that the best way to enforce this would be by creating a wrapper type using FloatingPointType protocol , but I am getting a compilation error
Protocol 'FloatingPointType' can only be used as a generic constraint because it has Self or associated type requirements
struct Percent {
init(val : FloatingPointType) {
// enforce value is between 0..100
}
}
func hideView(percent : Percent) {
// percent is 0..100 at this point
.. do some work here
}
What would be the correct way to enforce this condition at compile time?
Update: As of Swift 5.1 this can more easily achieved with “property wrappers”, see for example “Implementing a value clamping property wrapper” on NSHipster.
The easiest way would be to define a type that holds a
Double (or Float or Int) in the required range:
struct P {
let val : Double
init (val : Double) {
// ...
}
}
But if you want to treat different floating point types then
you have to define a generic class
struct Percent<T : FloatingPointType> {
let val : T
init(val : T) {
self.val = val
}
}
To compare the values you need to require Equatable as well:
struct Percent<T : FloatingPointType where T: Equatable> {
let val : T
init(val : T) {
if val < T(0) {
self.val = T(0)
} else if val > T(100) {
self.val = T(100)
} else {
self.val = val
}
}
}
Example:
let p = Percent(val: 123.4)
println(p.val) // 100.0
Note that this requires that hideView() is generic as well:
func hideView<T>(percent : Percent<T>) {
// percent.val has the type `T` and is in the range
// T(0) ... T(100)
}
The language feature you are looking for is called Partial Functions. A partial function is a function that is not defined for all possible arguments of the specified type. For instance, they are available in Haskell or Scala - but they are not available in Swift.
So the best you can do is to check at runtime if the provided value lies within the valid range and act accordingly (e.g. raise an exception or return an error).
It sounds like you're trying to enforce, at compile time, that you can't pass a value outside the range 0.0 to 100.0 to a function. You can't do that.
What you can do is write your function to throw an exception if it is passed a value that's out of range, or display an error to the user and return if it's out of range.
Adding up to Martin's answer with updating for Swift 5:
struct Percentage<T: FloatingPoint> {
let value: T
init(value: T) {
self.value = min(max(value, T(0)), T(100))
}
}
Usage site, you can define the generic type like:
func updateCircleWith(percentage: Percentage<CGFloat>) {
// percentage.value will be between 0 and 100 here
// of course the CGFloat(0) and CGFloat(100)
}