Use Function in Initializer - Swift? - swift

Assume the following:
class A {
let x : Int
init() {
self.x = assign(1)
}
func assign(y : Int) -> Int {
return y
}
}
This produces an error.
Here is my question : is there a way to call functions within the class initializer?
EDIT: Added error message:
use of 'self' in method call 'assign' before all stored properties are initialized

You can't call instance methods until the instance is initialized (before init is done), but you can use module-level functions and type methods defined using the class or static keyword.
func compute(y: Int) -> Int {
return y
}
class A {
let x: Int
static func assign(y: Int) -> Int {
return y
}
init () {
x = A.assign(3) + compute(4)
}
}

One other (possibly helpful) option is to have the function you call within the initializer scope:
class A {
let x : Int
init() {
func assign(y : Int) -> Int {
return y
}
self.x = assign(y: 1)
}
}
I'm doing that in a project right now. I have a large initializer (its actually a parser) and use an initializer-scoped function for error reporting. Of course, I'd prefer the function to be at class scope so I can reuse it between initializers. But at least I can reuse it within each initializer.

I think it is not the greatest solution but still it is working.
class A {
var variable : Int
init() {
self.variable = A.assign(1)
}
private class func assign(y : Int) -> Int {
return y
}
}

You could use somethings like:
class A {
var x : Int!
init() {
x = assign(1)
}
func assign(y : Int) -> Int {
return y
}
}
The downside of this approach is that you will get a runtime error if you access x and it is not initialised. Check out this answer.

Related

When declaring static variable for conformance to AdditiveArithmetic, cannot call instance member from same type

I know this sounds crazy for a 10-year-old, but because S4TF doesn't work for me, I'm building my own neural network library in Swift. (I haven't gotten that far.) I'm creating a structure that conforms to AdditiveArithmetic. It also uses Philip Turner's Differentiable, but that's unimportant.
Anyway, when defining the zero variable, I call another variable dimen, defined in the same structure. This raises an error: instance member 'dimen' cannot be used on type 'Electron<T>'
note: the structure I am creating is going to be used to create a multi-dimensional array for neural networks.
Total code (stripped down to remove unimportant bits):
public struct Electron<T> where T: ExpressibleByFloatLiteral, T: AdditiveArithmetic {
var energy: [[Int]: T] = [:]
var dimen: [Int]
public init(_ dim: [Int], with: ElectronInitializer) {
self.dimen = dim
self.energy = [:]
var curlay = [Int](repeating: 0, count: dimen.count)
curlay[curlay.count-1] = -1
while true {
var max: Int = -1
for x in 0..<curlay.count {
if curlay[curlay.count-1-x] == dimen[curlay.count-1-x]-1 {
max = curlay.count-1-x
}
else {break}
}
if max == 0 {break}
else if max != -1 {
for n in max..<curlay.count {
curlay[n] = -1
}
curlay[max-1] += 1
}
curlay[curlay.count-1] += 1
print(curlay)
energy[curlay] = { () -> T in
switch with {
case ElectronInitializer.repeating(let value):
return value as! T
case ElectronInitializer.random(let minimum, let maximum):
return Double.random(in: minimum..<maximum) as! T
}
}()
}
}
subscript(_ coordinate: Int...) -> T {
var convertList: [Int] = []
for conversion in coordinate {
convertList.append(conversion)
}
return self.energy[convertList]!
}
public mutating func setQuantum(_ replace: T, at: [Int]) {
self.energy[at]! = replace
}
}
extension Electron: AdditiveArithmetic {
public static func - (lhs: Electron<T>, rhs: Electron<T>) -> Electron<T> where T: AdditiveArithmetic, T: ExpressibleByFloatLiteral {
var output: Electron<T> = lhs
for value in lhs.energy {
output.energy[value.key] = output.energy[value.key]!-rhs.energy[value.key]!
}
return output
}
public static var zero: Electron<T> {
return Electron.init(dimen, with: ElectronInitializer.repeating(0.0))
}
static prefix func + (x: Electron) -> Electron {
return x
}
public static func + (lhs: Electron<T>, rhs: Electron<T>) -> Electron<T> where T: AdditiveArithmetic, T: ExpressibleByFloatLiteral {
var output: Electron<T> = lhs
for value in lhs.energy {
output.energy[value.key] = output.energy[value.key]!+rhs.energy[value.key]!
}
return output
}
}
public enum ElectronInitializer {
case random(Double, Double)
case repeating(Double)
}
Error:
NeuralNetwork.xcodeproj:59:30: error: instance member 'dimen' cannot be used on type 'Electron'
return Electron.init(dimen, with: ElectronInitializer.repeating(0.0))
I don't know what's happening, but thanks in advance. I'm new to Stack Overflow, so sorry if I did something wrong.
The root of the problem is that dimen is an instance property, while zero is a static property. In a static context, you don't have an instance from which to access dimen, and so the compiler gives you the error. static properties and methods are a lot like global variables and free-functions with respect to accessing instance properties and methods. You'd have to make an instance available somehow. For a static function, you could pass it in, but for a static computed property, you'd either have to store an instance in a stored static property, which isn't allowed for generics, or you'd have to store it in a global variable, which isn't good either, and would be tricky to make work for all the possible T.
There are ways to do what you need though. They all involve implementing some special behavior for a zero Electron rather than relying on access to an instance property in your static .zero implementation. I made some off-the-cuff suggestions in comments, which would work; however, I think a more elegant solution is to solve the problem by creating a custom type for energy, which would require very few changes to your existing code. Specifically you could make an Energy type nested in your Electron type:
internal struct Energy: Equatable, Sequence {
public typealias Value = T
public typealias Key = [Int]
public typealias Element = (key: Key, value: Value)
public typealias Storage = [Key: Value]
public typealias Iterator = Storage.Iterator
public typealias Keys = Storage.Keys
public typealias Values = Storage.Values
private var storage = Storage()
public var keys: Keys { storage.keys }
public var values: Values { storage.values }
public var count: Int { storage.count }
public init() { }
public subscript (key: Key) -> Value? {
get { storage.isEmpty ? .zero : storage[key] }
set { storage[key] = newValue }
}
public func makeIterator() -> Iterator {
storage.makeIterator()
}
}
The idea here is that when energy.storage is empty, it returns 0 for any key, which allows you to use it as a .zero value. I've made it internal, because energy defaults to internal, and so I've done a minimalist job of wrapping a Dictionary, mainly providing subscript operator, and making it conform to Sequence, which is all that is needed by code you provided.
The only changes needed in the rest of your code are to change the definition of energy
var energy: Energy
Then to set it in your initializer, by-passing the bulk of your init when dim is empty.
public init(_ dim: [Int], with: ElectronInitializer) {
self.dimen = dim
self.energy = Energy() // <- Initialize `energy`
// Empty dim indicates a zero electron which doesn't need the
// rest of the initialization
guard dim.count > 0 else { return }
var curlay = [Int](repeating: 0, count: dimen.count)
curlay[curlay.count-1] = -1
while true {
var max: Int = -1
for x in 0..<curlay.count {
if curlay[curlay.count-1-x] == dimen[curlay.count-1-x]-1 {
max = curlay.count-1-x
}
else {break}
}
if max == 0 {break}
else if max != -1 {
for n in max..<curlay.count {
curlay[n] = -1
}
curlay[max-1] += 1
}
curlay[curlay.count-1] += 1
print(curlay)
energy[curlay] = { () -> T in
switch with {
case ElectronInitializer.repeating(let value):
return value as! T
case ElectronInitializer.random(let minimum, let maximum):
return Double.random(in: minimum..<maximum) as! T
}
}()
}
}
And then of course, to change how you create it in your zero property
public static var zero: Electron<T> {
return Electron.init([], with: ElectronInitializer.repeating(0.0))
}
ElectronInitializer isn't actually used in this case. It's just a required parameter of your existing init. This suggests an opportunity to refactor initialization, so you could have an init() that creates a zero Electron in addition to your existing init(dim:with:)

Generic class call function

I am trying to create a wrapper for my API return wrapper class for my project.
these are my classes
class Wrapper<T> {
let message = "Hello World"
let wrapped = T.self
public func getData() -> T.Type {
return wrapped
}
}
class Object {
let number = 100
public func getNumber() -> Int {
return number
}
}
class SecondObject {
let name = "Second Object"
public func getName() -> String {
return name
}
}
What I want to achieve is, is there any way I can call the Object function like this
let example = Wrapper<Object>()
example.getData().getNumber() // <<-- This is not working
let secondExample = Wrapper<SecondObject>()
secondExample.getData().getName() // <<-- This is not working
The error in my playground is this
error: instance member 'getNumber' cannot be used on type 'Object'
If you notice the Wrapper class, there is message property which will be used for all my API return object model
So my goal is, I could simply call the Wrapper class together with my object model class and just call the function that is inside the object model class.
I am still learning about generic in swift. What am I missing here?
You don't set wrapped to anything useful. You ned to set it to an instance of T. So you can pass a Tinto the constructor
class Wrapper<T>
{
let wrapped: T
init(wrapped: T)
{
self.wrapped = wrapped
}
}
Or you can have the class construct an instance of T, but if you want to do that, you need to tell it how to construct the instance. For example:
class Wrapper<T>
{
let wrapped: T
init()
{
self.wrapped = T() // << error!
}
}
won't work because the compiler knows nothing about T, not even if it has an init. You can change that with a protocol
protocol Initable
{
init()
}
class Wrapper<T: Initable>
{
let wrapped: T
init()
{
self.wrapped = T()
}
}
And you can apply the protocol to any type you like with an extension. In most cases the extension can be empty because mot types already have an init() method. For example:
class MyClass
{
init() { /* do stuff */ }
}
extension MyClass: Initable {}
class MyOtherClass
{
init(number: Int) { /* do stuff */ }
}
extension MyOtherClass: Initable
{
init() { self.init(number: 0) }
}
Another option is to supply a closure to the wrapper's init.
class Wrapper<T>
{
let wrapped: T
init(factory: ()-> T)
{
self.wrapped = factory()
}
}
let w = Wrapper() { return Array<Int>() }
Normally you'd only do this if you wanted to create multiple instances i.e. you'd keep a reference to the closure and call it each time you needed a new instance.
class Wrapper<T> {
private var wrapped: T // Storing your object of T type
init(value: T) { // init with instance of T
wrapped = value
}
public func getData() -> T { //returning instance of T
return wrapped
}
}
class Object {
let number = 100
public func getNumber() -> Int {
return number
}
}
let o = Object()
let example = Wrapper(value: o) // Here we creating instance of Wrapper with instance of Object
example.getData().getNumber()
How about this , in your example changing the type of wrapped from non-optional to an optional variable type.
class Wrapper {
let message = "Hello World"
var wrapped : T?
public func getData() -> T? {
return wrapped
}
}
class Object {
let number = 100
public func getNumber() -> Int {
return number
}
}
class SecondObject {
let name = "Second Object"
public func getName() -> String {
return name
}
}
and then using it as below
let example = Wrapper()
example.wrapped = Object()
let result1 = example.getData()?.getNumber() // ()
secondExample.wrapped = SecondObject()
let result2 = secondExample.getData()?.getName()
if let val1 = result1 , let val2 = result2 {
print("result1 = \(val1) result2 = \(val2)" )
}

Conform to Protocol and Keep Property Private

I need to use a protocol property in the conforming class as a private. But the compiler refuses that. How can I implement that?
protocol ProtocolX: class {
var x: Int { get set }
func performAnyActionOnX()
}
extension ProtocolX {
func performAnyActionOnX() {
x = 5
print(x)
}
}
class A: ProtocolX {
private var x:Int = 7
}
Thanks.
As #TheAppMentor mentioned, there seems to be no exact solution to this problem as of Swift 4.
There are, however, two approximate solutions:
1.)
Since a protocol in Swift has the access level of internal by default, make the variable also internal. In order for internal to be enforced by the compiler, move the protocol, the class and all of their consumers (users) to a separate module (framework).
/* internal */ protocol ProtocolX: class {
var x: Any { get set }
func performAnyActionOnX()
}
extension ProtocolX {
func performAnyActionOnX() {}
}
/* internal */ class A: ProtocolX {
internal var x: Any = 0
}
2.)
Give the protocol the access level of private and the variable the access level of fileprivate. In order for the private protocol to be accessible, move the protocol, the class and all of their consumers to the same source file.
private protocol ProtocolX: class {
var x: Any { get set }
func performAnyActionOnX()
}
extension ProtocolX {
func performAnyActionOnX() {}
}
class A: ProtocolX {
fileprivate var x: Any = 0
}
Since protocol's properties always have the same access level as your protocol has you can create a separate class where you can apply fileprivate level to them e.g.:
public class Props {
fileprivate var x: Int = 0
}
public protocol ProtocolX: class {
var privateProps: Props { get }
}
extension ProtocolX {
public func performAnyActionOnX() {
privateProps.x = 5
print(privateProps.x)
}
}
public class A: ProtocolX {
public let privateProps = Props()
public init() {
privateProps.x = 7
}
}
As you can see x has fileprivate access level so it can be accessible in ProtocolX extention and A class implementation only so it behaves as private and you can't change privateProps variable of class A and access to x outside:
let a = A()
a.performAnyActionOnX()
// Prints: 5
let x = a.privateProps.x
// error: 'x' is inaccessible due to 'fileprivate' protection level
There is no the exact solution for your question, by the reason stated in the #TheAppMentor's comment. But there some workarounds which may be helpful if you purpose is to make your code understandable for humans (not to trick the compiler).
Compiles in Swift 4.0.
Solution 1: Python-like __privacy
Fast and simple. This solution relies on the user who would agree that properties and functions starting from _ are private and shouldn't be accessed.
protocol ProtocolX: class {
// Public x
var x: Int { get }
// It's private!
var _x: Int { get set }
func performAnyActionOnX()
}
extension ProtocolX {
var x: Int { return _x }
func performAnyActionOnX(){
_x = 5
print(x)
}
}
class A: ProtocolX {
var _x: Int = 7
}
Solution 2: Additional layer of abstration
Architecturally correct. You should split your protocol on the two parts: private and public.
protocol ProtocolX: class {
var x: Int { get }
func performAnyActionOnX()
}
protocol ProtocolXImplementation: class {
var _x: Int { get set }
}
extension ProtocolXImplementation {
var x: Int { return _x }
func performAnyActionOnX(){
_x = 5
print(x)
}
}
class A: ProtocolX, ProtocolXImplementation {
var _x: Int = 7
}
// ... somewhere later ...
// Hide the implementation when use `A`:
let item: ProtocolX = A()

How do I implement custom operator [] in swift

I have written a simple queue class in swift. It's implemented by an Array.
Now I want this performs more like built-in array.So I need to implement the []operator but failed. Somebody help?
public class SimpleQueue<T : Any>
{
private var frontCur = 0
private var reuseCur = -1
private var capacity = 0
private var impl = [T]()
public var count : Int
{
get
{
return impl.count - frontCur
}
}
public func empty() -> Bool
{
return self.count == 0
}
public func size() -> Int
{
return impl.count
}
public func append(o : T)
{
if(frontCur > reuseCur && reuseCur >= 0)
{
impl[reuseCur] = o
reuseCur++
}
else
{
impl.append(o)
}
}
public func pop()
{
frontCur++
}
public func front() -> T
{
return impl[frontCur]
}
public postfix func [](index:Int) -> T //Error!!!!
{
return impl[index + frontCur]
}
}
var x = SimpleQueue<Int>()
for index in 1...10{
x.append(index)
}
print(x.count)
for index in 1...3{
x.pop()
}
print(x.count,x.front(),x[2]) // x[2] Error!!!
apple docs
Subscripts enable you to query instances of a type by writing one or
more values in square brackets after the instance name. Their syntax
is similar to both instance method syntax and computed property
syntax. You write subscript definitions with the subscript keyword,
and specify one or more input parameters and a return type, in the
same way as instance methods.
Subscript is not an operator. Just a method marked with the subscript keyword.
subscript (index:Int) -> T {
return impl[index + frontCur]
}
Read this:
class MyColl {
private var someColl : [String] = []
subscript(index: Int) -> String {
get {
return someColl[index]
}
set(value) {
someColl[index] = value
}
}
}
And read this:
Swift has a well-designed and expansive suite of built-in collection types. Beyond Array, Dictionary, and the brand new Set types, the standard library provides slices, lazy collections, repeated sequences, and more, all with a consistent interface and syntax for operations. A group of built-in collection protocols—SequenceType, CollectionType, and several others—act like the steps on a ladder. With each step up, a collection type gains more functionality within the language and the standard library.

Swift 2.0 protocol extensions - typealias

I am trying to have a extend a protocol in the following way but I am getting the error: Cannot convert return expression of type typable to typable.
I thought by saying typalias MyType : inside MyType will have to be an entity that conforms to inside
struct typeable<T> {
let value : String = "hello world"
}
protocol inside {
func __myFunction() -> typeable<inside>
}
protocol outside : inside {
typealias MyType : inside
func myFunction() -> typeable<MyType>
}
extension outside {
final func __myFunction() -> typeable<inside> {
return self.myFunction()
}
}
struct thing : outside {
typealias MyType = thing
func myFunction() -> typeable<thing> {
return typeable<thing>()
}
}
Your inside protocol:
protocol inside {
func __myFunction() -> typeable<inside>
}
... requires a function with a return type typeable<inside>, which is not the same as typeable<T> where T: inside. On the other hand, the default implementation of the conforming candidate function in the extension of outside returns a typeable<MyType> where MyType has not been up-casted to inside...
The following code, however, or some variant thereof, may express your intent (as far as I understand it) without tripping up the compiler:
struct Typeable<T> {
init(_: T) {}
}
extension Typeable : CustomStringConvertible {
var description: String { return "I'm a \(self.dynamicType)" }
}
protocol InsideType {
func asTypeableInside() -> Typeable<Self>
}
protocol OutsideType : InsideType {
func asTypeableOutside() -> Typeable<Self>
}
extension OutsideType {
func asTypeableInside() -> Typeable<Self> {
return asTypeableOutside()
}
}
struct Outside {}
extension Outside : OutsideType {
func asTypeableOutside() -> Typeable<Outside> {
return Typeable(self)
}
}
... with following properties:
let o = Outside()
let x = o.asTypeableOutside()
print( o ) // prints: Outside()
print( x ) // prints: I'm a Typeable<Outside>
o is InsideType // always true
x is Typeable<InsideType> // always false
Typeable(o) is Typeable<Outside> // always true
Typeable(o) is Typeable<OutsideType> // always false
Typeable(o) is Typeable<InsideType> // always false
... bearing in mind that:
5 is CustomStringConvertible // always true
Typeable(5) is Typeable<CustomStringConvertible> // always false
It doesn't appear that the typealias MyType : inside within the outside protocol is visible in the outside extension. I was able to get the extension to compile by putting the typealias MyType = inside (note the = rather than :), but that made the thing struct error on compilation.
It's difficult to figure out what you're actually trying to do, more context would be helpful to fully grasp the problem at hand.
In the definition __myFunction in the extension to outside, the uninstantiated type MyType can be of any type which inherits inside, which may be instantiated anywhere outside is implemented. So returning a typeable<inside> as being of typeable<MyType> simply proved to be type mismatch.
You, however, can avoid the error changing the definition a little bit.
struct typeable<T> {
let value : String = "hello world"
}
protocol inside {
typealias MyType
func __myFunction() -> typeable<MyType>
}
protocol outside : inside {
typealias MyType : inside
func myFunction() -> typeable<MyType>
}
extension outside {
final func __myFunction() -> typeable<MyType> {
return self.myFunction()
}
}
struct thing : outside {
typealias MyType = thing
func myFunction() -> typeable<thing> {
return typeable<thing>()
}
}