Skip to content

Instantly share code, notes, and snippets.

@fnky
Last active August 29, 2015 14:13
Show Gist options
  • Save fnky/43ff80844a99fb10b200 to your computer and use it in GitHub Desktop.
Save fnky/43ff80844a99fb10b200 to your computer and use it in GitHub Desktop.
Proposal for Memberwise Initializers with Optional Arguments and Default Values
/*
Memberwise Initializers with Optional Arguments and Default Values
This playground explains a proposal to enhance the use of the great
feature; member variables. To extend the possibilities of the Swift
language and still keep it simple enough to understand.
Member initializers are a great addition, and helps scaffolding
structures, without doing initial boilerplate code. It works well,
but there's some differences when it comes to Optional types and
default values.
I do have in mind, that the design of member initializers have
been put into great thought, and should still be as is—to some extent.
*/
import UIKit
/* As it works now, creating a struct without
* an implicit initializer, will give use a memberwise
* initializer - convinient */
struct FooStruct {
var width: CGFloat
var height: CGFloat
}
var myRect: FooStruct = FooStruct(width: 150.0, height: 150.0)
/* We can also give default values */
struct BarStruct {
var red: Double = 255.0
var green: Double = 155.0
var blue: Double = 128.0
var alpha: Double = 1.0
}
var leColor: BarStruct = BarStruct()
/* However, here is where it becomes a bit strange as we already
* set default values, but it is still required to pass the arguments */
// var colors: BarStruct = BarStruct(blue: 0.0, alpha: 0.1) // Requires all arguments to be set
/* This would require us to declare implicit initializers
* even though the passing arguments should be of same
* structure.
*
* Even further, we can declare variables that uses ? and !
* This could be for specifying a specific set of values
* that later could be merged to become one without heavy
* validation */
struct BrushStyle {
var color: UIColor? = UIColor.blackColor()
var width: Double? = nil
var intensity: Double? = nil
var opacity: Double? = nil
var pattern: UIImage? = nil
}
// var fineBrush: BrushStyle = BrushStyle(width: 0.05, intensity: 1.0) // Requires arguments to be set - even to nil!
var whatBrush: BrushStyle = BrushStyle(color: nil, width: 2.0, intensity: 9.5, opacity: 1.0, pattern: nil)
/* In this case, it would make sense to allow the initializer
* to pass the default values.
*
* This is how the memberwise initializer could
* look like under the hood. */
struct MyStyle {
var backgroundColor: UIColor? = nil
var textColor: UIColor? = nil
var font: UIFont? = nil
var tintColor: UIColor? = nil
var borderStyle: UITextBorderStyle? = nil
init(backgroundColor: UIColor? = nil,
textColor: UIColor? = nil,
font: UIFont? = nil,
tintColor: UIColor? = nil,
borderStyle: UITextBorderStyle? = nil) {
self.backgroundColor = backgroundColor
self.textColor = textColor
self.font = font
self.tintColor = tintColor
self.borderStyle = borderStyle
}
}
let foo = MyStyle(backgroundColor: UIColor.redColor())
let bar = MyStyle(textColor: UIColor.whiteColor(), borderStyle: .Bezel)
/* Allowing the `optional` keyword for variables could
* also be an option, as it wouldn't break the current behaviour
* and also makes it clear which variables are optional to pass
* and which aren't */
/*/ struct Item {
var level: Int
optional var durability: Float = 1.0
optional var damage: Float = 0.0
optional var attacksPerSecond: Float = 2.0
optional var damagePerSecond: Float? = nil
optional var requiredLevel: Int? = nil
} /*/
/* Using the `optional` would allow for an initializer, that doesn't
* require all arguments to be implicitly set */
// var crossbow: Item = Item(level: 1, durability: 1.0) // {1, 1.0, 0.0, 2.0, nil, nil}
/* Classes could be used, but that would come down to Value and Reference Types,
* as we don't always want to use references for small constructors, that could or
* should be independent. */
/* This method allows us to use Value Types, keeping the memberwise initializers
* and not requiring arguments, even though their default value has been defined,
* which adds complexity—or a lot of bloat—to initializers. */
*/*/
@pyrtsa
Copy link

pyrtsa commented Jan 9, 2015

I don't think the feature is big enough to justify the added syntax. Here's how I'd do it with the existing language: https://gist.github.com/pyrtsa/4f18f43c5e467b0fdf54

@fnky
Copy link
Author

fnky commented Jan 9, 2015

@pyrtsa I see the idea in your example, however I don't quite like the approach of defining initializers, if all arguments should be the same anyway.

I agree with you, that the added syntax with using optional might be too much. But I also don't quite understand why it is required to pass arguments, if you're not going to change their default values anyway.

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