New syntax for default values in Swift functions - cocoa

I just noticed that the latest beta of Xcode (7.1) has changed the signature for the print function in Swift.
The new syntax is:
public func print(items: Any..., separator: String = default, terminator: String = default)
Anybody knows what this default thing is? How do you specify the default value, not just the fact that it has one?

The default in the function signature means that it has a default value and you don't have to pass a parameter.
func add(a: Int = 0, b: Int = 0) -> Int {
return a + b
}
// "normal" function call
add(2, b: 4) // 6
// no specified parameters at all
add() // 0; both a and b default to 0
// one parameter specified
// a has no external name since it is the first parameter
add(3) // 3; b defaults to 0
// b has an external name since it is not the first parameter
add(b: 4) // 4; a defaults to 0
In case of the print function separator defaults to " " and terminator to "\n".
There are 4 way to call it:
struct SomeItem {}
print(SomeItem(), SomeItem())
print(SomeItem(), SomeItem(), separator: "_")
print(SomeItem(), SomeItem(), terminator: " :) \n")
print(SomeItem(), SomeItem(), separator: "_", terminator: " :) \n")
Prints:
SomeItem() SomeItem()
SomeItem()_SomeItem()
SomeItem() SomeItem() :)
SomeItem()_SomeItem() :)

the default separator is a single space, and the default terminator is a newline
to use a different value for either of these, simply pass the desired value as an argument when you call the function - e.g.:
print("first", "second", separator: "-", terminator: "...")
print("third")
// => "first-second...third"

Related

Parse log entries with least possible overhead

I have some log format with entries like this:
log_entry_no1 := "2021-11-03 7:7:51 hal9000 evil_app heartbeat C99 I am sorry Dave"
Those "fields" are separated by space except the last one called message which is just log data and can contain spaces.
My question is. Is there better way to process those entries without first splitting whole sentence and then join'ing that last part (message) with less overhead using go?
type LogData struct {
d Date // yyyy-mm-dd Mandatory
t Time // hh:mm:ss Mandatory
hostname string // Mandatory
app_id string // Mandatory
etype string // enum based string Mandatory
level string // Optional base on etype
message string // Mandatory
}
log_fields := strings.Split(log_entry_no1, " ")
var log_data = LogData{}
log_data.d = parseTime(log_entry_no1[0])
log_data.t = parseTime(log_entry_no1[1])
//...
if log_fields[4] == "heartbeat" {
log_data.level = log_fields[5]
log_data.message = strings.Join(log_fields[6:], " ")
} else {
log_data.message = strings.Join(log_fields[5:], " ")
}
Use strings.SplitN.
func SplitN(s, sep string, n int) []string
The docs say if n is greater than zero: it returns at most n substrings; the last substring will be the unsplit remainder.

Why does an error occur when I try to test if a member variable (string) in a class is empty?

I'm working on a project and need to test one of my class' member variables to verify that the user did indeed enter a string.
I've also tried using (patronName == '') and (patronName == "") but have had no luck.
Edit: Using "\n" fixes the error but the program ends without allowing the user to enter a name.
std::string Restaurant::getPatronName()
{
bool controlFlag = true;
do
{
getline(std::cin,patronName);
if ((std::cin.fail()) || (patronName == '\n'))
{
std::cout << "You must enter a name!" << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
else
{
controlFlag = false;
}
} while (controlFlag);
return patronName;
}
The function should read and store the name entered by the user into patronName. When trying to build, I get an error that says "no match for 'operator=='". Could this be because the object called in main is a pointer of type Restaurant?
Besides the type mismatch between the character '\n' and the std::string patronName, we can find at https://en.cppreference.com/w/cpp/string/basic_string/getline that std::getline(input, str, delim);
Extracts characters from input and appends them to str until […] the next available input character is delim, […], in which case the delimiter character is extracted from input, but is not appended to str.
So there won't be any '\n' character, if delim is the newline, in the first place.
You can use std::basic_string::empty() to check if a string is empty.
What happens with '\n' is you are comparing a string with a char, which, i suspect, there is no operator== defined for this case. If you are sure the string isn't empty, you can call operator[] formerName[0], which returns a char.
You have to write patronName == "\n" because you cannot compare string and character

Make Xcode (swift )throw error for print()

I created a custom Logger for logging values for different modes like debug, release but I want that whenever I use the default print() Xcode should throw an error explaining the user to use the custom logger.
I referred this but want to throw error there and then rather than adding a build-phase.
Any Ideas ?
You could shadow the built-in print in your module and mark it "unavailable":
// swift 3:
#available(*, unavailable, message: "use Logger instead!")
internal func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
Swift.print(items, separator: separator, terminator: terminator)
}
// swift 2:
#available(*, unavailable, message="use Logger instead!")
internal func print(items: Any..., separator: String = " ", terminator: String = "\n") {
Swift.print(items, separator: separator, terminator: terminator)
}
The result looks like:
(There is still another instance of print<Target>(..., to output: inout Target) which I don't bother to hide, I guess no one will accidentally use that function.)
As shown, you could still use the qualified name Swift.print to refer to the real function in case of emergency.
Note that this will only affect your own module. You can't force users outside of your module to not use print.

Using Swift's Repeat collection

In pre-Swift 2.0 sample code, I've come across something like:
var val = "hello" + Repeat(count: paddingAmount, repeatedValue: "-") + "."
In Xcode 7.0/Swift 2.0 Playground, this produces the error:
note: expected an argument list of type '(String, String)'
How would you use the Repeat collection and get the value that's held by the collection for use?
String has an initializer that will return a string of repeated characters, I would recommend using that in your case:
let padding = String(count: paddingAmount, repeatedValue: Character("-"))
var val = "hello" + padding + "."
It's now Array(count: paddingAmount, repeatedValue: "-").

Swift adding multiple stringByReplacingOccurrencesOfString on one String?

Hello i would like to create a app that changes characters into binary code and i was wondering if there is a way to add multiple stringByReplacingOccurrencesOfString on one String or if i should take another approach to this "Problem".
Here is what i have so far
func textToBinary(theString: String) -> String {
return theString.stringByReplacingOccurrencesOfString("a",
withString: "01100001")
}
textArea.text = textToBinary(lettersCombined)
// lettersCombined is the string that i want to turn into BinaryCode.
Try this:
func textToBinary(theString : String, radix : Int = 2) -> String {
var result = ""
for c in theString.unicodeScalars {
result += String(c.value, radix: radix) + " "
}
return result
}
println(textToBinary("a"))
println(textToBinary("abc", radix: 10))
println(textToBinary("€20", radix: 16))
println(textToBinary("😄"))
(The last one is a smiley face but somehow my browser can't display it).
Edit: if you want to pad your strings to 8-character long, try this:
let str = "00000000" + String(c.value, radix: radix)
result += str.substringFromIndex(advance(str.startIndex, str.characters.count - 8)) + " "
The first line adds eight 0 the left of your string. The second line takes the last 8 characters from the padded string.

Resources