Skip to content

Instantly share code, notes, and snippets.

@broomburgo
Created May 4, 2015 16:16
Show Gist options
  • Save broomburgo/ba8e5dd6cd509fdfd781 to your computer and use it in GitHub Desktop.
Save broomburgo/ba8e5dd6cd509fdfd781 to your computer and use it in GitHub Desktop.
type-first-development-in-swift-code-for-blog-article
/* NOT QUITE FLEXIBLE
struct Field {
let id: String
let name: String
let value: String
let visible: Bool
}
*/
typealias UniqueKey = String
enum FieldValue: Equatable {
case Text(String)
case Empty
}
func == (lhs: FieldValue, rhs: FieldValue) -> Bool {
switch (lhs, rhs) {
case (.Empty, .Empty):
return true
case (.Text(let lhsText), .Text(let rhsText)):
return lhsText == rhsText
default:
return false
}
}
enum FieldVisibility: Equatable {
case Visible
case Hidden
}
func == (lhs: FieldVisibility, rhs: FieldVisibility) -> Bool {
switch (lhs, rhs) {
case (.Visible, .Visible), (.Hidden, .Hidden):
return true
default:
return false
}
}
struct Field {
let id: UniqueKey
let name: String
let value: FieldValue
let visibility: FieldVisibility
init (_ id: UniqueKey, _ name: String, _ value: FieldValue, _ visibility: FieldVisibility) {
self.id = id
self.name = name
self.value = value
self.visibility = visibility
}
}
typealias FieldChange = Field -> Field
func setVisibility (visibility: FieldVisibility) -> FieldChange {
return { field in
return Field (
field.id,
field.name,
field.value,
visibility
)
}
}
/// alcuni esempi
let setHidden = setVisibility(.Hidden)
let visibleField1 = Field ("","", .Empty, .Visible)
let isTrue1 = visibleField1.visibility == .Visible
let hiddenField1 = setHidden(visibleField1)
let isTrue2 = hiddenField1.visibility == .Hidden
typealias FieldChangeGenerator = Field -> FieldChange
/// una funzione che rende modifica la visibilità di un campo in base al valore di un altro campo
/*
typealias FieldCondition = Field -> FieldVisibility
func setVisibilityIfOrigin (condition: FieldCondition) -> FieldChangeGenerator {
return { origin in
let newVisibility = condition(origin)
return setVisibility(newVisibility)
}
}
/// alcuni esempi
let setVisibleIfNotEmpty = setVisibilityIfOrigin { field in
switch field.value {
case .Empty:
return .Hidden
default:
return .Visible
}
}
let nonEmptyField = Field ("", "", .Text("something"), .Visible)
let anotherVisibleField = setVisibleIfNotEmpty(nonEmptyField)(invisibleField)
let isTrue3 = anotherVisibleField.visibility == .Visible
*/
/// rendiamo generica la condizione
struct FieldCondition<T> {
let apply: Field -> T
init(_ apply: Field -> T) {
self.apply = apply
}
}
func setTargetIfOrigin<T> (condition: FieldCondition<T>, generate: T -> FieldChange) -> FieldChangeGenerator {
return { field in
return generate(condition.apply(field))
}
}
func setVisibilityIfOrigin (condition: FieldCondition<FieldVisibility>) -> FieldChangeGenerator {
return setTargetIfOrigin (condition) { visibility in setVisibility(visibility) }
}
let setVisibleIfNotEmpty = setVisibilityIfOrigin (FieldCondition { origin in
switch origin.value {
case .Empty:
return .Hidden
default:
return .Visible
}
})
let copyValue = setTargetIfOrigin (FieldCondition { $0.value}) { value in
return { target in
return Field(target.id,target.name,value,target.visibility)
}
}
let field1 = Field("field1","",.Text("1"),.Visible)
let field2 = Field("field2","",.Text("2"),.Visible)
let newField1 = copyValue(field2)(field1)
let isTrue4 = newField1.value == .Text("2")
/// creiamo una condizione per il target
/// serve perché nel form avremmo tanti campi e noi vogliamo solo modificarne uno
typealias FieldCheck = FieldChange -> FieldChange
typealias FieldConditionBool = FieldCondition<Bool>
func checkTarget (condition: FieldConditionBool) -> FieldCheck {
return { change in
return { field in
if condition.apply(field) {
return change(field)
}
else {
return field
}
}
}
}
func ifTargetId (id: UniqueKey) -> FieldCheck {
return checkTarget (FieldCondition { $0.id == id })
}
let visibleField = ifTargetId("field2")(setHidden)(field1)
let hiddenField = ifTargetId("field2")(setHidden)(field2)
let isTrue5 = visibleField.visibility == .Visible
let isTrue6 = hiddenField.visibility == .Hidden
let fields = [field1,field2]
let newFields = fields.map(ifTargetId("field2")(setHidden))
let isTrue7 = newFields[0].visibility == .Visible
let isTrue8 = newFields[1].visibility == .Hidden
/// ok, da una lista di Field vogliamo realizzare un Form
/* BAD IDEA
struct Section {
let fields: [Field]
}
struct Step {
let sections: [Section]
}
struct Form {
let steps: [Step]
}
*/
enum Node<T> {
case Branch([T])
case Root([Node<T>])
}
typealias Form = Node<Field>
func branch (fields: [Field]) -> Form {
return Node.Branch(fields)
}
func root (nodes: [Form]) -> Form {
return Node.Root(nodes)
}
typealias FormChange = Form -> Form
func changeFromFieldChange (fieldChange: FieldChange) -> FormChange {
return { form in
switch form {
case .Branch (let fields):
return branch(fields.map(fieldChange))
case .Root (let subforms):
return root(subforms.map(changeFromFieldChange(fieldChange)))
}
}
}
let updateField = changeFromFieldChange
let form = branch([field1,field2])
let newForm = updateField(ifTargetId("field1")(setHidden))(form)
typealias FieldGet = Form -> [Field]
func fieldsWithCondition (condition: FieldConditionBool) -> FieldGet {
return { form in
switch form {
case .Branch(let fields):
return fields.filter(condition.apply)
case .Root(let subforms):
return subforms.map(fieldsWithCondition(condition)).reduce([], combine: +)
}
}
}
func fieldsWithId (id: UniqueKey) -> FieldGet {
return fieldsWithCondition (FieldConditionBool { $0.id == id })
}
let allFields: FieldGet = fieldsWithCondition (FieldConditionBool { _ in true })
let twoFields = allFields(form)
let isTrue9 = count(twoFields) == 2
let isTrue10 = fieldsWithId("field1")(form)[0].visibility == .Visible
let isTrue11 = fieldsWithId("field1")(newForm)[0].visibility == .Hidden
@broomburgo
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment