Type Safe Key-Value Construct


(David Moore) #1

  
Hello swift-evolution,

There are clearly weaknesses with obtaining values from a given dictionary in swift. Most notably, if we have a [String: Any] dictionary, how is one supposed to set/get a value with type safety? The following concept addresses this very issue.
  
I regularly use a self-constructed structure with static constants embedded within it, the structure enables a type safe implementation of keys and values (especially Dictionary applications). I will include a code snippet later on in this message, but I would specifically like to describe the benefits of a type safe key and value system, and how it would benefit the language.
  
When using dictionaries in Swift, one often finds themselves needing to use more general key and value types (e.g. [String: Any]). Unfortunately, when a Dictionary uses a general type, rather than one with more type safety and compile time checks, many issues can arise from such a use case.
  
The solution, in my opinion, is to use a pairing struct which can be used to create constant type-safe-enforcing structures. Additionally, said struct could have the ability to transform values of one type to that of another. Please see the code snippet below for more information regarding the implementation.
  
>
>
> struct Bar {
>
> var str: String
>
> }
>
>
>
> var foo = [String: Any]()
>
> foo["bar"] = Bar(str: "Hello, world.")
>
>
>
> // We are optionally casting this value of `Any` to `Bar`, but it's strongly typed, so there are clearly drawbacks.
>
> if let bar = foo["bar"] as? Bar {
>
> bar.str
>
> }
>
>
>
> // What if we use a `KeyValuePair`?
>
> let barPair = KeyValuePair<String, Any, Bar>(key: "bar")
>
> barPair.addValue(Bar(str: "This is better."), to: &foo)
>
>
>
> // Now look how easy (and safe) it is to get the value.
>
> let bar = barPair.value(from: foo)
>
>
  
I have already implemented the underlying structure for the above example usage. Also, there are other use cases that are not highlighted here, such as built in value transformation.
  
Let me know if anyone else agrees that this is a type safe solution for generalized dictionaries, or if think there are other uses for it. I also have all the code for the struct KeyValuePair, if anyone wants to see how it works, but it’s quite lightweight.
  
Thank you,
  
  David Moore / Owner / Chief Executive Officer
   david@mooredev.ca (mailto:david@mooredev.ca) / (705) 845-6057

  Moore Development
   https://www.mooredev.ca


(TJ Usiyan) #2

Wouldn't a struct be the better answer here overall or (with slightly fewer
assurances) using an enum as the `Value` type?

···

On Sat, Jun 10, 2017 at 12:56 PM, David Moore via swift-evolution < swift-evolution@swift.org> wrote:

Hello swift-evolution,

There are clearly weaknesses with obtaining values from a given dictionary
in swift. Most notably, if we have a [String: Any] dictionary, how is one
supposed to set/get a value with type safety? The following concept
addresses this very issue.

I regularly use a self-constructed structure with static constants
embedded within it, the structure enables a type safe implementation of
keys and values (especially Dictionary applications). I will include a code
snippet later on in this message, but I would specifically like to describe
the benefits of a type safe key and value system, and how it would benefit
the language.

When using dictionaries in Swift, one often finds themselves needing to
use more general key and value types (e.g. [String: Any]). Unfortunately,
when a Dictionary uses a general type, rather than one with more type
safety and compile time checks, many issues can arise from such a use case.

The solution, in my opinion, is to use a pairing struct which can be used
to create constant type-safe-enforcing structures. Additionally, said
struct could have the ability to transform values of one type to that of
another. Please see the code snippet below for more information regarding
the implementation.

struct Bar {

    var str: String

}

var foo = [String: Any]()

foo["bar"] = Bar(str: "Hello, world.")

// We are optionally casting this value of `Any` to `Bar`, but it's
strongly typed, so there are clearly drawbacks.

if let bar = foo["bar"] as? Bar {

    bar.str

}

// What if we use a `KeyValuePair`?

let barPair = KeyValuePair<String, Any, Bar>(key: "bar")

barPair.addValue(Bar(str: "This is better."), to: &foo)

// Now look how easy (and safe) it is to get the value.

let bar = barPair.value(from: foo)

I have already implemented the underlying structure for the above example
usage. Also, there are other use cases that are not highlighted here, such
as built in value transformation.

Let me know if anyone else agrees that this is a type safe solution for
generalized dictionaries, or if think there are other uses for it. I also
have all the code for the struct KeyValuePair, if anyone wants to see how
it works, but it’s quite lightweight.

Thank you,

[image: Moore Development]

David Moore / Owner / Chief Executive Officer
david@mooredev.ca / (705) 845-6057

Moore Development
https://www.mooredev.ca

<https://www.mooredev.ca/>

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution