EDIT: Ok, the responses have helped me figure out the terminology I need to be using to more clearly describe this question. Thank you!
Transitioning from Python to Swift, I'm trying to replicate some educational exercises, and there's a process Python can do with string interpolation that uses a sort of a generic "placeholder" space in a string literal that can be passed a value at a later time.
It would look something like:
color = "purple"
size = "large"
description = "My car is the {} one over there."
print(description.format(color))
print(description.format(size))
and would return:
> My car is the purple one over there.
> My car is the large one over there.
So:
{}
print()
and attaching the format()
function to the sentence variable allows it to pass in another variable to be inserted as a string literal at the "placeholder"For the life of me, I cannot figure out how to replicate this particular method of string interpolation in Swift. In particular, attempting to mimic Python's [EDIT: looks like {}
with \()
isn't allowed,%@
is the answer for that issue] and trying to attach functions to variables in print()
when strings are involved is causing a bunch of different issues depending on what I try.
How can I perform the Python task in Swift? Am I missing something simple and just don't know the terminology [likely] which is making this more difficult than it should be, or is this kind of string interpolation not something that Swift can do?
EDIT 2: Attached snippets of code I'm working with
let hilarious = false
let joke_evaluation = "Isn't that joke so funny?! %@"
print(joke_evaluation)
print(String(format: joke_evaluation, arguments: [hilarious])) // Extra argument 'arguments' in call
struct carStuff {
let color = "red"
let size = "large"
let description = "The %@ car."
init(format: String, arguments: [CVarArg]) // Initializer requires a body
}
print(String(format: carStuff.description, arguments: carStuff.color)) // Extra argument 'arguments' in call
Normally in Swift you can just use String Interpolation \()
. This is just like Python's f-strings.
let color = "purple"
let size = "large"
print("My car is the \(color) one over there.") /// My car is the purple one over there.
print("My car is the \(size) one over there.") /// My car is the large one over there.
That should be fine for most cases. But if you want an explicit placeholder, check out init(format:_:)
.
let color = "purple"
let size = "large"
let description = "My car is the %@ one over there."
print(String(format: description, color)) /// My car is the purple one over there.
print(String(format: description, size)) /// My car is the large one over there.
Use %@
for String
values like color
. Here's the full list of placeholders, in case you want format an Int
or something else.
Your first code snippet compiles fine for me. However, %@
only supports String
and other objects that bridge to obj-c — Bool
s like hilarious
don't work. You need to convert it to a String
first.
let hilarious = false
let joke_evaluation = "Isn't that joke so funny?! %@"
print(String(format: joke_evaluation, arguments: [String(hilarious)])) /// Need to convert `hilarious` to a String first
Result:
Isn't that joke so funny?! false
Your second code snippet has a couple problems. I think you might be confusing Apple structs like String
with custom, made-by-you structs like CarStuff
. But anyway, if you want to make your own struct CarStuff
(again, why?), here's how:
carStuff
is a struct, so it should be capitalized to CarStuff
(just good conventions).init()
is called. See the docs for more information.init(format: String, arguments: [CVarArg])
, doesn't have a body. This is a syntax error - you need the curly braces {}
.init(format: String, arguments: [CVarArg])
? The properties of CarStuff
are color
, size
, and description
. What does format
and arguments
have to do with those? Remember: The purpose of an initializer is to initialize all of the struct's properties.init(format: String, arguments: [CVarArg]) {
/**
initialize the struct's properties here.
but, you already provided default values to the properties...
... for example, `let color = "red"`
so you don't even need your custom init — Swift does it automatically for you.
And besides, what is `format` and `arguments` for?
Just remove this `init` entirely.
*/
}
Anyway, all of that was just some extra info, not really related to your original question. The real problem is that there are 2 very similar String
initializers:
The first one requires you to pass in an Array
. The second one takes in a variadic number of parameters, so you can just directly pass in your variable to be substituted.
struct CarStuff {
let color = "red"
let size = "large"
let description = "The %@ car."
}
let carStuff = CarStuff() /// initialize a `CarStuff` (using Swift's auto-generated initializer)
print(String(format: carStuff.description, arguments: [carStuff.color])) // init(format:arguments:) requires an array
print(String(format: carStuff.description, carStuff.color)) // init(format:_:) lets you omit `arguments` and directly pass in your arguments
Result:
The red car.
The red car.