This question already has answers here:
How to set and get fields in struct's method
(3 answers)
Assign a new value to a struct field
(2 answers)
Struct field reverts [duplicate]
(1 answer)
Closed 5 years ago.
I'm just starting out with Go and I'm having a hard time saving data in a struct. Coming from other languages I learned there is no such thing as a class in Go. For similar purposes, the struct can be used, and functions can be "added" to the struct. So I wrote the following simple program:
package main
import "fmt"
type MyStruct struct {
the_number int
}
func (self MyStruct) add(another_number int) int {
self.the_number += another_number // I save the result to the struct the_number
return self.the_number
}
func main() {
my_struct := MyStruct{1}
result := my_struct.add(2)
fmt.Println(result) // prints out 3 as expected
fmt.Println(my_struct.the_number) // prints out 1. Why not also 3?
}
As you can see from the comments I'm puzzled by the fact that the result is not saved in self.the_number in the instantiated my_struct.
So I found out I can get around this by doing
my_struct.the_number = my_struct.add(2)
But I methods/functions can sometimes become complex in which I want to save a lot of data to the my_struct from within the function.
Could any smarter soul than me give me a tip on what I'm missing here?
How can I save data to an instantiated struct from within a function?
You should use pointer in struct method func (self *MyStruct) add(another_number int) int as without the * variable (self) is passed by value, not by references. E.g. you are updating a copy of an original object and this changes are discarded.
It's a basic stuff and well covered in Tour of Go - everyone should take it before starting coding in Go.
Another option would be return the self from the method - it would follow "immutable" style so you can write code like: my_struct = my_struct.add(1).add(2)
package main
import "fmt"
type MyStruct struct {
the_number int
}
func (self *MyStruct) add(another_number int) int {
self.the_number += another_number
return self.the_number
}
func main() {
my_struct := MyStruct{1}
result := my_struct.add(2)
fmt.Println(result) // prints out 3 as expected
fmt.Println(my_struct.the_number) // prints out 1. Why not also 3?
}
Related
This question already has answers here:
How to compare "Any" value types
(7 answers)
Closed 20 days ago.
I have implemented a linked list in Swift. Code that uses this data structure can append, insert, etc., a new node into the list by providing an element of the generic type. In other words, the list holds nodes and each node holds a reference or instance of the type, and callers simply pass the T type element to insert into the list (not wasting lines of code creating a node they don't need to know about). Here are some pieces of the code defining the linked list (with tons of irrelevant stuff removed):
public class LinkedListNode<T> {
init( value: T ) {
self.value = value
}
public var next: LinkedListNode?
public weak var previous: LinkedListNode?
public var value: T
}
struct LinkedList<T>: Sequence {
internal var head: LinkedListNode<T>?
internal unowned var tail: LinkedListNode<T>?
#discardableResult public mutating func insert( _ value: T, after: LinkedListNode<T> ) -> LinkedListNode<T> {
if after === tail {
return append( value )
} else {
let node = LinkedListNode<T>( value: value )
insertBetween( node, after: after, before: after.previous )
return node
}
}
...
}
This all works great. I only had a medium amount of trouble finding documentation that explained how to make the Sequence protocol work right.
Now I want to add a function to add or replace an element in the list. I want the caller to pass in something of type T and I want to check to see if it exists so it can be replaced. I want to add the new element if it doesn't already exist. The problem is that I want to compare two T types to see if they are the same instance of an object of the list has objects in it (within the nodes) but compare for content equality if the list has structs or just native types like Int, within it.
I can do this outside of the linked list code because I have a first() function. Maybe that's a better choice. But I would still like to know if it's possible to write code that let's me do an appropriate equality test depending on the type of thing that the list contains.
This is what I was working on when I got to this problem:
#discardableResult public mutating func replaceOrAppend( _ value: T ) -> LinkedListNode<T> {
var node = first( where: { $0.value === value } )
if node == nil {
node = LinkedListNode<T>( value: value )
insertBetween( node!, after: tail, before: tail?.next )
tail = node
}
return node!
}
Notice that I used === for the comparison. Unless I define T as T:AnyObject, this will fail to compile. I want this to work to compare the content of structs and native types and the references for class objects.
Not all things can be compared for equality. Functions are a great example of this. If I have a LinkedList<() -> Void>, and I want to replaceOrAppend another () -> Void to it, how can you tell if the new function "already exists" in the linked list? Figuring that out would at least require solving the halting problem. :D
A better design would be to only have replaceOrAppend be available when T is Equatable:
extension LinkedList where T: Equatable {
// I've rewritten this to eliminate the "!"
#discardableResult public mutating func replaceOrAppend( _ value: T ) -> LinkedListNode<T> {
// now you can use "==", because T is known to be Equatable
if let node = first( where: { $0.value == value } ) {
return node
} else {
let newNode = LinkedListNode<T>( value: value )
insertBetween( newNode, after: tail, before: tail?.next )
tail = newNode
return newNode
}
}
}
The problem is that I want to compare two T types to see if they are the same instance of an object of the list has objects in it (within the nodes) but compare for content equality if the list has structs or just native types like Int, within it.
I don't think you should have this distinction. I would suggest you just use ==.
It's pretty unusual to have objects only be considered equal when they're exactly equal. If you callers did want that, they would implement Equatable/== to achieve that, or stuff it in a wrapper like the IdentityWrapper in this example here.
I drank the struct/value koolaid in Swift. And now I have an interesting problem I don't know how to solve. I have a struct which is a container, e.g.
struct Foo {
var bars:[Bar]
}
As I make edits to this, I create copies so that I can keep an undo stack. So far so good. Just like the good tutorials showed. There are some derived attributes that I use with this guy though:
struct Foo {
var bars:[Bar]
var derivedValue:Int {
...
}
}
In recent profiling, I noticed a) that the computation to compute derivedValue is kind of expensive/redundant b) not always necessary to compute in a variety of use cases.
In my classic OOP way, I would make this a memoizing/lazy variable. Basically, have it be nil until called upon, compute it once and store it, and return said result on future calls. Since I'm following a "make copies to edit" pattern, the invariant wouldn't be broken.
But I can't figure out how to apply this pattern if it is struct. I can do this:
struct Foo {
var bars:[Bar]
lazy var derivedValue:Int = self.computeDerivation()
}
which works, until the struct references that value itself, e.g.
struct Foo {
var bars:[Bar]
lazy var derivedValue:Int = self.computeDerivation()
fun anotherDerivedComputation() {
return self.derivedValue / 2
}
}
At this point, the compiler complains because anotherDerivedComputation is causing a change to the receiver and therefore needs to be marked mutating. That just feels wrong to make an accessor be marked mutating. But for grins, I try it, but that creates a new raft of problems. Now anywhere where I have an expression like
XCTAssertEqaul(foo.anotherDerivedComputation(), 20)
the compiler complains because a parameter is implicitly a non mutating let value, not a var.
Is there a pattern I'm missing for having a struct with a deferred/lazy/cached member?
Memoization doesn't happen inside the struct. The way to memoize is to store a dictionary off in some separate space. The key is whatever goes into deriving the value and the value is the value, calculated once. You could make it a static of the struct type, just as a way of namespacing it.
struct S {
static var memo = [Int:Int]()
var i : Int
var square : Int {
if let result = S.memo[i] {return result}
print("calculating")
let newresult = i*i // pretend that's expensive
S.memo[i] = newresult
return newresult
}
}
var s = S(i:2)
s.square // calculating
s = S(i:2)
s.square // [nothing]
s = S(i:3)
s.square // calculating
The only way I know to make this work is to wrap the lazy member in a class. That way, the struct containing the reference to the object can remain immutable while the object itself can be mutated.
I wrote a blog post about this topic a few years ago: Lazy Properties in Structs. It goes into a lot more detail on the specifics and suggest two different approaches for the design of the wrapper class, depending on whether the lazy member needs instance information from the struct to compute the cached value or not.
I generalized the problem to a simpler one: An x,y Point struct, that wants to lazily compute/cache the value for r(adius). I went with the ref wrapper around a block closure and came up with the following. I call it a "Once" block.
import Foundation
class Once<Input,Output> {
let block:(Input)->Output
private var cache:Output? = nil
init(_ block:#escaping (Input)->Output) {
self.block = block
}
func once(_ input:Input) -> Output {
if self.cache == nil {
self.cache = self.block(input)
}
return self.cache!
}
}
struct Point {
let x:Float
let y:Float
private let rOnce:Once<Point,Float> = Once {myself in myself.computeRadius()}
init(x:Float, y:Float) {
self.x = x
self.y = y
}
var r:Float {
return self.rOnce.once(self)
}
func computeRadius() -> Float {
return sqrtf((self.x * self.x) + (self.y * self.y))
}
}
let p = Point(x: 30, y: 40)
print("p.r \(p.r)")
I made the choice to have the OnceBlock take an input, because otherwise initializing it as a function that has a reference to self is a pain because self doesn't exist yet at initialization, so it was easier to just defer that linkage to the cache/call site (the var r:Float)
If the postfix operator of a custom function is declared at file scope - as in my previous post - there must be a way to access such a function from another Swift 3 file in the same Xcode project.
Apple’s documentation on custom functions states that “New operators are declared at a global level …“ so I can presume the creators of Swift 3 would consider it important for a custom function to be accessed globally. But for a novice in Swift it is not self-evident how I would do this.
Based on code in my previous accepted answer (here) what would I need to do so a custom function can be accessed from another file elsewhere in the project ?
FINAL EDIT
The solution is embarrassingly simple (see accepted answer) and hopefully other Swift novices may also find it useful.
A postfix operator % is declared globally while an Extension of Int reads an Int variable from another file. Extensions of Double and CGFloat as well as Int are also possible.
CustomOperators.swift
import UIKit
postfix operator %
extension Double {
static postfix func % (n: Double) -> Double {
return Double(n) / 100
}
}
extension Int {
static postfix func % (n: Int) -> Double {
return Double(n) / 100
}
}
extension CGFloat {
static postfix func % (n: CGFloat) -> Double {
return Double(n) / 100
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
let test1: Double = 93.7
let test2: Int = 80
let test3: CGFloat = 70
override func viewDidLoad() {
super.viewDidLoad()
print(test1%) // prints '0.937'
print(test2%) // prints '0.8'
print(test3%) // prints '0.7'
}
}
Thanks marosoiae, and also Martin R and unniversal for your input.
EDIT 2
Martin R’s comments prompted me to try a further example with my custom postfix function defined in Utils but in file scope rather than as a static postfix function. Utils becomes an empty class for custom functions all defined in file scope outside the class.
import UIKit
class ViewController: UIViewController {
let value: Int = 25
override func viewDidLoad() {
super.viewDidLoad()
example1()
example2()
}
func example1() {
// 1. call to a function in Utils with an explicit value
// and nothing returned from Utils.
// Note this uses literal postfix syntax i.e. 25%
Utils.25%
// Debug message:
// Type 'Utils' has no member '25'
}
func example2() {
// 2. call to a function in Utils with an argument
// declared in UIViewController and nothing returned from Utils
Utils.(Int: value)%
// Debug message
// Expected member name following '.'
}
}
Utils.swift now compiles but from debug messages that Xcode reports with both examples, it is clear that the token '%' is expected immediately following the '.'.
Even without returning a variable from Utils.swift, this is obviously not how to call a postfix function in Utils.swift from a file elsewhere in the project. My question remains: how would I do it ?
EDIT 1
At this point it might help to include some code so I created a class with static functions, following the syntax (as far as possible) used in Unniversal's answer. I decided to try static functions if these help avoid cluttering the global scope with methods that should be owned by a class/struct.
File 1 - Utils
import UIKit
postfix operator %
class Utils {
static func yourFunction(){
//Do your stuff here
}
static func yourFunction1(value: Int) {
print(value)
}
static postfix func % (percentage: Int) -> Double {
return (Double(percentage) / 100)
}
}
The static function % reports
Member operator '%' must have at least one argument of type 'Utils'
which I’d expect to disappear once an argument is supplied from another file.
The following code shows four ways I tried to supply an argument to static functions in Utils. I ran the project with one example at a time
File 2 - UIViewController
import UIKit
class ViewController: UIViewController {
let value: Int = 25
var percentage = Double()
override func viewDidLoad() {
super.viewDidLoad()
// example1()
// example2()
// example3()
// example4()
}
func example1() {
// 1. call to a function in Utils with no argument and no return (i.e. suggested answer)
Utils.yourfunction()
// Debug messages:
// Type 'Utils' has no member 'yourfunction'
// Did you mean 'yourFunction'?
// Did you mean 'yourFunction1'?
}
func example2() {
// 2. call to a function in Utils with argument and no return
Utils.yourfunction1(Int: Int)
// Debug messages:
// Type 'Utils' has no member 'yourfunction'
// Did you mean 'yourFunction'?
// Did you mean 'yourFunction1'?
}
func example3() {
// 3. call to a function in Utils with argument and returning a value for percentage
Utils.%() {
return Int(percentage)
}
// Debug message:
// Use of unresolved operator '.%'
}
func example4() {
// 4. call to a function in Utils with argument and returning a value for percentage
percentage = Utils.%(Int: value) -> Int {
return Int(percentage)
}
// Debug messages:
// Use of unresolved operator '.%'
// Expected type before '->'
// Expected type after '->'
}
}
As far as I can see, static functions Utils.yourFunction and Utils.yourFunction1 can’t be accessed from outside Utils, as shown in example 1 and 2. And the postfix operator % seems to cause Xcode to report Use of unresolved operator ‘.%’, as shown in example 3 and 4. However these problems might be the way I adapted the syntax used by Unniversal.
Any function declared at file scope will have the implicit scope internal and will be visible in the rest of the project/module.
I recommend reading the access control guide for more information.
Edit:
I'm still not sure what you're trying to do, but it looks like you are mixing global functions with static methods and custom operators.
If what you want is to declare a custom operator that you can use in any other file in the project, the solution is in the documentation that you linked in your question.
So this is what you need to declare a custom % (as you defined it) for the Int type:
CustomOperators.swift
postfix operator %
extension Int {
static postfix func % (n: Int) -> Double {
return Double(n) / 100
}
}
main.swift
print(90%) //outputs "0.9"
That's all there is to it. You simply declare the operator globally: postfix operator % and you define the operator function as a static method in a extension on the Int type.
Now you can use your new operator in other files (like I did in main.swift).
If you want a function to be accessed globally I would recommend to create a class that has static functions. For example
class Utils {
static func yourFunction(){
//Do your stuff here
}
}
To use it :
Utils.yourfunction()
This question already has answers here:
Cannot assign property in method of struct
(2 answers)
Closed 7 years ago.
Can someone please tell me how I am failing here?
I have a Struct called cardView, in which I predefine an option called currentIndex and define it as an Integer.
When I from a function inside my struct try to add to currentIndex I get a compiler error as the topic says.
Here's how it looks:
struct cardView {
var currentIndex: Int = 0
func addToIndex() {
currentIndex++
}
}
The cardView struct and function is initialized from my viewController.
You can change struct variables from outside of that struct, but not from within its own functions, you need to add the keyword mutating before fun.
struct cardView {
var currentIndex: Int = 0
mutating func addToIndex() {
currentIndex++
}
}
The method is changing the internal status, so it must be declared as mutating:
mutating func addToIndex() {
^^^^^^^^
Note that this is needed for value types only - classes don't need it, as you can see by just turning the structure into a class.
Calling a method from its name (in a String format) can be sometimes useful.
In Swift it is recomended to change behavior and to use closures to do something "dynamically", so for example you can have a dictionary of functions, with the name as the key, and the implementation as the value.
However, sometimes you want to simply know "how to do it", and this is the reason of this question.
So, how to call dynamically a Swift method starting from it's name as string?
In Objective C it was simple:
[self performSelector:NSSelectorFromString(#"aSelector")];
But performSelector is banned in Swift
Is there any alternative?
In Swift, you should use closures and change your approach.
However, if you want to use performSelector to dynamically call a method given only it's String signature, altough it's not supported natively, I've found how to do it.
It is possible to create a C alternative to performSelector that:
works even on native swift classes (non objective-c)
takes a selector from string
However it's not so straightforward to implement a complete version of it, and it's necessary to create the method in C.
in C we have dlsym(), a function that returns a pointer to a function given the char symbol.
Well, reading this interesting post:
http://www.eswick.com/2014/06/inside-swift/
I've learned a lot of interesting things about swift.
Swift instance methods are plain functions with a specific signature, like this
_TFC14FirstSwiftTest12ASampleClass13aTestFunctionfS0_FT_CSo8NSString
where the "self" value is passed as the last parameter
in short you can call it directly from the c side without any kind of bridging, it is sufficient to rebuild the correct function signature.
In the signature above, there is the name of the project (FirstSwiftTest) and the lenght (14), the name of the class (ASampleClass) and the lenght (12), the name of the function (aTestFunction) and the lenght (13), then other values as the return type ecc ecc. For other details look at the previous link
The function above, is the representation of this:
class ASampleClass
{
func aTestFunction() -> NSString
{
println("called correctly")
return NSString(string: "test")
}
}
Well, on the c side, I was able to create this function
#include <stdio.h>
#include <dlfcn.h>
typedef struct objc_object *id;
id _performMethod(id stringMethod, id onObject)
{
// ...
// here the code (to be created) to translate stringMethod in _TFC14FirstSwiftTest12ASampleClass13aTestFunctionfS0_FT_CSo8NSString
// ...
id (*functionImplementation)(id);
*(void **) (&functionImplementation) = dlsym(RTLD_DEFAULT, "_TFC14FirstSwiftTest12ASampleClass13aTestFunctionfS0_FT_CSo8NSString");
char *error;
if ((error = dlerror()) != NULL) {
printf("Method not found \n");
} else {
return functionImplementation(onObject); // <--- call the function
}
return NULL
}
And then called it on the swift side
let sampleClassInstance = ASampleClass()
println(_performMethod("aTestFunction", sampleClassInstance))
The function resulted in these statement printed on the log:
called correctly
test
So it should be not so difficult to create a _performMethod() alternative in C that:
creates automatically the function signature (since it seems to have a logic :-)
manages different return value types and parameters
EDIT
In Swift 2 (and maybe in Beta3, I didn't try) It seems that performSelector() is permitted (and you can call it only on NSObject subclasses). Examining the binary, It seems that now Swift creates static functions that can be specifically called by performSelector.
I created this class
class TestClass: NSObject {
func test() -> Void {
print("Hello");
}
}
let test = TestClass()
let aSel : Selector = NSSelectorFromString("test")
test.performSelector(aSel)
and now in the binary I find
000000010026d830 t __TToFC7Perform9TestClass4testfT_T_
At this time, I don't understand well the reasons behind this, but I'll investigate further
You could call a method from a String this way:
let foo = <some NSObject subclass instance>
let selectorName = "name"
foo.perform(Selector(selectorName))
It is available only when your foo class is subclass of NSObject
swift3 version
class MyClass:NSObject
{
required public override init() { print("Hi!") }
public func test(){
print("This is Test")
}
public class func static_test(){
print("This is Static Test")
}
}
if let c: NSObject.Type = NSClassFromString("TestPerformSelector.MyClass") as? NSObject.Type{
let c_tmp = c.init()
c_tmp.perform(Selector("test"))
c.perform(Selector("static_test"))
}