How to merge multiple Arrays without slowing the compiler down? - ios

Adding this line of code causes my compile time to go from 10 seconds to 3 minutes.
var resultsArray = hashTagParticipantCodes + prefixParticipantCodes + asterixParticipantCodes + attPrefixParticipantCodes + attURLParticipantCodes
Changing it to this brings the compile time back down to normal.
var resultsArray = hashTagParticipantCodes
resultsArray += prefixParticipantCodes
resultsArray += asterixParticipantCodes
resultsArray += attPrefixParticipantCodes
resultsArray += attURLParticipantCodes
Why does the first line cause my compile time to slow down so drastically and is there a more elegant way to merge these Arrays than the 5 line solution I've posted?

It's always +. Every time people complain about explosive compile times, I ask "do you have chained +?" And it's always yes. It's because + is so heavily overloaded. That said, I think this is dramatically better in Xcode 8, at least in my quick experiment.
You can dramatically speed this up without requiring a var by joining the arrays rather than adding them:
let resultsArray = [hashTagParticipantCodes,
prefixParticipantCodes,
asterixParticipantCodes,
attPrefixParticipantCodes,
attURLParticipantCodes]
.joinWithSeparator([]).map{$0}
The .map{$0} at the end is to force it back into an Array (if you need that, otherwise you can just use the lazy FlattenCollection). You can also do it this way:
let resultsArray = Array(
[hashTagParticipantCodes,
prefixParticipantCodes,
asterixParticipantCodes,
attPrefixParticipantCodes,
attURLParticipantCodes]
.joinWithSeparator([]))
But check Xcode 8; I believe this is at least partially fixed (but using .joined() is still much faster, even in Swift 3).

Related

what's the use of .count command in repeat while loop?

I recently began to study swift as my first programming language and there's a very simple term that i can't find an answer for it.
take a look at this code:
var a = [Int]()
repeat {
let randomNumbers = Int.random(in: 0...10)
if a.contains(randomNumbers) == false {
a.append(randomNumbers)
}
print(randomNumbers)
} while (a.count < 10)
so this code is supposed to add 10 numbers (no duplicates) from 0...10 into the array until all unique integers are listed. what I don't understand is the role of "while" here.
doesn't the last line mean the number of "generated numbers" must be less than 10? then why every time I run the code I get more than 10 numbers (say 30-40) in the console?
Also according to the code, this code must not generate dupes. then why do I get some numbers printed 2,3 times in the console?
you check if randomNumbers already added to array a, if yes, the loop will be executed again, until a.count < 10.
if you move the print statement inside the if statement, it will be printed exactly 10 times.

F# seq behavior

I'm a little baffled about the inner work of the sequence expression in F#.
Normally if we make a sequential file reader with seq with no intentional caching of data
seq {
let mutable current = file.Read()
while current <> -1 do
yield current
}
We will end up with some weird behavior if we try to do some re-iterate or backtracking, My Idea of this was, since Read() is a function calling some mutable value we can't expect the output to be correct if we re-iterate. But then this behaves nicely even on boundary reading?
let Read path =
seq {
use fp = System.IO.File.OpenRead path
let buf = [| for _ in 0 .. 1024 -> 0uy |]
let mutable pos = 1
let mutable current = 0
while pos <> 0 do
if current = 0 then
pos <- fp.Read(buf, 0, 1024)
if pos > 0 && current < pos then
yield buf.[current]
current <- (current + 1) % 1024
}
let content = Read "some path"
We clearly use the same buffer to enhance performance, but assuming that we read the 1025 byte, it will trigger an update to the buffer, if we then try to read any byte with position < 1025 after we still get the correct output. How can that be and what are the difference?
Your question is a bit unclear, so I'll try to guess.
When you create a seq { }, you're essentially creating a state machine which will run only as far as it needs to. When you request the very first element from it, it'll start at the top and run until your first yield instruction. Then, when you request another value, it'll run from that point until the next yield, and so on.
Keep in mind that a seq { } produces an IEnumerable<'T>, which is like a "plan of execution". Each time you start to iterate the sequence (for example by calling Seq.head), a call to GetEnumerator is made behind the scenes, which causes a new IEnumerator<'T> to be created. It is the IEnumerator which does the actual providing of values. You can think of it in more classical terms as having an array over which you can iterate (an iterable or enumerable) and many pointers over that array, each of which are at different points in the array (many iterators or enumerators).
In your first code, file is most likely external to the seq block. This means that the file you are reading from is baked into the plan of execution; no matter how many times you start to iterate the sequence, you'll always be reading from the same file. This is obviously going to cause unpredictable behaviour.
However, in your second code, the file is opened as part of the seq block's definition. This means that you'll get a new file handle each time you iterate the sequence or, essentially, a new file handle per enumerator. The reason this code works is that you can't reverse an enumerator or iterate over it multiple times, not with a single thread at least.
(Now, if you were to manually get an enumerator and advance it over multiple threads, you'd probably run into problems very quickly. But that is a different topic.)

Initialising hist function in Julia for use in a loop

When I use a loop, to access the variables outside of the loop they need to be initialised before you enter the loop. For example:
Y = Array{Int}()
for i = 1:end
Y = i
end
Since I have initialised Y before entering the loop, I can access it later by typing
Y
If I had not initialised it before entering the loop, typing Y would not have returned anything.
I want to extend this functionality to the output of the 'hist' function. I don't know how to set up the empty hist output before the loop. The only work around I have found is below.
yHistData = [hist(DataSet[1],Bins)]
for j = 2:NumberOfLayers
yHistData = [yHistData;hist(DataSet[j],Bins)]
end
Now when I access this later on by simply typing
yHistData
I get the correct values returned to me.
How can I initialise this hist data before entering the loop without defining it using the first value of the list I'm iterating over?
This can be done with a loop like follows:
yHistData = []
for j = 1:NumberOfLayers
push!(yHistData, hist(DataSet[j], Bins))
end
push! modifies the array by adding the specified element to the end. This increases code speed because we do not need to create copies of the array all the time. This code is nice and simple, and runs faster than yours. The return type, however, is now Array{Any, 1}, which can be improved.
Here I have typed the array so that the performance when using this array in the future is better. Without typing the array, the performance is sometimes better and sometimes worse than your code, depending on NumberOfLayers.
yHistData = Tuple{FloatRange{Float64},Array{Int64,1}}[]
for j = 1:NumberOfLayers
push!(yHistData, hist(DataSet[j], Bins))
end
Assuming length(DataSet) == NumberOfLayers, we can use anonymous functions to simplify the code even further:
yHistData = map(data -> hist(data, Bins), DataSet)
This solution is short, easy to read, and very fast on Julia 0.5. However, this version is not yet released. On 0.4, the currently released version, the performance of this version will be slower.

Can't modify loop-variable in lua [duplicate]

This question already has answers here:
Lua for loop reduce i? Weird behavior [duplicate]
(3 answers)
Closed 7 years ago.
im trying this in lua:
for i = 1, 10,1 do
print(i)
i = i+2
end
I would expect the following output:
1,4,7,10
However, it seems like i is getting not affected, so it gives me:
1,2,3,4,5,6,7,8,9,10
Can someone tell my a bit about the background concept and what is the right way to modify the counter variable?
As Colonel Thirty Two said, there is no way to modify a loop variable in Lua. Or rather more to the point, the loop counter in Lua is hidden from you. The variable i in your case is merely a copy of the counter's current value. So changing it does nothing; it will be overwritten by the actual hidden counter every time the loop cycles.
When you write a for loop in Lua, it always means exactly what it says. This is good, since it makes it abundantly clear when you're doing looping over a fixed sequence (whether a count or a set of data) and when you're doing something more complicated.
for is for fixed loops; if you want dynamic looping, you must use a while loop. That way, the reader of the code is aware that looping is not fixed; that it's under your control.
When using a Numeric for loop, you can change the increment by the third value, in your example you set it to 1.
To see what I mean:
for i = 1,10,3 do
print(i)
end
However this isn't always a practical solution, because often times you'll only want to modify the loop variable under specific conditions. When you wish to do this, you can use a while loop (or if you want your code to run at least once, a repeat loop):
local i = 1
while i < 10 do
print(i)
i = i + 1
end
Using a while loop you have full control over the condition, and any variables (be they global or upvalues).
All answers / comments so far only suggested while loops; here's two more ways of working around this problem:
If you always have the same step size, which just isn't 1, you can explicitly give the step size as in for i =start,end,stepdo … end, e.g. for i = 1, 10, 3 do … or for i = 10, 1, -1 do …. If you need varying step sizes, that won't work.
A "problem" with while-loops is that you always have to manually increment your counter and forgetting this in a sub-branch easily leads to infinite loops. I've seen the following pattern a few times:
local diff = 0
for i = 1, n do
i = i+diff
if i > n then break end
-- code here
-- and to change i for the next round, do something like
if some_condition then
diff = diff + 1 -- skip 1 forward
end
end
This way, you cannot forget incrementing i, and you still have the adjusted i available in your code. The deltas are also kept in a separate variable, so scanning this for bugs is relatively easy. (i autoincrements so must work, any assignment to i below the loop body's first line is an error, check whether you are/n't assigning diff, check branches, …)

Working with large dictionaries in Swift

I have a large set of data (approximately forty thousand value pairs), that ideally fits into [Int:Double] dictionary, but Xcode tries to reindex the file all the time and it just doesn't work.. the environment hangs, crashes..
What is the current best practice to deal with such issue in Swift for iOS?
class R {
let array:[Int:Double] = [
99502:0.1730,
// 40 thousand lines are here
99503:0.1730
]
}

Resources