Element vs. Generic Type <T> - swift

I wonder why Swift uses Element rather than Generic <T> in the following example.
What is the difference between Element vs T

From Generics:
Type Parameters
Type parameters specify and name a placeholder type, and are written immediately after the function’s name, between a pair of matching angle brackets (such as <T>).
Naming Type Parameters
In most cases, type parameters have descriptive names, such as Key and Value in Dictionary<Key, Value> and Element in Array<Element>, which tells the reader about the relationship between the type parameter and the generic type or function it’s used in. However, when there isn’t a meaningful relationship between them, it’s traditional to name them using single letters such as T, U, and V, such as T in the swapTwoValues(_:_:) function above.
So
func createArray<Element>(element: Element) -> [Element] { ... }
func createArray<T>(element: T) -> [T] { ... }
func createArray<Rumpelstilzchen>(element: Rumpelstilzchen) -> [Rumpelstilzchen] { ... }
are identical functions. Here the placeholder type is the element type of the returned array, therefore Element is a suitable “descriptive name.”
But it makes no difference otherwise, is it up to you to choose a name for the placeholder, balancing between readability and conciseness.

T is not particularly traditional. In FP, Backus uses T, but ML, from around the same time, uses a. Haskell uses a, Scala uses A. There's a mix of choices.
Swift, however, has strong reasons to use descriptive names. First, it's a quite descriptive language. Types are named with fully spelled-out words. Methods typically are literate in construction. Variables and properties are rarely abbreviated. There's no reason that type parameters should be uniquely obscure.
It also matches well with associated types which are quite naturally verbose. What would you call Collection's index type besides Index? Why should its "element" type be specially abbreviated? And if Array implements Collection, why should it create a distinct name (T) that it would then have to associate with Collection's Element? Why would you special-case all this just to make the type name unintuitive?
The deeper question would be, why wouldn't Array's element be called Element?

Related

What is the relationship of TypeMirrors and Elements in the lang model?

(While this question is tagged with annotation-processing I'm actually asking questions about the type model exposed by javax.lang.model whether or not annotation processing is involved.)
In javax.lang.model, there are two fundamental constructs: Elements and TypeMirrors.
Every Element is backed by a TypeMirror. However only certain TypeMirror subtypes, namely DeclaredType and TypeVariable, have Elements associated with them via DeclaredType#asElement() and TypeVariable#asElement() respectively.
(It follows that all Elements "have" TypeMirrors, but not all TypeMirrors "have" Elements.)
Speaking loosely and intuitively, this makes sense: you declare types by chanting certain Java spells: the spells themselves are the (declared) elements; the things they bring into being are the types that back them. I've programmed in Java for decades and have a good working familiarity with oddities like Foo implements Comparable<Foo>. I'm trying to get more rigorous here.
With all that in mind, and considering the following snippet, how are the javax.lang.model types and elements manifested?
// (Defined by the JDK itself of course.)
public interface Comparable<T> ...
// (My class.)
public class Frob implements Comparable<Frob> ...
I see the following "things", working from "top" to "bottom" with less and less certainty as I go along:
a TypeParameterElement whose affiliated Name is equal to "T"
The return value of its asType() method will be a (definitionally nameless) TypeVariable whose asElement() method will return the TypeParameterElement currently being discussed.
The return value of its getGenericElement() method (and its getEnclosingElement() method) will be the Element we'll talk about next ("Comparable").
a TypeElement whose affiliated Name is equal to "Comparable"
The return value of its asType() method will be a (definitionally nameless) DeclaredType whose asElement() method will return the TypeElement currently being discussed
The DeclaredType so returned will have exactly one type argument which will be the (definitionally nameless) TypeVariable discussed above whose asElement() method will return the TypeParameterElement discussed above ("T")
The return value of its getTypeParameters() method will consist solely of the TypeParameterElement discussed earlier.
a TypeElement whose affiliated Name is equal to "Frob".
(This TypeElement is brought into being with the Java syntax public class Frob ....)
The return value of its asType() method will be a (definitionally nameless) DeclaredType whose asElement() method will return the TypeElement currently being discussed.
The return value of its getInterfaces() method will be discussed in a moment.
an Element of some variety loosely described by "Comparable<Frob>".
I say "of some variety" because as written it itself does not have, say, an explicit or implicit extends or implements clause, or other markers I would expect to see of, say, a TypeElement. Nevertheless I'm not sure that it could be any other kind of Element other than a TypeElement. Maybe it is a TypeElement equal to that denoted by "Comparable<T>", but with its various TypeMirror-returning or -referencing methods using the type denoted by Frob?
The return value of its asType() method will be a (definitionally nameless) TypeMirror of some variety (almost certainly a DeclaredType) whose asElement() method will return the Element currently being discussed (this corresponds somewhat to java.lang.reflect.ParameterizedType in the runtime/reflection model)
The TypeMirror so returned will have exactly one type argument which will be the (definitionally nameless) DeclaredType returned by the asType() method of the TypeElement whose Name is equal to "Frob" described above
The TypeMirror so returned will be the sole member of the return value of the getInterfaces() method when invoked on the TypeElement whose Name is equal to "Frob" described above
Do I have this right as far as it goes?
Your question seems well-reasoned, and I can't find anything specifically wrong with it to point out to you, but it is missing the one vital truth of where Elements and TypeMirrors differ.
Elements represent nodes in the Java type AST that reside "on disk" - the code at rest, either in .java or .class files. Any class/interface/enum/record/annotation that exists on disk in this form is in some way discoverable by this. To get a bit further, these cover the entire API of any of those types above - any members (fields/constructors/methods or nested types, then also the params of those methods/ctors) and packages too are described by elements. But the Element hierarchy only covers the types on disk - to use a concrete example from your question, Comparable<T> and its Comparable<T>.compareTo(T) member, and that method's parameter are covered in this way. And yes, lest I omit the type parameter, both the class and the method have a type param embedded in their respective element - as an element.
On the other hand, TypeMirrors represent those elements "in use" - you can't really reason about Comparable<T> in your code, but instead will either use it raw (please don't), or will parameterize it in some specific way (such as Comparable<Frob>, Comparable<?>, or possibly Comparable<T> where T is the type param of an enclosing element such as the current method or class). This means that T is not the same TypeElement as above - it isn't the value of the TypeElement that was on disk, but is something more specific.
You'll find TypeMirrors in Elements (for example "what is the return type of the method that appears in this class?"), and all Elements can be converted to some form of TypeMirror. On the other hand, not all TypeMirrors can be converted to some Element (such as a primitive), or if they can, that conversion may be "lossy" (for example converting a TypeMirror of List<String> to an Element would give you only List<T> itself).

What's the difference between using a generic where condition and specifying argument type? [duplicate]

This question already has answers here:
What is the in-practice difference between generic and protocol-typed function parameters?
(2 answers)
Closed 3 years ago.
What advantages are there to using generics with a where clause over specifying a protocol for an argument, as in the following function signatures?
func encode<T>(_ value: T) throws -> Data where T : Encodable {...}
func encode(value: Encodable) throws -> Data {...}
The first is a generic method that requires a concrete type that conforms to Encodable. That means for each call to encode with a different type, a completely new copy of the function may be created, optimized just for that concrete type. In some cases the compiler may remove some of these copies, but in principle encode<Int>() is a completely different function than encode<String>(). It's a (generic) system for creating functions at compile time.
In contrast, the second is a non-generic function that accepts a parameter of the "Encodable existential" type. An existential is a compiler-generated box that wraps some other type. In principle this means that the value will be copied into the box at run time before being passed, possibly requiring a heap allocation if it's too large for the box (again, it may not be because the compiler is very smart and can sometimes see that it's unnecessary).
This ambiguity between the name of the protocol and the name of the existential will hopefully be fixed in the future (and there's discussion about doing so). In the future, the latter function will hopefully be spelled (note "any"):
func encode(value: any Encodable) throws -> Data {...}
The former might be faster. It might also take more space for all the copies of the function. (But see above about the compiler. Do not assume you know which of these will be faster in an actual, optimized build.)
The former provides a real, concrete type. That means it can be used for things that require a real, concrete type, such as calling a static method, or init. This means it can be used when the protocol has an associated type.
The latter is boxed into an existential, meaning it can be stored into heterogeneous collections. The former can only be put into collections of its particular concrete type.
So they're pretty different things, and each has its purpose.
You can use multiple type constraints.
func encode<T>(encodable: T) -> Data where T: Encodable, T: Decodable {
...
}

Understanding what Self.Generator.Element is in Swift map definition

Swift noob here.
Many functions have the Self.Generator.Element in the parameters of the closure definition. What the heck is it? I tried to go to the definition and it took me no where.
public func map<T>(#noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
This is a chain of the resolved types of generic protocols. Self is the adopter of this generic protocol, which has an associated type called Generator which adopts GeneratorType, which is itself a generic protocol, which has an associated type called Element. So Self.Generator.Element is whatever that type resolves to.
This chain lies at the basis of the relationship between a sequence (or collection) and its elements. For example, if Self is CollectionType, then Self.Generator.Element is the type of the collection's elements.
Thus, for instance, an Array of String, type Array<String> or [String], is a Collection whose Self.Generator.Element is String. And so the map method's transform function (in your example) would take a String as its parameter.
(Note that map says nothing about what type is output by the transform function; it is a pure generic placeholder, T. The compiler expects to be able to resolve T when it sees the actual function at compile time.)

How to constrain function parameter's protocol's associated types

For fun, I am attempting to extend the Dictionary class to replicate Python's Counter class. I am trying to implement init, taking a CollectionType as the sole argument. However, Swift does not allow this because of CollectionType's associated types. So, I am trying to write code like this:
import Foundation
// Must constrain extension with a protocol, not a class or struct
protocol SingletonIntProtocol { }
extension Int: SingletonIntProtocol { }
extension Dictionary where Value: SingletonIntProtocol { // i.e. Value == Int
init(from sequence: SequenceType where sequence.Generator.Element == Key) {
// Initialize
}
}
However, Swift does not allow this syntax in the parameter list. Is there a way to write init so that it can take any type conforming to CollectionType whose values are of type Key (the name of the type used in the generic Dictionary<Key: Hashable, Value>)? Preferably I would not be forced to write init(from sequence: [Key]), so that I could take any CollectionType (such as a CharacterView, say).
You just have a syntax problem. Your basic idea seems fine. The correct syntax is:
init<Seq: SequenceType where Seq.Generator.Element == Key>(from sequence: Seq) {
The rest of this answer just explains why the syntax is this way. You don't really need to read the rest if the first part satisfies you.
The subtle difference is that you were trying to treat SequenceType where sequence.Generator.Element == Key as a type. It's not a type; it's a type constraint. What the correct syntax means is:
There is a type Seq such that Seq.Generator.Element == Key, and sequence must be of that type.
While that may seem to be the same thing, the difference is that Seq is one specific type at any given time. It isn't "any type that follows this rule." It's actually one specific type. Every time you call init with some type (say [Key]), Swift will create an entirely new init method in which Seq is replaced with [Key]. (In reality, Swift can sometimes optimize that extra method away, but in principle it exists.) That's the key point in understanding generic syntax.
Or you can just memorize where the angle-brackets go, let the compiler remind you when you mess it up, and call it day. Most people do fine without learning the type theory that underpins it.

When do I have to specify type <T> for IEnumerable extension methods?

I'm a bit confused about the use of all the IEnumerable<T> extension methods, intellisense is always asking for <T>, but I don't think it's necessary to specify <T> at all times.
Let's say I have the following:
List<Person> people = GetSomePeople();
How is this:
List<string> names = people.ConvertAll<string>(p=>p.Name).Distinct<string>().ToList<string>();
different from this:
List<string> names = people.ConvertAll<string>(p=>p.Name).Distinct().ToList();
I think the two lines of code above are sxactly the same, now the question:
How do I know when to specify <T> and when to skip it?
The simplest way is obviously to omit it and see if it compiles.
In practice, you can omit type parameters wherever they are inferred; and they can normally be inferred when they are used in the type of a method parameter than you specify. They cannot be inferred if they're used only in the return type of the method. Thus, for example, for Enumerable.Select<T>, T will be inferred from the type of first argument (which is of type IEnumerable<T>). But for Enumerable.Empty<T>(), will not be inferred, because it's only used in return type of the method, and not in any arguments (as there are none).
Note that the actual rules are more complex than that, and not all arguments are inferable. Say you have this method:
void Foo<T>(Func<T, T> x);
and you try to call it with a lambda:
Foo(x => x);
Even though T is used in type of argument here, there's no way to infer the type - since there are no type specifications in the lambda either! As far as compiler is concerned, T is the same type x is, and x is of type T...
On the other hand, this will work:
Foo((int x) => x);
since now there is sufficient type information to infer everything. Or you could do it the other way:
Foo<int>(x => x);
The specific step-by-step rules for inference are in fact fairly complicated, and you'd be best off reading the primary source here - which is C# language specification.
This feature is known as type inference. In your example, the compiler can automatically determine the generic argument type implicitly for you because in the method call to ConvertAll, the parameter lambda returns a string value (i.e. Name). So you can even remove the <string> part of ConvertAll call. The same is with Distict(), as ConvertAll returns a List<string> and the compiler can declare the generic argument for you.
As for you answer, when the compiler can determine the type itself, the generic argument is redundant and unnecessary. Most of the times, the only place where you need to pass the generic argument is the declaration, like, List<string> list = new List<string>();. You can substitute the first List<string> with var instead or when you are using templates as parameters in lambdas too.