Last active
August 29, 2015 14:13
-
-
Save fnky/43ff80844a99fb10b200 to your computer and use it in GitHub Desktop.
Proposal for Memberwise Initializers with Optional Arguments and Default Values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 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
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