Print in Swift 3 - swift

i would like to know what's the different between these two way to print the object in Swift.
The result seems identical.
var myName : String = "yohoo"
print ("My name is \(myName).")
print ("My name is ", myName, ".")

There is almost no functional difference, the comma simply inputs a space either before or after the string.
let name = "John"
// both print "Hello John"
print("Hello", name)
print("Hello \(name)")

You can use the \(variable) syntax to create interpolated strings, which are then printed just as you input them. However, the print(var1,var2) syntax has some "facilities":
It automatically adds a space in between each two variables, and that is called separator
You can customise your separator based on the context, for example:
var hello = "Hello"
var world = "World!"
print(hello,world,separator: "|") // prints "Hello|World!"
print(hello,world,separator: "\\//") // prints "Hello\\//World!"

No difference between the two
var favoriteFood: String = "Pizza" //favoriteFood = Pizza
//both print the same thing
print("My favorite food is", favoriteFood)
print("My favorite food is \(favoriteFood)")

Related

Access an optional capture by name when using Swift Regex Builder

I'm just getting started with regular expressions and Swift Regex, so a heads up that my terminology my be incorrect. I have boiled this problem down to a very simple task:
I have input lines that have either just one word (a name) or start with the word "Test" followed by one space and then a name. I want to extract the name and also be able to access - without using match indices - the match to "Test " (which may be nil). Here is code that better describes the problem:
import RegexBuilder
let line1 = "Test John"
let line2 = "Robert"
let nameReference = Reference(String.self)
let testReference = Reference(String.self)
let regex = Regex {
Optionally {
Capture(as:testReference) {
"Test "
} transform : { text in
String(text)
}
}
Capture(as:nameReference) {
OneOrMore(.any)
} transform : { text in
String(text)
}
}
if let matches = try? regex.wholeMatch(in: line1) { // USE line1 OR line2 HERE
let theName = matches[nameReference]
print("Name is \(theName)")
// using index to access the test flag works fine for both line1 and line2:
if let flag = matches.1, flag == "Test " {
print("Using index: This is a test line")
} else {
print("Using index: Not a test line")
}
// but for line2, attempting to access with testReference crashes:
if matches[testReference] == "Test " { // crashes for line2 (not surprisingly)
print("Using reference: This is a test line")
} else {
print("Using reference: Not a test line")
}
}
When regex.wholeMatch() is called with line1 things work as expected with output:
Name is John
Using index: This is a test line
Using reference: This is a test line
but when called with line2 it crashes with a SIGABRT and output:
Name is Robert
Using index: Not a test line
Could not cast value of type 'Swift.Optional<Swift.Substring>' (0x7ff84bf06f20) to 'Swift.String' (0x7ff84ba6e918).
The crash is not surprising, because the Capture(as:testReference) was never matched.
My question is: is there a way to do this without using match indices (matches.1)? An answer using Regex Builder would be much appreciated:-)
The documentation says Regex.Match has a subscript(String) method which "returns nil if there's no capture with that name". That would be ideal, but it works only when the match output is type AnyRegexOutput.
I don't think you can get away with not using indexes, or at least code that knows the index but might hide it. Regular expression parsing works like that in any language, because it's always assumed that you know the order of elements in the expression.
For something like this, your example could be simplified to something like
let nameRegex = Regex {
ZeroOrMore("Test ")
Capture { OneOrMore(.anyNonNewline) }
}
if let matches = try? nameRegex.wholeMatch(in: line2) {
let (_, name) = matches.output
print("Name: \(name)")
}
That works for both of your sample lines. The let (_, name) doesn't use a numeric index but it's effectively the same thing since it uses index 1 as the value for name.
If your data is as straightforward as these examples, a regular expression may be overkill. You could work with if line1.hasPrefix("Test ") to detect lines with Test and then drop the first 5 characters, for example.

Swift NSAlert() argument print string with spaces

How do a print the array below to display the full string?
alert.informativeText = CommandLine.arguments[4]
This prints fine if it's one word. Argument Test
Test
However if the argument is This Is A Test. It still prints just the first word:
Test
Full Code:
CommandLine.arguments[1]{
func dialogOKCancel(title: String) -> Bool
{
let alert = NSAlert()
alert.informativeText = CommandLine.arguments[4]
alert.alertStyle = NSAlert.Style.warning
alert.addButton(withTitle: "Dismiss")
return alert.runModal() == NSApplication.ModalResponse.alertFirstButtonReturn
}
_ = dialogOKCancel(title: "")
The space character is the argument separator in the command line.
You have to quote the string
/path/to/executable 'This is A Test'
or to escape
/path/to/executable This\ is\ A\ Test
the spaces in the string when calling the executable.
Command line arguments are always split with spaces. Although "This Is A Test" might look like a single argument, it is four arguments - "This", "Is", "A" and "Test".
What you are trying to do seems to be printing all the arguments. In that case, you should drop the first element of CommandLine.arguments (that's the command itself) and then join the strings:
alert.informativeText = CommandLine.arguments.dropFirst().joined(separator: " ")

swift why is characters.split used for? and why is map(String.init) used for

import Foundation
for i in 1 ... n {
let entry = readLine()!.characters.split(" ").map(String.init)
let name = entry[0]
let phone = Int(entry[1])!
phoneBook[name] = phone``
}
//can someone explain this piece of code`
I assume you know everything else in the code except this line:
let entry = readLine()!.characters.split(" ").map(String.init)
readLine() reads user input and returns it. Let's say the user input is
Sweeper 12345678
using .characters.split(" "), we split the input using a separator. What is this separator? A space (" ")! Now the input has been split into two - "Sweeper" and "12345678".
We want the two split parts to be strings, right? Strings are much more easier to manipulate. Currently the split parts are stored in an array of String.CharacterView.SubSequence. We want to turn each String.CharacterView.SubSequence into a string. That is why we use map. map applies a certain function to everything in a collection. So
.map(String.init)
is like
// this is for demonstration purposes only, not real code
for x in readLine()!.characters.split(" ") {
String.init(x)
}
We have now transformed the whole collection into strings!
There is error in your code replace it like below:
let entry = readLine()!.characters.split(separator: " ").map(String.init)
Alternative to the above code is:
let entry = readLine()!.components(separatedBy: " ")
Example:
var str = "Hello, playground"
let entry = str.characters.split(separator: " ").map(String.init)
print(entry)
Now characters.split with split the characters with the separator you give in above case " "(space). So it will generate an array of characters. And you need to use it as string so you are mapping characters into String type by map().

String replacement not working with Dictionary

I have a mini dictionary that I would like to use in order to replace occurrences of text within a user's inputted string. However, instead of replacing every occurrence of a particular string, it retains the original string. For example, user types:
"The girl went to school"
My program still returns "The girl went to school". It should come out as "The binguel debbo went to jangirde"
func input() -> String {
let keyboard = NSFileHandle.fileHandleWithStandardInput()
let inputData = keyboard.availableData
return (NSString(data: inputData, encoding:NSUTF8StringEncoding)?.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet()))! as! String
}
var userInput = "" //Declares original user input
var finalSentence:String = "" //Declares a string variable for the final sentence
var newUserString:String
var fulfuldeWords = ["man":"gorko", "woman":"debbo",
"boy":"binguel gorko", "girl": "binguel debbo", "work":"golle",
"school":"jangirde", "water":"ndiyam", "horse":"puccu", "cow":"na'i",
"hat":"hufunere", "house":"wuro", "courage":"cuusal", "camel":"gelodi",
"milk":"kossam"
]
print("Please enter a sentence to be partially translated: ") //Ask user for input
userInput = input()
var theStringArray = userInput.componentsSeparatedByString(" ")
for (englishWord, fulaniWord) in fulfuldeWords {
finalSentence = userInput.stringByReplacingOccurrencesOfString(englishWord, withString: fulaniWord)
}
print(finalSentence)
This is being done in Swift and I don't get why it's not working. Where did I go wrong in my code. Thanks!
You need to perform the function stringByReplacingOccurencesOfString on the same variable to get your desired result. So, in your code, store the result on userInput and print as the output as well.
for (englishWord, fulaniWord) in fulfuldeWords {
userInput = userInput.stringByReplacingOccurrencesOfString(englishWord, withString: fulaniWord)
}
print(userInput)

How does this Play 2 ScalaTemplates code work

Please explain the code below:
#title(text: String) = #{
text.split(' ').map(_.capitalize).mkString(" ")
}
<h1>#title("hello world")</h1>
A breakdown of the reusable code block #title(text: String)
text.split( ' ' ) separates the text into a List by splitting the string by ' ', e.g. "hello world" would become ["hello", "world"]
map(_.capitalize) iterates the List, calls capitalize on each element, and returns the new List, e.g. ["hello", "world"] becomes ["Hello", "World"]. This blog post give a good overview of _.
mkString(" ") converts the List back to a String by joining the string with " ", e.g. ["Hello", "World"] becomes "Hello World"
In summary, #title(text: String) capitalizes all words in a String.
The <h1>#title("hello world")</h1> is how you could ouput the result in a ScalaTemplate.