Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Julia Module 6

The type system and multiple dispatch interview questions

Interview questions on the type system and multiple dispatch: warm-ups, then what each harder question tests and how a good answer starts.

18 questions: 6 warm-ups and 12 with model answers · Levels: Fresher to staff

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher to mid

    How does an abstract type differ from a concrete type in Julia?

    Answered in the lesson The type system: abstract and concrete types

  2. Fresher to mid

    When would you choose a mutable struct over a struct in Julia?

    Answered in the lesson Structs, constructors and redefining types (1.12+)

  3. Fresher to mid

    How is multiple dispatch different from method overloading in Java or C++?

    Answered in the lesson Methods and multiple dispatch

  4. Fresher to mid

    What does the T in struct Point{T} do?

    Answered in the lesson Parametric types and generic numeric code

  5. Fresher to mid

    When does Julia call convert(T, x) by itself, and how does T(x) differ?

    Answered in the lesson Conversion, promotion and custom number types

  6. Fresher to mid

    What must a type define to work in a for loop?

    Answered in the lesson Interfaces: iteration and custom arrays

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Fresher to senior

    A library function is declared fit(x::Vector{Float64}, y::Vector{Float64}). Users report MethodErrors when they pass ranges, views, Float32 data and vectors of integers. How do you widen the signature, how far do you widen it, and what does the change cost?

    What it tests
    Knowing invariance and the AbstractVector family, choosing between AbstractVector{<:Real}, a type parameter and no annotation, and knowing that specialisation keeps the Float64 path as fast as before.
    First step
    List the types users actually pass: UnitRange{Int64}, SubArray, Vector{Float32}, Vector{Int64}. None is a Vector{Float64}, and invariance means none ever will be. Then write down what fit needs from its inputs, indexing and real arithmetic, which is what AbstractVector{<:Real} says.
    Follow-ups

    From the lesson The type system: abstract and concrete types

    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.

    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
  2. Mid to staff

    A station lookup returns nothing for unknown stations. A nightly batch job fails after three hours with MethodError: no method matching +(::Nothing, ::Float64) inside a summing loop. How do you find the cause, and how do you redesign the lookup and its callers so the failure comes early or never?

    What it tests
    Reading a MethodError that involves Nothing, tracing a Union{Nothing, T} result to its source, and choosing between nothing, missing, an error and a default.
    First step
    The nothing was made by the lookup, not by the loop: find where values enter the sum and check what each source can return, for example with Base.return_types, which shows Union{Nothing, Float64}. Then decide what an unknown station means for this job: an error to stop on, a gap to skip and report, or a value with a default.
    Follow-ups

    From the lesson The type system: abstract and concrete types

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  3. Fresher to senior

    Sensor readings are stored in a struct with the fields station, hour, value and unit. Analysts keep finding NaN values, hours above 24 and unknown units in the results. Redesign the type so that such readings cannot exist, and explain what changes for the code that builds them.

    What it tests
    Using an inner constructor to enforce rules, knowing that it removes the default constructors, writing errors that name the field, and handling NaN in comparisons.
    First step
    Write each rule as a check on one field: a station that is not empty, an hour in [0, 24), a value that is not NaN, a unit from a fixed list. Put all of them in one inner constructor that ends in new, so every way of building a reading passes through them.
    Follow-ups

    From the lesson Structs, constructors and redefining types (1.12+)

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  4. Mid to staff

    During a long Julia 1.12 session you add a unit field to a struct. Afterwards a function that worked before throws a MethodError for new values, and values in a cache print as @world(Sample, …). Explain what happened, and how you would work with struct redefinition safely.

    What it tests
    Knowing that redefinition creates a new type and moves the name, that values and methods stay with the old type, and a way of working that avoids stale state.
    First step
    Compare typeof of an old and a new value: they differ, because the second definition made a new type and moved the name Sample to it. The methods compiled earlier name the old type, which explains the MethodError for new values.
    Follow-ups

    From the lesson Structs, constructors and redefining types (1.12+)

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  5. Mid to staff

    Two packages add methods to a shared function combine(a, b): one for (MyMatrix, AbstractMatrix), the other for (AbstractMatrix, TheirMatrix). Users who load both get "ambiguous" MethodErrors for some calls. How do you find every ambiguity, fix the one you have, and keep new ones from appearing?

    What it tests
    Seeing why two signatures overlap, deciding which package defines the method for the overlap, and preventing new ambiguities with Test.detect_ambiguities, Aqua.jl and design.
    First step
    Write down the overlap: combine(::MyMatrix, ::TheirMatrix) fits both methods and neither is more specific, so every call with that pair of types is ambiguous. Then run Test.detect_ambiguities with both packages loaded to list every such pair, not only the one users reported.
    Follow-ups

    From the lesson Methods and multiple dispatch

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  6. Fresher to senior

    A colleague adds Base.:+(v::Vector{Float64}, x::Float64) = v .+ x to a project's utilities so that v + 1.0 works. What is wrong with it, what can it break, and what would you do instead?

    What it tests
    Recognising type piracy, knowing what it does to other code in the same session, and the alternatives: broadcasting or a function of your own.
    First step
    Check who owns what: + belongs to Base, and Vector{Float64} and Float64 are Base types, so the method is type piracy and changes + for every package loaded in the session. Then ask what the colleague wanted, element-wise addition, which Julia already writes as v .+ 1.0.
    Follow-ups

    From the lesson Methods and multiple dispatch

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  7. Mid to staff

    A simulation keeps its state in struct Sim with the fields state::AbstractVector, dt::Real and params::Dict{Symbol, Any}. Profiling shows the time-step loop allocating on every iteration. Explain why, and redesign the struct without losing the ability to run on Float32 data or on GPU arrays.

    What it tests
    Recognising abstract and Any-valued fields as the cause, replacing them with type parameters or a named tuple, and checking the fix with @allocated or @code_warntype.
    First step
    Ask what the compiler can learn from typeof(sim): Sim is one type whatever it holds, so state, dt and every params lookup have unknown types inside the loop. Measure one step with @allocated, then make each field's type a parameter or a concrete type.
    Follow-ups

    From the lesson Parametric types and generic numeric code

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  8. Fresher to senior

    A numerical routine written with s = 0.0, 1/n and a tolerance of 1e-12 returns Float64 for Float32 inputs, loses exactness for Rational inputs, and never stops for one user's Float32 data. How do you make it generic, and how do you test that it stays generic?

    What it tests
    Spotting Float64 literals and tolerances that leak into generic code, rewriting them with zero, one, oftype and eps, and testing result types with typeof and @inferred.
    First step
    Find every constant that fixes a type: 0.0, 1/n and 1e-12. The first two turn the computation into Float64, and the third is a tolerance below the spacing of Float32 numbers. Replace them with zero(T), one(T)/n and a tolerance built from eps(T), where T comes from the input.
    Follow-ups

    From the lesson Parametric types and generic numeric code

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  9. Mid to staff

    A Money type stores paise in an Int64 and defines + for two Money values. Colleagues want 2 * m, m + 100 and sum(Money[]) to work, and propose promote_rule and convert so that Money mixes with every number. Which of these should work, how do you implement them, and where is promotion the wrong tool?

    What it tests
    Choosing between promotion and explicit methods, spotting conversions that would change meaning, and giving a type a zero for empty sums.
    First step
    Ask what each operation means. 2 * m scales an amount and makes sense; m + 100 does not, because 100 has no unit: paise or rupees? Promotion would make every number silently convertible to money, so write explicit methods for scaling and a zero for the empty sum instead.
    Follow-ups

    From the lesson Conversion, promotion and custom number types

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  10. Mid to staff

    An Interval type is a subtype of Real. Tests show that sort works, but x <= y is false for some intervals that are equal, and a Dict with Interval keys holds what look like duplicates. What is wrong, and how do you define the comparisons of a type like this?

    What it tests
    Knowing how Base builds <=, isequal and hash from a few methods, keeping them consistent, and deciding what order and equality mean for an interval.
    First step
    List what the type defines: probably < on one bound and the default ==, which compares every field. Base's <= combines == and <, and a Dict uses isequal and hash, so the three disagree. Decide what equality and order mean for an interval, then derive ==, isless, < and hash from that one decision.
    Follow-ups

    From the lesson Conversion, promotion and custom number types

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  11. Fresher to senior

    A colleague's iterator over the records of a large file works in for loops, but collect(records) returns a Vector{Any}, and every analysis of the collected records is slow and allocates. What is missing, how do you fix it, and how do you check the fix?

    What it tests
    Knowing the IteratorSize and eltype traits and their defaults, choosing between HasLength, SizeUnknown and EltypeUnknown, and checking the result with typeof and @inferred.
    First step
    Ask what collect was told. The default eltype is Any, so collect built a Vector{Any} even though every record has the same type. Declare Base.eltype on the iterator's type, and IteratorSize as SizeUnknown when the number of records is not known before the file is read.
    Follow-ups

    From the lesson Interfaces: iteration and custom arrays

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  12. Mid to staff

    You wrap a matrix whose entries come from a formula as an AbstractMatrix with size and getindex. A * x is many times slower than Matrix(A) * x, and A \ b uses as much memory as the dense matrix. Explain both, and decide when to keep the lazy type and when to build the dense matrix.

    What it tests
    Knowing that generic fallbacks read entries one at a time, that factorizations copy into dense storage, and choosing between laziness, a dense copy and specialised methods.
    First step
    Separate the two effects. The product runs Base's generic fallback, which calls getindex for every entry and recomputes the formula each time; the solver factorizes a dense copy, so it needs that memory whatever the type. Then count how often the matrix is used.
    Follow-ups

    From the lesson Interfaces: iteration and custom arrays

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes

All Julia interview questions · The Julia track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.