How do I write a generic recursive function that takes a CollectionType in Swift? - swift2

How would you create a generic function to process a CollectionType in Swift? For example, I want something that boils down to this:
func f<C: CollectionType>(list: C) {
if list.isEmpty {
return
}
else {
f(list.dropFirst()) // causes error
}
}
This causes an error because SubSequence might not be a CollectionType: Cannot invoke 'f' with an argument list of type '(C.SubSequence)'
I tried working around it by constraining the SubSequence type like this:
<C: CollectionType where C.SubSequence: CollectionType>
I get the same error, though. Any suggestions on how to write a generic recursive function for CollectionType?

To fix your error, you can transform a SubSequence into an array with the Array initializer:
func f<C: CollectionType>(list: C) {
if list.isEmpty {
return
}
else {
f(Array(list.dropFirst()))
}
}

Here's a solution that doesn't require copying the storage in a new array with every iteration:
func f<C: CollectionType
where C.SubSequence: CollectionType,
C.SubSequence == C.SubSequence.SubSequence>(c: C) {
guard let first = c.first else { return }
print(first)
f(c.dropFirst())
}
In Swift 3:
func f<C>(_ c: C) where
C: Collection,
C.SubSequence: Collection,
C.SubSequence == C.SubSequence.SubSequence {
guard !c.isEmpty else { return }
f(c.dropFirst())
}
f([1, 2, 3])

Related

Can I rewrite a key value while iterating a sync.Map using it's reciever function Range(func(key, value interface{}) bool {...})

I have the example below as the existing sync.Map (I know, they are iterfaces,this is just visualized) :
[1: "Hello", 2: "Good", 3: "Morning"]
Can I use the sync.Map's built in (reciever) Range function while iterating on it using to change the value of the keys based on certain conditions? Example:
sync.Map.Range(func(key, value interface {}) bool {
if key.(int) == 1 {
sync.Map.Store(1, "Sorry")
}
if key.(int) == 2 {
sync.Map.Store(2, "Not")
}
if key.(int) == 3 {
sync.Map.Store(3, "Interested")
}
})

What is the meaning of `copyOnWriteContext` in module `github.com/google/btree`?

Recently, I read the source code of google/btree. But I'am conflused by the struct copyOnWriteContext. It is used in node function mutableFor, like following
func (n *node) mutableFor(cow *copyOnWriteContext) *node {
if n.cow == cow {
return n
}
fmt.Println("new node?")
out := cow.newNode()
if cap(out.items) >= len(n.items) {
out.items = out.items[:len(n.items)]
} else {
out.items = make(items, len(n.items), cap(n.items))
}
copy(out.items, n.items)
// Copy children
if cap(out.children) >= len(n.children) {
out.children = out.children[:len(n.children)]
} else {
out.children = make(children, len(n.children), cap(n.children))
}
copy(out.children, n.children)
return out
}
I review all the code in this module, and found that there is only one place create the copyOnWriteContext's instance. It is when the tree is created.
func New(degree int) *BTree {
return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize))
}
So what is the meaning for mutableFor. Because there is only one copyOnWriteContext in the entire code. The n.cow always equals param cow.
n.cow can be nil.
// freeNode frees a node within a given COW context, if it's owned by that
// context. It returns what happened to the node (see freeType const
// documentation).
func (c *copyOnWriteContext) freeNode(n *node) freeType {
if n.cow == c {
// clear to allow GC
n.items.truncate(0)
n.children.truncate(0)
n.cow = nil
if c.freelist.freeNode(n) {
return ftStored
} else {
return ftFreelistFull
}
} else {
return ftNotOwned
}
}

Rust: take ownership of enum value without another pattern matching

The question is in the comment. Expensive is a struct that either doesn't implement Copy, or copying is too expensive.
Update: replaced Option with a user enum Internal.
enum Internal {
Type1(Expensive),
Type2(String),
Empty,
}
struct Foo {
value: Internal,
}
impl Foo {
fn exec(&mut self) -> Result<Expensive, String> {
if let Internal::Type1(_) = &self.value {
let value = std::mem::take(&mut self.value);
// QUESTION: how do I avoid this pattern matching since we know the value must be Internal::Type1
return match value {
Internal::Type1(e) => Result::Ok(e),
_ => Result::Err(String::from("Impossible")),
};
}
// Some other logic that will use self.value
}
}
You can leverage Option::take to make the code shorter:
if let Option::Some(value) = self.value.take() {
return Ok(value);
}

Swift: filter protocol array by comparing types

(first post)
usually im able to find answers here or elsewhere but no luck this time =(
Question: in Swift, how do you filter an array that is of a protocol type by an implementing type supplied as a function parameter?
protocol Aprotocol {
var number:Int { get set }
}
class Aclass: Aprotocol {
var number = 1
}
class AnotherClass: Aprotocol {
var number = 1
}
var array:[Aprotocol] = [ Aclass(), AnotherClass(), Aclass() ]
func foo (parameter:Aprotocol) -> Int {
return array.filter({ /* p in p.self == parameter.self */ }).count
}
var bar:Aprotocol = // Aclass() or AnotherClass()
var result:Int = foo(bar) // should return 2 or 1, depending on bar type
maybe this is not the right approach at all?
thanks!
Here is what I think you want:
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == parameter.dynamicType
}.count
But I recommend this, which does the same, but without the useless instance of Aclass() which is passed in the answer on the top. Also this way is faster:
func foo <T: Aprotocol>(type: T.Type) -> Int {
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == type
}.count
}
var result:Int = foo(Aclass)
The dynamicType will return the Type of an instance
Very easy:
return array.filter({ parameter.number == $0.number }).count
Kametrixoms solution works (if you use "is T" instead of "== type") but in my case, since i didnt know which implementing class was going to call it, had to go with this solution:
protocol Aprotocol: AnyObject {
var number:Int { get set }
}
class func foo(parameter: AnyObject) -> Int {
return array.filter ({ (element: Aprotocol) -> Bool in
object_getClassName(element) == object_getClassName(parameter)
}).count
}

Swift, Equatable protocol bug?

I am building a very simple structure in Swift that contains an array of optional values. This struct must conform to the Equatable protocol. This is the code:
struct MyTable: Equatable {
var values: [Int?] = Array(count: 64, repeatedValue: nil)
}
func == (lhs: MyTable, rhs: MyTable) -> Bool {
return lhs.values == rhs.values
}
Quite simple. I see no mistakes, but the compiler gives error: "'[Int?]' is not convertible to 'MyTable'". Am I doing something stupid? or is this a compiler's bug? Thanks!
(Using Xcode6-Beta5)
The reason why it does not work is there is no == operator defined for arrays with optional elements, only for non-optional elements:
/// Returns true if these arrays contain the same elements.
func ==<T : Equatable>(lhs: [T], rhs: [T]) -> Bool
You can provide your own:
func ==<T : Equatable>(lhs: [T?], rhs: [T?]) -> Bool {
if lhs.count != rhs.count {
return false
}
for index in 0..<lhs.count {
if lhs[index] != rhs[index] {
return false
}
}
return true
}
Another useful option is to use the elementsEqual:isEquivalent: method available on SequenceType. This could allow you to avoid implementing Equatable, but is best used rarely as it is more verbose.
Usage:
let a: [Int?] = []
let b: [Int?] = []
if a.elementsEqual(b, isEquivalent: { $0 == $1 }) {
print("foo") // Works
}

Resources