DaveS
(remove this account)
April 13, 2021, 5:23pm
1
In another langage I used in the past there was a very handy feature
Sub myRoutine(somevar as String, assigns new_value as string)
newValue=somevar + new_value
End Sub
which would be used like this
myRoutine("foo")="bar"
with the result being "foobar"
I have tried to come up with some func/class/structure that would allow me to replicate this.
The best option would be Computed Property where you could pass arguments
var myRoutine(somevar : String) : String {
get { return backingStore }
set { backingStore = "\(somevar)\(newValue)"
}
Jumhyn
(Frederick Kellison-Linn)
April 13, 2021, 5:31pm
2
"Computed Property where you could pass arguments" is, roughly, a custom subscript
:
struct S {
private var store: [String: String] = [:]
subscript(_ key: String) -> String {
get { return store[key] ?? "" }
set { store[key] = key + newValue }
}
}
var s = S()
s["foo"] = "bar"
print(s["foo"]) // 'foobar'
Does that accomplish what you're trying to do?
DaveS
(remove this account)
April 13, 2021, 5:41pm
3
Well, yes and no... that would work in the exact example I provided
but not when the func has a more complex signature
var myRoutine(var1 : String, var2 : Int, var3 : Double) : String {
get { return <something> }
set { < do something with var1, var2, var3 AND newValue )
}
subscript(var1 : String, var2 : Int, var3 : Double) -> String {
get { return <something> }
set { < do something with var1, var2, var3 AND newValue )
}
but it DOES seem you can have the above signature... so THAT might work
1 Like
Jumhyn
(Frederick Kellison-Linn)
April 13, 2021, 5:45pm
4
Yep, it's perfectly valid for subscripts to take multiple arguments!
DaveS
(remove this account)
April 13, 2021, 5:47pm
5
Thanks let me experiment.... would be nice if I didn't have to create a structure, then an instance of it.
This is part of a project to actually translate code from That other language into Swift... and that ONE feature has so far been a sticking point... I have 95% of the rest working
DaveS
(remove this account)
April 13, 2021, 10:00pm
6
Looks like this syntax will work in my Translator
Before
Sub myRoutine(var1 as String, var2 as Double, assigns Xyz as integer)
// do stuff
End sub
After
var myRoutine = _myRoutine()
struct _myRoutine {
subscript(_ var1: String,_ var2 : Double) -> Int? {
get { return nil }
set { var xyz = newValue!
// do stuff
}
}
}
Jon_Shier
(Jon Shier)
April 13, 2021, 10:03pm
7
Seems like a good use for callAsFunction
.
DaveS
(remove this account)
April 13, 2021, 10:10pm
8
not familiar... can you provide a simple example?
Jon_Shier
(Jon Shier)
April 13, 2021, 10:16pm
9
struct Appender {
var value = "initialValue "
mutating func callAsFunction(_ string: String) {
value = value + string
}
}
var appender = Appender()
appender("secondValue")
print(appender.value) // Prints "initialValue secondValue"
You can read more around the internet, like this post .
DaveS
(remove this account)
April 13, 2021, 10:19pm
10
thanks but that doesn't meet the requirement of having the "newValue" on the right of the assignment
the required syntax would need to end up
appender = "secondvalue"
note that any use would be a non-value returning function
hooman
(Hooman Mehr)
April 13, 2021, 10:57pm
11
You can also use a static subscript to eliminate instantiation:
enum myRoutine {
static subscript(_ var1: String,_ var2 : Double) -> Int? {
get { return nil }
set { var xyz = newValue!
// do stuff
}
}
}
DaveS
(remove this account)
April 13, 2021, 10:58pm
12
Thanks, I will try that variation as well...
DaveS
(remove this account)
April 14, 2021, 12:14am
13
Seems like that works :)
BASIC code going into my Translator *
private Sub myRoutine(var1 as String, var2 as Double, assigns Xyz as integer)
var x as integer =3
print(x)
End sub
Swift code coming out
import Cocoa
private enum myRoutine {
subscript(_ var1 : String , _ var2 : Double) -> Int? {
get { return nil }
set { let Xyz = newValue!
let x : Int = 3
print(x)
}
}
}
DaveS
(remove this account)
April 14, 2021, 12:15am
14
THANKS... the took my translator another major step forward
DaveS
(remove this account)
April 14, 2021, 1:12am
15
Enum version doesn't work.... cannot assign values
but Struct version seems to
Jon_Shier
(Jon Shier)
April 14, 2021, 1:27am
16
You can use the enum
in the static case, as it ensures you canβt creat an instance. They donβt have mutable instance properties.
DaveS
(remove this account)
April 15, 2021, 12:36am
17
Well this works except inside an Extension, any ideas? or cannot it not be done?
extension String {
struct myRoutine {
subscript (_ var2 : String) -> Int? {
get { return nil }
set { let Xyz = newValue!
let x : Int = 3
print("\(Xyz) \(x) \(self)")
}
}
}
}
func test() {
print("test")
var s : String = ""
s.myRoutine["A"] = 3 // <--------------- ERROR
// Instance member 'subscript' cannot be used on type 'String.myRoutine'
// Static member 'myRoutine' cannot be used on instance of type 'String'
}
// Defining as a FUNC replacement only, works just fine
private var myRoutine2 = _myRoutine2()
struct _myRoutine2 {
subscript (_ var1 : String ,_ var2 : String) -> Int? {
get { return nil }
set { let Xyz = newValue!
let x : Int = 3
print("\(Xyz) \(x) \(var1) \(var2)")
}
}
}
func test2() {
print("test2")
myRoutine2["A" , "B"] = 3
}
Which do you want: s.myRoutine["A"] = 3
(where s: String
), String.myRoutine["A"] = 3
or myRoutine["A"] = 3
?
Your first example fails because you are defining something which would be used as: String.myRoutine()["A"] = 3
and calling it as s.myRoutine["A"] = 3
DaveS
(remove this account)
April 15, 2021, 4:16am
19
well I wanted
s.myRoutine["A"] = 3
which I guess doesn't work, as the Struct needs to be instantiated
sveinhal
(Svein Halvor Halvorsen)
April 15, 2021, 12:49pm
20
You can do either this:
extension String {
subscript (myRoutine var2: String) -> Int? {
get { return nil }
nonmutating set { print("\(self) \(var2) \(newValue!)") }
}
}
func test1() {
let s = "B"
s[myRoutine: "A"] = 3
}
test1() // prints B A 3
Or this:
extension String {
struct _MyRoutine {
var parent: String
subscript (_ var2: String) -> Int? {
get { return nil }
nonmutating set { print("\(parent) \(var2) \(newValue!)") }
}
}
var myRoutine: _MyRoutine { _MyRoutine(parent: self) }
}
func test2() {
let s = "B"
s.myRoutine["A"] = 3
}
test2() // prints B A 3