Returning lazy sequences - swift

I have a lazy sequence I do some operations on and want to return from a function
func getSeq() -> ??? {
let a = array.lazy
./* ... operations like map, filter, etc */
}
The final type of a is:
LazyMapSequence<FlattenSequence<LazyMapSequence<LazyFilterSequence<LazySequence<[[ComponentId] : ArchetypeId]>.Elements>.Elements, Zip2Sequence<Zip2Sequence<[C1], [C2]>, [C3]>>>, (C1, C2, C3)>
now how do I return a without having to specify the return type as that long type?

Opaque result types were created for exactly this purpose. They were added in Swift 5.1. You'll see them often in SwiftUI, where view contents are expressed as some View, meaning the result is some complex generic type (whose particular type is hidden from the user code), so long as it conforms to View.
For your particular case here, you would need to them in conjunction with primary associated types, to express exactly what kind of elements the resulting sequence should produce, like so:
func getSeq() -> some Sequence<Element> {
return array.lazy
./* ... operations like map, filter, etc */
}
Primary associated types were only recently introduced in Swift 5.7. As far as I can tell, they're a purely compile-time feature, so they don't require any specific OS version at runtime.
If Apple dropped support for your Mac and you can't run the necessary Xcode version for Swift 5.7, your next best bet is to do what we used to do: Use a type-eraser to erase the concrete type. For cases like yours, the standard library provides two type erasers, AnySequence and AnyCollection. This limits the type information to work with, so it might not optimize as nicely, but it works well enough.
func getSeq() -> AnySequence<Element> {
return AnySequence(
array.lazy
./* ... operations like map, filter, etc */
)
}

Related

Why does the generic type not participate in method overloading via constraint further down the call chain?

Swift allows generic methods to be overloaded by the constraints placed upon the generic types passed in. If you use this with concrete types, then the type passed in will participate in this overloading and constraints will be inferred from that type.
As soon as a generic method delegates to another with overload resolution, the constraints can no longer be inferred and will instead utilize the constraints already placed on the type from above.
protocol Conformance {}
extension String : Conformance {}
// #1
func baseMethod<T>(_ value: T) {
let isConforming = T.self is Conformance.Type
}
// #2
func baseMethod<T>(_ value: T) where T : Conformance {
let isConforming = T.self is Conformance.Type
}
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
func run() {
// Calls #2, isConforming = true
baseMethod(String())
// Calls #1, isConforming = true
delegatingMethod(String())
}
I assume this is there so that you have sufficient type information from the call site about what constraints are applicable no matter where the generic type is used, but it seems to severely and artificially limit the utility of overloading by constraint.
Are there any known workarounds to this oddity? Something that emulates this would be extremely useful.
Swift allows generic methods to be overloaded by the constraints placed upon the generic types passed in.
Yes...but be very clear that this is a static overload, not a dynamic override. It is based on types that can be proven at compile-time.
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
We're compiling this now, and we need to write it as a concrete, static function call, possibly inlined, into the binary. What do we know about T? We know nothing about T, so any where clause will fail.
We don't even know about how this function is called, because the call may come from another compile unit or module. While in principle, it could have different semantics based on access level, such that one version were used when it is private and all calls can be evaluated, and another used when it's public, that would be a really horrible source of bugs.
What you're asking for is that delegatingMethod defer its decision about what function call to make until runtime. That's not how generics work. Moreover, you're asking that all the where clauses be encoded somewhere in the binary so that they can be evaluated at runtime. Also not how generics work. That would require a much more dynamic dispatch system than Swift wants to implement. It's not impossible; it's just a completely different animal, and prevents lots of optimizations.
This feels like you're trying to reinvent class inheritance with protocols and generics. You can't. They're different solutions and have different features. Class inheritance is fundamentally dynamic. Protocols and generics are fundamentally static. If you want dynamic dispatch based on specific types, use classes.

Are Int, String etc. considered to be 'primitives' in Swift?

Types representing numbers, characters and strings implemented using structures in swift.
An excerpt from the official documentation:
Data types that are normally considered basic or primitive in other
languages—such as types that represent numbers, characters, and
strings—are actually named types, defined and implemented in the Swift
standard library using structures.
Does that mean the following:
Int
Float
String
// etc
... are not considered as primitives?
Yes and no...
As other answers have noted, in Swift there's no difference at the language level between the things one thinks of as "primitives" in other languages and the other struct types in the standard library or the value types you can create yourself. For example, it's not like Java, where there's a big difference between int and Integer and it's not possible to create your own types that behave semantically like the former. In Swift, all types are "non-primitive" or "user-level": the language features that define the syntax and semantics of, say, Int are no different from those defining CGRect or UIScrollView or your own types.
However, there is still a distinction. A CPU has native instructions for tasks like adding integers, multiplying floats, and even taking vector cross products, but not those like insetting rects or searching lists. One of the things people talk about when they name some of a language's types "primitively" is that those are the types for which the compiler provides hooks into the underlying CPU architecture, so that the things you do with those types map directly to basic CPU instructions. (That is, so operations like "add two integers" don't get bogged down in object lookups and function calls.)
Swift still has that distinction — certain standard library types like Int and Float are special in that they map to basic CPU operations. (And in Swift, the compiler doesn't offer any other means to directly access those operations.)
The difference with many other languages is that for Swift, the distinction between "primitive" types and otherwise is an implementation detail of the standard library, not a "feature" of the language.
Just to ramble on this subject some more...
When people talk about strings being a "primitive" type in many languages, that's a different meaning of the word — strings are a level of abstraction further away from the CPU than integers and floats.
Strings being "primitive" in other languages usually means something like it does in C or Java: The compiler has a special case where putting something in quotes results in some data getting built into the program binary, and the place in the code where you wrote that getting a pointer to that data, possibly wrapped in some sort of object interface so you can do useful text processing with it. (That is, a string literal.) Maybe the compiler also has special cases so that you can have handy shortcuts for some of those text processing procedures, like + for concatenation.
In Swift, String is "primitive" in that it's the standard string type used by all text-related functions in the standard library. But there's no compiler magic keeping you from making your own string types that can be created with literals or handled with operators. So again, there's much less difference between "primitives" and user types in Swift.
Swift does not have primitive types.
In all programming languages, we have basic types that are available part of the language. In swift, we have these types availed through the Swift standard library, created using structures. These include the types for numbers, characters and strings.
No, they're not primitives in the sense other languages define primitives. But they behave just like primitives, in the sense that they're passed by value. This is consequence from the fact that they're internally implemented by structs. Consider:
import Foundation
struct ByValueType {
var x: Int = 0;
}
class ByReferenceType {
var x: Int = 0;
}
var str: String = "no value";
var byRef: ByReferenceType = ByReferenceType();
var byVal: ByValueType = ByValueType();
func foo(var type: ByValueType) {
type.x = 10;
}
func foo(var type: ByReferenceType) {
type.x = 10;
}
func foo(var type: String) {
type = "foo was here";
}
foo(byRef);
foo(byVal);
foo(str);
print(byRef.x);
print(byVal.x);
print(str);
The output is
10
0
no value
Just like Ruby, Swift does not have primitive types.
Int per example is implemented as structand conforms with the protocols:
BitwiseOperationsType
CVarArgType
Comparable
CustomStringConvertible
Equatable
Hashable
MirrorPathType
RandomAccessIndexType
SignedIntegerType
SignedNumberType
You can check the source code of Bool.swift where Bool is implemented.
There are no primitives in Swift.
However, there is a distinction between "value types" and "reference types". Which doesn't quite fit with either C++ or Java use.
They are partial primitive.
Swift not exposing the primitive like other language(Java). But Int, Int16, Float, Double are defined using structure which behaves like derived primitives data type(Structure) not an object pointer.
Swift Documentation favouring to primitive feature :
1.They have Hashable extension say
Axiom: x == y implies x.hashValue == y.hashValue.
and hashValue is current assigned value.
2.Most of the init method are used for type casting and overflow check (remember swift is type safe).
Int.init(_ other: Float)
3. See the below code Int have default value 0 with optional type. While NSNumber print nil with optional type variable.
var myInteger:Int? = Int.init()
print(myInteger) //Optional(0)
var myNumber:NSNumber? = NSNumber.init()
print(myNumber) //nil
Swift Documentation not favouring to primitive feature :
As per doc, There are two types: named types and compound types. No concept of primitives types.
Int support extension
extension Int : Hashable {}
All these types available through the Swift standard library not like standard keyword.

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.

What is the usecase for ignored parameters in Swift

In Swift, you can write the following:
func foo(_:Int) -> { return 1 }
Where the underscore is an ignored parameter. I only know this because of the documentation, but cannot think of ANY usecase on why you would even do this. Am I missing something?
Ignoring parameters (or members of a tuple, which are pretty close to the same thing) makes sense when:
You're overriding a superclass function or implementing a function defined by a protocol, but your implementation of that function doesn't need one of the parameters. For example, if you hook app launching but don't need a reference to the shared UIApplication instance in that method:
override func application(_: UIApplication!, didFinishLaunchingWithOptions _: NSDictionary!) -> Bool { /* ... */ }
You're providing a closure (aka block in ObjC) as a parameter to some API, but your use of that API doesn't care about one of the parameters to the closure. For example, if you're submitting changes to the Photos library and want to throw caution to the wind, you can ignore the success and error parameters in the completion handler:
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
// change requests
}, completionHandler: { _, _ in
NSLog("Changes complete. Did they succeed? Who knows!")
})
You're calling a function/method that provides multiple return values, but don't care about one of them. For example, assuming a hypothetical NSColor method that returned components as a tuple, you could ignore alpha:
let (r, g, b, _) = color.getComponents()
The reasoning behind this is that it makes your code more readable. If you declare a local name for a parameter (or tuple member) that you don't end up using, someone else reading your code (who could well be just the several-months-later version of yourself) might see that name and wonder where or how it gets used in the function body. If you declare upfront that you're ignoring that parameter (or tuple member), it makes it clear that there's no need to worry about it in that scope. (In theory, this could also provide an optimization hint to the complier, which might make your code run faster, too.)
Perhaps you're overriding a method and your override ignores one of the parameters? Making it clear that you're ignoring the parameter saves future coders from having to look through your code to work out that it's not using the parameter and makes it clear that this was intentional. Or maybe it's to create some sort of Adapter pattern where you make it clear that one of the parameters is being ignored.

Passing a collection of interface types to a function

I'm having trouble figuring out the correct way to use interfaces in Go. My function needs to take a map of items that implement a certain method. It looks like this:
type foo interface {
bar() string
}
func doSomething(items map[string]foo) {
}
I'm trying to call this function with a type that implements the foo interface.
type baz struct { }
func (b baz) bar() string {
return "hello"
}
items := map[string]baz{"a": baz{}}
doSomething(items)
But I get the following error:
cannot use items (type map[string]baz) as type map[string]foo in function argument
However, it works fine when I do this:
items := map[string]foo{"a": baz{}}
doSomething(items)
But I want to reuse this same map against different interfaces. Basically I'm indexing a lot of objects and then passing them to various functions that require different interfaces implemented to compute results. I want to pass the map to one function as a map of foo and another function as a map of foobar.
I've tried various type assertions and conversions but nothing seems to work so I'm not sure if I'm just not using the correct syntax or just doing it completely wrong.
Go Playground at http://play.golang.org/p/8mMWCDG7vm.
This is a fairly common mistake.
You are mixing these two distinct types:
map[string]foo
map[string]baz
You cannot simply convert from one map type to another. The same goes with converting []T slices to []interface{} slices, or converting chan T to chan interface{} (same question/answer but for channels).
map[string]foo means a map of foo interfaces, not all types map[string]T where T implements the foo interface.
You can solve it by making this change:
items := map[string]foo{"a": baz{}}
Playground: http://play.golang.org/p/HxIVGSptwk
Edit:
Having a map of interfaces allows you to type cast the different interface values to other types of interfaces. So the map can be reused.
Playground: http://play.golang.org/p/20YMWmDjYT
But then you should have a map of an interface type that is the intersection of all the different methods implemented by the types to be stored in the map. If there is no intersection, then you will have to use interface{} to ensure that any type might be stored.