Julia Module 4
Tuples, dictionaries, strings and text interview questions
Interview questions on tuples, dictionaries, strings and text: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher to mid
Tuple or named tuple, how do the two differ in Julia, and when would you return each from a function?
-
Fresher to mid
How does a Julia Dict decide that two keys are the same, and what does that mean for 1 and 1.0?
Answered in the lesson Dictionaries and sets, and the 1.13 order change
-
Fresher to mid
Why can s[2] fail on a Julia string, and how do you loop over its characters safely?
Answered in the lesson Strings, characters and Unicode in Julia
-
Fresher to mid
What do match and eachmatch return in Julia, and what does match return when the pattern does not match?
Answered in the lesson Regular expressions and parsing instrument logs
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Fresher to senior
A statistics function returns its four results in a Dict{Symbol, Any}, and a profile shows the loop that reads them allocating on every pass and running slowly. What would you return instead, and how would you show that the change worked?
- What it tests
- Knowing what a Dict costs on every call and why its abstract value type spreads to callers, choosing a named tuple or a struct, and measuring the change with @allocated and @inferred.
- First step
- Measure one call first: @allocated after a warm-up call shows the bytes the Dict costs, and @inferred on a read of one result shows that its type is abstract. Then list the results: their names are the same on every call, so a named tuple can hold them with a concrete type for each.
- Follow-ups
-
- When is a Dict still the right return value?
- When would you define a struct instead of a named tuple?
- How do you keep callers that index the Dict working during the change?
From the lesson Tuples, named tuples and pairs
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to staff
Tuple{Int64, Float64} <: Tuple{Real, Real} is true, but Vector{Int64} <: Vector{Real} is false. Why does Julia make this difference, and how do you write a method that accepts any vector of real numbers?
- What it tests
- Telling covariant tuple types from invariant parametric types, the memory reason behind invariance, and writing signatures with AbstractVector{<:Real} or a type parameter.
- First step
- Ask what a Vector{Real} promises: any slot may hold any real number, so code may store a Float64 into it. A Vector{Int64} cannot keep that promise. A tuple can never be written to, so letting it stand in for a tuple of wider types breaks no promise.
- Follow-ups
-
- How does a Vector{Real} store its elements, compared with a Vector{Float64}?
- What is the difference between v::Vector{<:Real} and v::Vector{T} where {T<:Real}?
- Why are named tuple types not covariant in their field types?
From the lesson Tuples, named tuples and pairs
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to senior
A test writes a Dict of station totals to text and compares it with a saved file. It passed on Julia 1.12 and fails on 1.13, although every total is the same. Why, and how do you fix the test and the code that writes the file?
- What it tests
- Knowing that the order of a Dict is unspecified and changed with the 1.13 hash, comparing values instead of text, and writing output that stays the same across releases.
- First step
- Diff the two outputs: the same entries in another order. A Dict hands out its keys in the order of the slots they hash to, and Julia 1.13 changed the hash function, so the printed order changed while == between the two dictionaries still holds.
- Follow-ups
-
- Another program reads the file and expects a fixed order. What do you write?
- Would OrderedDict be a good fix?
- Could the order change again without a Julia upgrade?
From the lesson Dictionaries and sets, and the 1.13 order change
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A cache maps parameter vectors such as [a, b] to computed results. After a while it misses entries that were stored, and length(cache) keeps growing. What is happening, and what would you use as the key instead?
- What it tests
- Knowing that a Dict hashes a key when it is stored, that changing a mutable key strands its entry, and choosing immutable keys such as tuples.
- First step
- Look for code that changes a vector after it was used as a key, such as push! or params[1] = …: the entry stays in the slot of its old hash, lookups with the old values no longer compare equal, and every miss stores another entry.
- Follow-ups
-
- How would you show that this is the cause?
- Is copying the vector before storing it enough?
- What does a tuple key cost in memory compared with a vector key?
From the lesson Dictionaries and sets, and the 1.13 order change
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to senior
A database column holds at most 20 bytes, and names are cut with first(name, 20) before they are stored. Inserts fail for some Hindi and Tamil names, and a quick fix that cuts at byte 20 corrupts others. What is wrong, and how do you cut a name correctly?
- What it tests
- Telling bytes from characters and graphemes in UTF-8, cutting text only at valid boundaries, and deciding what a limit in bytes means for the person whose name is cut.
- First step
- Count one long name three ways. first(name, 20) keeps 20 characters, and a Devanagari character takes 3 bytes, so the result can be far over 20 bytes. Cutting at byte 20 can land inside a character, which leaves invalid UTF-8, or inside a grapheme, which leaves half a letter.
- Follow-ups
-
- How do you cut at the last whole grapheme that fits?
- What should the person see when a name is cut?
- How do you test the function?
From the lesson Strings, characters and Unicode in Julia
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to senior
A report pads names to a column with name * " "^(20 - length(name)). The columns line up for English names but not for Hindi or Tamil ones. Why, and how would you fix the report and test the fix?
- What it tests
- Knowing that length counts code points while textwidth counts columns and rpad pads by it, and the limits of column widths for complex scripts and emoji.
- First step
- Compare length and textwidth for one name: नमस्ते has 6 code points but takes 4 columns, so the padding comes out 2 spaces short. Compute the padding from textwidth, which is what rpad has done since Julia 1.7.
- Follow-ups
-
- Is textwidth always what the terminal shows?
- How would you right-align numbers next to the names?
- What changes if the report is written to HTML or a spreadsheet instead?
From the lesson Strings, characters and Unicode in Julia
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to senior
A nightly job parses 2 million data-logger lines, calling parse(Float64, …) on a regex capture of each, and it stops with an error at the first malformed line, so most nights produce nothing. How would you redesign it, and what should it report?
- What it tests
- Treating bad input as data: anchored patterns, tryparse, keeping each rejected line with its number and reason, and reading the file lazily.
- First step
- Find where it stops: parse throws on the first value that is not a number, and nothing catches it. Then separate the two questions every line raises, whether it has the right shape and whether its value is a number, and give each failure its own reason.
- Follow-ups
-
- How do you keep memory flat for 2 million lines?
- When should the job fail instead of reporting?
- How would you test the parser?
From the lesson Regular expressions and parsing instrument logs
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to staff
An internal tool lets users type a search pattern, and the code runs occursin(Regex(input), line) over a large log. Some searches find the wrong lines, and one made the tool stop answering. What is going on, and how do you make the feature safe?
- What it tests
- Seeing that user text used as a pattern is both a correctness and a denial-of-service risk, and choosing literal search, input bounds and fixed patterns.
- First step
- Separate the two failures. The wrong lines: dots and stars in the input act as pattern syntax, as "a.b*c" matched "aXbbbc". The stall: a pattern with a repeat inside a repeat backtracks until PCRE2 stops at its match limit, after a great deal of work on every line.
- Follow-ups
-
- Is quoting the input with \Q and \E enough?
- What if users really need patterns?
- How would you test the fix?
From the lesson Regular expressions and parsing instrument logs
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes