salutis
(Rudolf Adamkovič)
1
Hi there!
In my app, I have a very simple class that serves as a key-value cache. The whole thing is basically a lazily populated [String: AVAudioPCMBuffer] dictionary with a String -> AVAudioPCMBuffer function that generates values as needed:
final class PlayerAudioCache {
// MARK: Retrieving audio buffers
func audioBufferForAssetWithName(name: String) -> AVAudioPCMBuffer? {
addAudioBufferForAssetWithNameIfNeeded(name)
return cachedAudioBuffers[name]
}
// MARK: Adding audio buffers
func addAudioBufferForAssetWithNameIfNeeded(name: String) {
guard cachedAudioBuffers[name] == nil else { return }
addAudioBufferForAssetWithName(name)
}
private func addAudioBufferForAssetWithName(name: String) {
guard let dataAsset = NSDataAsset(name: name) else { fatalError() }
cachedAudioBuffers[name] = dataAsset.map { URL -> AVAudioPCMBuffer in
AVAudioPCMBuffer(contentsOfURL: URL)!
}
}
private var cachedAudioBuffers: [String: AVAudioPCMBuffer] = [:]
}
I feel like there is a pre-made type in Swift’s standard library for what I’m doing here. Am I right?
Ideas? Pointers?
Thank you!
R+
Maybe something like this?
struct KeyedLazyCache<T: Hashable, U> {
var backingDictionary: Dictionary<T, U>
var builderDictionary: Dictionary<T, () -> U>
mutating func clear() {backingDictionary.removeAll()}
mutating func valueForKey(key: T) -> U? {
if let value = backingDictionary[key] {return value}
if let builder = builderDictionary[key] {
let value = builder()
backingDictionary[key] = value
return value
}
return nil
}
}
-- E
···
On Dec 28, 2015, at 11:36 AM, Rudolf Adamkovič via swift-users <swift-users@swift.org> wrote:
Hi there!
In my app, I have a very simple class that serves as a key-value cache. The whole thing is basically a lazily populated [String: AVAudioPCMBuffer] dictionary with a String -> AVAudioPCMBuffer function that generates values as needed:
final class PlayerAudioCache {
// MARK: Retrieving audio buffers
func audioBufferForAssetWithName(name: String) -> AVAudioPCMBuffer? {
addAudioBufferForAssetWithNameIfNeeded(name)
return cachedAudioBuffers[name]
}
// MARK: Adding audio buffers
func addAudioBufferForAssetWithNameIfNeeded(name: String) {
guard cachedAudioBuffers[name] == nil else { return }
addAudioBufferForAssetWithName(name)
}
private func addAudioBufferForAssetWithName(name: String) {
guard let dataAsset = NSDataAsset(name: name) else { fatalError() }
cachedAudioBuffers[name] = dataAsset.map { URL -> AVAudioPCMBuffer in
AVAudioPCMBuffer(contentsOfURL: URL)!
}
}
private var cachedAudioBuffers: [String: AVAudioPCMBuffer] = [:]
}
I feel like there is a pre-made type in Swift’s standard library for what I’m doing here. Am I right?
Ideas? Pointers?
Thank you!
R+
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users
1 Like
This version kind of mirrors Python’s defaultdict:
final class DefaultDict<Key: Hashable, Value>: CollectionType, CustomStringConvertible {
private var store: [Key:Value]
private let factory: Key -> Value
subscript(i: DictionaryIndex<Key,Value>) -> (Key,Value) {
return store[i]
}
var startIndex: DictionaryIndex<Key,Value> { return store.startIndex }
var endIndex: DictionaryIndex<Key,Value> { return store.endIndex }
func generate() -> DictionaryGenerator<Key,Value> {
return store.generate()
}
subscript(key: Key) -> Value {
get {
if let x = store[key] { return x }
let x = factory(key)
self.store[key] = x
return x
} set {
store[key] = newValue
}
}
init(_ def: Value) {
self.store = [:]
self.factory = { _ in def }
}
init(_ fac: Key -> Value) {
self.store = [:]
self.factory = fac
}
init(_ fac: () -> Value) {
self.store = [:]
self.factory = { _ in fac() }
}
var description: String { return store.description }
}
let dict = DefaultDict<Character,Int>(0)
for c in "abcdgeaaa".characters { dict[c] += 1 }
dict // ["b": 1, "e": 1, "a": 4, "g": 1, "d": 1, "c": 1]
···
On 28 Dec 2015, at 19:26, Erica Sadun via swift-users <swift-users@swift.org> wrote:
Maybe something like this?
struct KeyedLazyCache<T: Hashable, U> {
var backingDictionary: Dictionary<T, U>
var builderDictionary: Dictionary<T, () -> U>
mutating func clear() {backingDictionary.removeAll()}
mutating func valueForKey(key: T) -> U? {
if let value = backingDictionary[key] {return value}
if let builder = builderDictionary[key] {
let value = builder()
backingDictionary[key] = value
return value
}
return nil
}
}
-- E
On Dec 28, 2015, at 11:36 AM, Rudolf Adamkovič via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Hi there!
In my app, I have a very simple class that serves as a key-value cache. The whole thing is basically a lazily populated [String: AVAudioPCMBuffer] dictionary with a String -> AVAudioPCMBuffer function that generates values as needed:
final class PlayerAudioCache {
// MARK: Retrieving audio buffers
func audioBufferForAssetWithName(name: String) -> AVAudioPCMBuffer? {
addAudioBufferForAssetWithNameIfNeeded(name)
return cachedAudioBuffers[name]
}
// MARK: Adding audio buffers
func addAudioBufferForAssetWithNameIfNeeded(name: String) {
guard cachedAudioBuffers[name] == nil else { return }
addAudioBufferForAssetWithName(name)
}
private func addAudioBufferForAssetWithName(name: String) {
guard let dataAsset = NSDataAsset(name: name) else { fatalError() }
cachedAudioBuffers[name] = dataAsset.map { URL -> AVAudioPCMBuffer in
AVAudioPCMBuffer(contentsOfURL: URL)!
}
}
private var cachedAudioBuffers: [String: AVAudioPCMBuffer] = [:]
}
I feel like there is a pre-made type in Swift’s standard library for what I’m doing here. Am I right?
Ideas? Pointers?
Thank you!
R+
_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users
salutis
(Rudolf Adamkovič)
4
That’s a nice one, Erica.
Does this mean there’s nothing ready-made for this in the standard library?
P.S. No need for the builder dictionary. A simple static function (T->U) would be more enough for my use-case.
R+
···
On 28 Dec 2015, at 20:26, Erica Sadun <erica@ericasadun.com> wrote:
Maybe something like this?
struct KeyedLazyCache<T: Hashable, U> {
var backingDictionary: Dictionary<T, U>
var builderDictionary: Dictionary<T, () -> U>
mutating func clear() {backingDictionary.removeAll()}
mutating func valueForKey(key: T) -> U? {
if let value = backingDictionary[key] {return value}
if let builder = builderDictionary[key] {
let value = builder()
backingDictionary[key] = value
return value
}
return nil
}
}
-- E
On Dec 28, 2015, at 11:36 AM, Rudolf Adamkovič via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Hi there!
In my app, I have a very simple class that serves as a key-value cache. The whole thing is basically a lazily populated [String: AVAudioPCMBuffer] dictionary with a String -> AVAudioPCMBuffer function that generates values as needed:
final class PlayerAudioCache {
// MARK: Retrieving audio buffers
func audioBufferForAssetWithName(name: String) -> AVAudioPCMBuffer? {
addAudioBufferForAssetWithNameIfNeeded(name)
return cachedAudioBuffers[name]
}
// MARK: Adding audio buffers
func addAudioBufferForAssetWithNameIfNeeded(name: String) {
guard cachedAudioBuffers[name] == nil else { return }
addAudioBufferForAssetWithName(name)
}
private func addAudioBufferForAssetWithName(name: String) {
guard let dataAsset = NSDataAsset(name: name) else { fatalError() }
cachedAudioBuffers[name] = dataAsset.map { URL -> AVAudioPCMBuffer in
AVAudioPCMBuffer(contentsOfURL: URL)!
}
}
private var cachedAudioBuffers: [String: AVAudioPCMBuffer] = [:]
}
I feel like there is a pre-made type in Swift’s standard library for what I’m doing here. Am I right?
Ideas? Pointers?
Thank you!
R+
_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users
salutis
(Rudolf Adamkovič)
5
All right, here is the outcome:
https://github.com/salutis/KeyedCache/blob/master/KeyedCache.swift
Thanks Erica and Donnacha for examples and inspiration!
R+
···
On 28 Dec 2015, at 19:36, Rudolf Adamkovič via swift-users <swift-users@swift.org> wrote:
Hi there!
In my app, I have a very simple class that serves as a key-value cache. The whole thing is basically a lazily populated [String: AVAudioPCMBuffer] dictionary with a String -> AVAudioPCMBuffer function that generates values as needed:
final class PlayerAudioCache {
// MARK: Retrieving audio buffers
func audioBufferForAssetWithName(name: String) -> AVAudioPCMBuffer? {
addAudioBufferForAssetWithNameIfNeeded(name)
return cachedAudioBuffers[name]
}
// MARK: Adding audio buffers
func addAudioBufferForAssetWithNameIfNeeded(name: String) {
guard cachedAudioBuffers[name] == nil else { return }
addAudioBufferForAssetWithName(name)
}
private func addAudioBufferForAssetWithName(name: String) {
guard let dataAsset = NSDataAsset(name: name) else { fatalError() }
cachedAudioBuffers[name] = dataAsset.map { URL -> AVAudioPCMBuffer in
AVAudioPCMBuffer(contentsOfURL: URL)!
}
}
private var cachedAudioBuffers: [String: AVAudioPCMBuffer] = [:]
}
I feel like there is a pre-made type in Swift’s standard library for what I’m doing here. Am I right?
Ideas? Pointers?
Thank you!
R+
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users