Mysterious " " in Swift 4 print output (Xcode 9Beta) - swift

I believe this is my first post here. I am teaching myself Swift and have come across some odd behavior involving the mysterious appearance of a leading " " in a print statement. I was exploring print formatting and this code is producing a leading " " in the first dashedLine printed.
Code:
var dashedLine = "-------------------------------------------------------------------"
print("a bunch of text\n", dashedLine)
print(dashedLine)
Output:
a bunch of text
-------------------------------------------------------------------
-------------------------------------------------------------------
Why the leading space before the first dashed line?
I've read the Swift 4 documentation. (In playing with "terminator" syntax at the end of a print list, I get unanticipated results, including suppression of output, depending.) I am curious as to the appearance of the leading space as my primary question.

By default, a print statement with multiple arguments prints those out with a space in between.
You can find more in Apple's documentation here.

Following on to #bajracharyas353’s answer, a solution if you’re needing to avoid this would be to combine strings using any of the methods Swift allows, like "a" + "b" or String.append, or print(String1, String2, separator: "").
As for suppression of output, I think I’ve run into the same thing with JWTs. There seems to be a pretty modest limit on output, but I could be wrong there.

Problem
The Swift.print(_ items: Any...) function prints multiple arguments separated by a space.
Solution
Use print("a bunch of text\n", dashedLine, separator: "") instead

Related

Can a Swift statement be broken over multiple lines?

The language guide says:
Swift doesn’t require you to write a semicolon (;) after each statement in your code, although you can do so if you wish. However, semicolons are required if you want to write multiple separate statements on a single line.
This implies that Swift uses newlines as statement terminators. Does every statement need to fit on a single line? Or is it possible to insert a newline within a single statement - and if so, what are the rules that determine whether or not a newline terminates a statement?
Swift can have newlines in statements. It is so common in complex commands like this:
var query = HouseholdInfoTable.table
.select(HouseholdInfoTable.uuid.distinct, HouseholdInfoTable.table[*])
.join(PersonInfoTable.table, on: PersonInfoTable.householdUuid == HouseholdInfoTable.uuid)
.filter(HouseholdInfoTable.houseNumber == houseNumber)
.order(HouseholdInfoTable.sortName)
But you can have simple statements broken up, like this:
let a = 1
+ 2
let b = 1 +
2
Generally you can split the line across operands or punctuation
You can do multiline comments with line feeds in them like this:
let bigComment = """
anythingYou want can go here
asdlkasdkljfad
askjf
"""
Swift's style guide has more in-depth information:
https://google.github.io/swift/#line-wrapping
Playgrounds are a good place to see what the compiler handles.

How to shuffle words in a sentence and show them with spacing on a UILabel?

let mySentences:String = "Hello. nice to meet you!"
let divideMySentencesAndShuffled:[String] = mySentences.components(separatedBy: " ").shuffled()
showSentence.text = divideMySentencesAndShuffled.joined()
I tried the above code, but the result is like this : Hello.you!nicemeetto
I'd like to give spaces to the shuffled sentence. Like, nice to Hello! you. meet
You can specify a space as a separator:
divideMySentencesAndShuffled.joined(separator: " ")
However, I would recommend some other changes. Often times, there are situations in which you have long expressions that would benefit from being broken down into sub-expressions assigned to well-named intermediate variables. The variable names act like comments, to explain what each sub-expression is.
However, this is a case in which the intermediate variable doesn't add much value, because you wouldn't really know what divideMySentences means if you didn't look at the right side's value. Explaining that division means splitting text into words (well not quite, because splitting on spaces still leaves punctuation attached to the words, but close enough) would make the variable name longer and more complex than the actual code itself. At that point, it's better to just skip the intermediate variable. To improve clarity however, you can make the chained method calls be one per line.
Also, don't add type annotations where they don't add value.
Compare:
let mySentences: String = "Hello. nice to meet you!"
let dividedMySentences:[String] = mySentences.components(separatedBy: " ")
let dividedMySentencesAndShuffled:[String] = dividedMySentences.shuffled()
let result: String = divideMySentencesAndShuffled.joined(separator: " ")
To:
let inputText = "Hello. nice to meet you!"
let scrambledWords = inputText
.components(separatedBy: " ")
.shuffled()
.joined(separator: " ")
You don't even have to comment what the components(separatedBy:), shuffled(), joined(separator:) calls do, because they already read pretty much like plain English. This is what people refer to as "self documenting" code.
It's generally preferable to write self-documenting code where possible like this, rather than having complex code explained by English comments, because comments can easily go out-of-sync from the code they comment on.

AutoHotKey Source Code Line Break

Is there a way to do line break in AutoHotKey souce code? My code is getting longer than 80 characters and I would like to separate them neatly. I know we can do this in some other language, such as VBA for example below:
http://www.excelforum.com/excel-programming-vba-macros/564301-how-do-i-break-vba-code-into-two-or-more-lines.html
If Day(Date) > 10 _
And Hour(Time) > 20 Then _
MsgBox "It is after the tenth " & _
"and it is evening"
Is there a souce code line break in AutoHotKey? I use a older version of the AutoHotKey, ver 1.0.47.06
There is a Splitting a Long Line into a Series of Shorter Ones section in the documentation:
Long lines can be divided up into a collection of smaller ones to
improve readability and maintainability. This does not reduce the
script's execution speed because such lines are merged in memory the
moment the script launches.
Method #1: A line that starts with "and", "or", ||, &&, a comma, or a
period is automatically merged with the line directly above it (in
v1.0.46+, the same is true for all other expression operators except
++ and --). In the following example, the second line is appended to the first because it begins with a comma:
FileAppend, This is the text to append.`n ; A comment is allowed here.
, %A_ProgramFiles%\SomeApplication\LogFile.txt ; Comment.
Similarly, the following lines would get merged into a single line
because the last two start with "and" or "or":
if (Color = "Red" or Color = "Green" or Color = "Blue" ; Comment.
or Color = "Black" or Color = "Gray" or Color = "White") ; Comment.
and ProductIsAvailableInColor(Product, Color) ; Comment.
The ternary operator is also a good candidate:
ProductIsAvailable := (Color = "Red")
? false ; We don't have any red products, so don't bother calling the function.
: ProductIsAvailableInColor(Product, Color)
Although the indentation used in the examples above is optional, it might improve
clarity by indicating which lines belong to ones above them. Also, it
is not necessary to include extra spaces for lines starting with the
words "AND" and "OR"; the program does this automatically. Finally,
blank lines or comments may be added between or at the end of any of
the lines in the above examples.
Method #2: This method should be used to merge a large number of lines
or when the lines are not suitable for Method #1. Although this method
is especially useful for auto-replace hotstrings, it can also be used
with any command or expression. For example:
; EXAMPLE #1:
Var =
(
Line 1 of the text.
Line 2 of the text. By default, a line feed (`n) is present between lines.
)
; EXAMPLE #2:
FileAppend, ; The comma is required in this case.
(
A line of text.
By default, the hard carriage return (Enter) between the previous line and this one will be written to the file as a linefeed (`n).
By default, the tab to the left of this line will also be written to the file (the same is true for spaces).
By default, variable references such as %Var% are resolved to the variable's contents.
), C:\My File.txt
In the examples above, a series of lines is bounded at
the top and bottom by a pair of parentheses. This is known as a
continuation section. Notice that the bottom line contains
FileAppend's last parameter after the closing parenthesis. This
practice is optional; it is done in cases like this so that the comma
will be seen as a parameter-delimiter rather than a literal comma.
Please read the documentation link for more details.
So your example can be rewritten as the following:
If Day(Date) > 10
And Hour(Time) > 20 Then
MsgBox
(
It is after the tenth
and it is evening
)
I'm not aware of a general way of doing this, but it seems you can break a line and start the remainder of the broken line (e.g. the next real line) with an operator. As long as the second line (and the third, fourth, etc., as applicable) starts with (optional whitespace plus) an operator, AHK will treat the whole thing as one line.
For instance:
hello := "Hello, "
. "world!"
MsgBox %hello%
The presence of the concatenation operator . at the logical beginning of the second line here makes AHK treat both lines as one.
(I also tried leaving the operator and the end of the first line and starting the second off with a double-quoted string; that didn't work.)

How does this Perl one-liner actually work?

So, I happened to notice that last.fm is hiring in my area, and since I've known a few people who worked there, I though of applying.
But I thought I'd better take a look at the current staff first.
Everyone on that page has a cute/clever/dumb strapline, like "Is life not a thousand times too short for us to bore ourselves?". In fact, it was quite amusing, until I got to this:
perl -e'print+pack+q,c*,,map$.+=$_,74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34'
Which I couldn't resist pasting into my terminal (kind of a stupid thing to do, maybe), but it printed:
Just another Last.fm hacker,
I thought it would be relatively easy to figure out how that Perl one-liner works. But I couldn't really make sense of the documentation, and I don't know Perl, so I wasn't even sure I was reading the relevant documentation.
So I tried modifying the numbers, which got me nowhere. So I decided it was genuinely interesting and worth figuring out.
So, 'how does it work' being a bit vague, my question is mainly,
What are those numbers? Why are there negative numbers and positive numbers, and does the negativity or positivity matter?
What does the combination of operators +=$_ do?
What's pack+q,c*,, doing?
This is a variant on “Just another Perl hacker”, a Perl meme. As JAPHs go, this one is relatively tame.
The first thing you need to do is figure out how to parse the perl program. It lacks parentheses around function calls and uses the + and quote-like operators in interesting ways. The original program is this:
print+pack+q,c*,,map$.+=$_,74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34
pack is a function, whereas print and map are list operators. Either way, a function or non-nullary operator name immediately followed by a plus sign can't be using + as a binary operator, so both + signs at the beginning are unary operators. This oddity is described in the manual.
If we add parentheses, use the block syntax for map, and add a bit of whitespace, we get:
print(+pack(+q,c*,,
map{$.+=$_} (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21,
18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34)))
The next tricky bit is that q here is the q quote-like operator. It's more commonly written with single quotes:
print(+pack(+'c*',
map{$.+=$_} (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21,
18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34)))
Remember that the unary plus is a no-op (apart from forcing a scalar context), so things should now be looking more familiar. This is a call to the pack function, with a format of c*, meaning “any number of characters, specified by their number in the current character set”. An alternate way to write this is
print(join("", map {chr($.+=$_)} (74, …, -34)))
The map function applies the supplied block to the elements of the argument list in order. For each element, $_ is set to the element value, and the result of the map call is the list of values returned by executing the block on the successive elements. A longer way to write this program would be
#list_accumulator = ();
for $n in (74, …, -34) {
$. += $n;
push #list_accumulator, chr($.)
}
print(join("", #list_accumulator))
The $. variable contains a running total of the numbers. The numbers are chosen so that the running total is the ASCII codes of the characters the author wants to print: 74=J, 74+43=117=u, 74+43-2=115=s, etc. They are negative or positive depending on whether each character is before or after the previous one in ASCII order.
For your next task, explain this JAPH (produced by EyesDrop).
''=~('(?{'.('-)#.)#_*([]#!#/)(#)#-#),#(##+#)'
^'][)#]`}`]()`#.#]#%[`}%[#`#!##%[').',"})')
Don't use any of this in production code.
The basic idea behind this is quite simple. You have an array containing the ASCII values of the characters. To make things a little bit more complicated you don't use absolute values, but relative ones except for the first one. So the idea is to add the specific value to the previous one, for example:
74 -> J
74 + 43 -> u
74 + 42 + (-2 ) -> s
Even though $. is a special variable in Perl it does not mean anything special in this case. It is just used to save the previous value and add the current element:
map($.+=$_, ARRAY)
Basically it means add the current list element ($_) to the variable $.. This will return a new array with the correct ASCII values for the new sentence.
The q function in Perl is used for single quoted, literal strings. E.g. you can use something like
q/Literal $1 String/
q!Another literal String!
q,Third literal string,
This means that pack+q,c*,, is basically pack 'c*', ARRAY. The c* modifier in pack interprets the value as characters. For example, it will use the value and interpret it as a character.
It basically boils down to this:
#!/usr/bin/perl
use strict;
use warnings;
my $prev_value = 0;
my #relative = (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34);
my #absolute = map($prev_value += $_, #relative);
print pack("c*", #absolute);

How do I insert a lot of whitespace in Perl?

I need to buff out a line of text with a varying but large number of whitespace. I can figure out a janky way of doing a loop and adding whitespace to $foo, then splicing that into the text, but it is not an elegant solution.
I need a little more info. Are you just appending to some text or do you need to insert it?
Either way, one easy way to get repetition is perl's 'x' operator, eg.
" " x 20000
will give you 20K spaces.
If have an existing string ($s say) and you want to pad it out to 20K, try
$s .= (" " x (20000 - length($s)))
BTW, Perl has an extensive set of operators - well worth studying if you're serious about the language.
UPDATE: The question as originally asked (it has since been edited) asked about 20K spaces, not a "lot of whitespace", hence the 20K in my answer.
If you always want the string to be a certain length you can use sprintf:
For example, to pad out $var with white space so it 20,000 characters long use:
$var = sprintf("%-20000s",$var);
use the 'x' operator:
print ' ' x 20000;