skip to content

Programming Paradigms

The competing ways to structure a program: behavior bundled into objects, built from pure functions over immutable data, or driven by streams. Interviewers check that you pick a style deliberately.

on this pageshow

explore

questions

692 · 7 sections

A library operation documents that its argument must be a non-empty collection, and a caller passes an empty one. Whose defect is that, and how do Eiffel, Racket, Kotlin and Rust each express and enforce that obligation differently?

level: middleimportance: must knowfreq 40%
basics
~20 s

The caller's. Preconditions are caller obligations. Eiffel's require blames the caller by name, Racket blames the module that crossed the boundary, Kotlin's require throws with no party named, and Rust encodes non-emptiness in the argument type so there is nothing left to check.

open as a page

Languages disagree about who decides that a concrete type satisfies an abstraction: in Java the type's author declares it, in Go the compiler infers it from method shape, and in Rust a third party may be forbidden from declaring it at all. Compare these models and what each one costs.

level: middleimportance: must knowfreq 48%
basics
~20 s

Nominal (Java, C#): the type's author writes implements, so retrofitting a library type needs a wrapper. Structural (Go, TypeScript): matching method shape is enough, so a consumer can define the abstraction afterwards. Rust traits are nominal but either side may write the impl, and the orphan rule forces a newtype when neither is local.

open as a page

Some languages let a class have two supertypes that share a common ancestor, and others refuse. Explain why inheriting a type, inheriting an implementation, and inheriting state are three separate problems, and show how at least three named languages draw the line differently.

level: middleimportance: must knowfreq 58%
basics
~20 s

Types are only obligations, so they union freely. Implementation conflicts are decidable — pick one, order them, or error. State is the hard layer: a shared ancestor's fields must be duplicated per path or shared, and neither default is right for every program.

open as a page

Two modules each reference the other, forming a cycle in the dependency graph. What does a cycle actually cost you, and which languages refuse to build one versus merely letting it hurt later?

level: middleimportance: must knowfreq 54%
basics
~20 s

A cycle fuses its members into one unit: everything in a strongly connected component must be built, tested, versioned and understood together. Go rejects import cycles at compile time with no override; Java and C# allow package-level cycles freely; Python allows the import and fails at runtime on a partially initialised module.

open as a page

A C library's public header contains only `typedef struct Conn Conn;` plus functions taking `Conn *` — the struct itself is defined in a .c file the caller never sees — even though the C language has no access-control keywords at all. Python is similar in spirit: a leading underscore is a convention, `__all__` names the exported surface, and an attribute written `self.__x` inside `class Cls` is simply stored under the name `_Cls__x` so that a subclass will not collide with it. Meanwhile, a class that declares every field private and adds a matching getter and setter for each satisfies every rule a language is able to check. Are encapsulation and information hiding the same thing? Argue using these cases.

level: middleimportance: must knowfreq 55%
basics
~20 s

No. Encapsulation is a mechanism: bundle state with the operations that reach it. Information hiding is a design property: a module keeps a changeable decision secret. A C header can hide everything with no keywords; getter-and-setter classes hide nothing.

open as a page

A transfer function returns either a success value or a described failure. What does that return type force on every caller?

level: juniorimportance: must knowfreq 66%
basics
~20 s

Every caller must handle the failure case to reach the success value, because the two outcomes are alternative shapes of one returned value. A failure that is thrown instead puts no such obligation at the call site.

open as a page

A directory lookup returns an empty-or-one-employee context instead of a null reference: what does that force every caller to do?

level: juniorimportance: must knowfreq 78%
basics
~20 s

An empty-or-one-value context puts the missing case in the return type, so a caller cannot reach the employee without opening the container: transform the value inside it, or supply a fallback. The possibility of nothing stops being a convention.

open as a page

In a match expression, what does binding a value's parts inside the pattern give you that reading fields in the branch body does not?

level: juniorimportance: must knowfreq 62%
basics
~20 s

Binding in the pattern makes one construct do two jobs: it tests that the value has the case's shape and names the parts of that shape at the same time. The branch body starts with named parts instead of shape checks and accessor calls.

open as a page

What does a compiler's exhaustiveness check on a match over ticket states actually guarantee?

level: juniorimportance: must knowfreq 62%
basics
~20 s

An exhaustiveness check proves at compile time that a match handles every variant its type can hold. The payoff comes later: add a variant and every match with a gap fails the build instead of falling through at run time.

open as a page

In algebraic data types, what distinguishes a payment that is exactly one of card, transfer or credit from a record holding all three?

level: juniorimportance: must knowfreq 72%
basics
~20 s

A sum type holds exactly one of its variants, tagged so you can tell which; a product type holds a value of every component at once. The payment is a sum, the record of all three is a product.

open as a page

When a notification pipeline that loads a recipient, records an attempt and calls a carrier is retried after the carrier fails, which steps run again?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Retrying resubscribes to the source, so every stage above the retry point runs again from the start: the recipient is loaded a second time, a second attempt record is written, and the carrier is called again.

open as a page

A hand-written stream source emits a failure signal and then keeps pushing values — which rule does that break?

level: juniorimportance: must knowfreq 70%
basics
~20 s

The signal grammar: a run carries any number of value signals and then at most one terminal signal, completion or failure, never both. A failure is that ending, not another value, so the source must go silent after it.

open as a page

A chat screen builds a message stream but no request is sent — what act starts the work, and what does it return?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Subscribing starts the work; building a stream only describes it. A subscription call attaches a subscriber to the source, triggers whatever the source does to produce values, and hands back a handle the caller uses to cancel that run.

open as a page

What has happened when a source declared to carry at most one value completes without emitting a value?

level: juniorimportance: must knowfreq 65%
basics
~20 s

Nothing was found and nothing failed: empty completion is a third outcome beside a value and a failure. The caller must decide what absence means here - a default, a fallback source, or an error it raises itself.

open as a page

A checkout display joins a scan feed and a price feed: why does lockstep pairing emit fewer results than latest-value combination?

level: juniorimportance: must knowfreq 58%
basics
~20 s

Lockstep pairing consumes one value from each source per result, so its rate is the slowest source's rate. Latest-value combination keeps each source's most recent value and emits on every arrival, so its rate is the sum of all rates.

open as a page

In a loop that processes a list of pending items, what does break do that continue does not?

level: juniorimportance: must knowfreq 70%
basics
~20 s

break ends the loop itself: control resumes at the first statement after it. continue ends only the current pass, skipping the rest of the body and jumping to the loop's next condition test, so later items are still processed.

open as a page

When a nested block declares a name that an enclosing block already declares, what happens to references to that name inside and after that block?

level: juniorimportance: must knowfreq 62%
basics
~10 s

The inner declaration shadows the outer one: inside that block the name resolves to the new declaration, while the outer binding keeps its own value, untouched, and becomes visible again once the block ends.

open as a page

A compound condition's second operand also writes to a log — when does short-circuit evaluation skip it?

level: juniorimportance: must knowfreq 74%
basics
~20 s

Short-circuit evaluation stops as soon as the result is decided: a short-circuiting AND skips its second operand when the first is false, an OR when the first is true. The skipped operand never runs, so its log write never happens.

open as a page

Under call by value versus call by reference, what exactly does a call copy when a routine is handed a sensor record to fill?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Call by value copies the argument's value into a fresh parameter slot, so assigning to the parameter cannot reach the caller. Call by reference copies the location of the caller's variable, so assigning to the parameter replaces the caller's variable.

open as a page

Go To Statement Considered Harmful is remembered as goto is evil, but what defect in jump-ridden control flow did it actually name?

level: middleimportance: must knowfreq 55%
basics
~20 s

The objection was about reasoning, not taste. With unrestricted jumps you can no longer describe where a running program has got to using a few coordinates, so a position in the text stops telling you what already happened.

open as a page

On the state axis of paradigm classification, what are you measuring when you place an unfamiliar language?

level: juniorimportance: must knowfreq 66%
basics
~20 s

The state axis measures how far a write travels, not whether assignment exists. You are asking whether a step overwrites a value other code still holds, or produces a new value and leaves the old one intact.

open as a page

Why does a chat room's shared mutable participant roster force coordination between delivery threads when an immutable roster does not?

level: juniorimportance: must knowfreq 70%
basics
~20 s

A mutable roster is changed in place, so every reader and every writer must follow one shared discipline or observe a half-applied change. An immutable roster is never written after publication, so a reader that holds one needs no permission from anybody.

open as a page

In a declarative description of desired state, what does stating the result rather than the steps buy you?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Stating the result hands the evaluator the strategy: it derives which operations run, in what order, and whether any are needed. You gain re-runnability, ordering freedom and portability, and give up step-by-step control of how the work is done.

open as a page

In an imperative simulation that assigns each entity a new position every tick, what becomes of the previous position?

level: juniorimportance: must knowfreq 74%
basics
~20 s

Assignment in the imperative model is a destructive update: the storage cell that held the old position now holds the new one. The previous value survives only if the program copied it somewhere before the write.

open as a page

A payroll subroutine changes the pay amount it was given, but the caller still sees the old value — which parameter-passing mode is in use?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Call by value: the routine received a copy of the amount, so its assignment updated only the copy in its own activation record. Call by reference, or returning the new value, would make the update visible to the caller.

open as a page

A marker attached to a class declaration changes nothing on its own — what must exist for it to have any effect?

level: juniorimportance: must knowfreq 60%
basics
~20 s

Attached metadata is inert: something has to read it. A consumer — a build-time processor, a startup scanner, or a check at the call site — must look for that marker and act on what it says, or nothing happens.

open as a page

You declare a metadata type marking rate-limited operations. Why does its declaration name the kinds of declarations it may be attached to?

level: juniorimportance: must knowfreq 62%
basics
~20 s

A metadata type's declaration enumerates the declaration kinds it may be attached to - type, method, field, parameter - and attachments anywhere else are rejected. Target lists turn a misplaced marker into a build error instead of a silent no-op.

open as a page

In a chained configuration API, what makes one call follow another, and what does the closing call add?

level: juniorimportance: must knowfreq 65%
basics
~20 s

Each configuring call returns a receiver carrying everything recorded so far, so the next call can be written straight onto it. The closing call is different: it validates the accumulated state and produces the finished result.

open as a page

In a nested policy notation built from blocks, what does it mean that each block runs against an implicit receiver?

level: juniorimportance: must knowfreq 58%
basics
~20 s

Each block is a piece of code the enclosing call evaluates against an object it supplies, so unqualified calls inside the block configure that object. Nesting blocks builds a tree: an inner block targets the node its enclosing call just created.

open as a page

What does a type's run-time self-description contain that lets a renderer build one column per field of an unknown object?

level: juniorimportance: must knowfreq 68%
basics
~20 s

A loaded type hands back a structured description of itself: its members with their names and declared types, modifier and visibility flags, its supertypes and the contracts it implements, and the type's own run-time identity.

open as a page

An unrestricted placeholder type in a payroll totalling routine — what may its body do with each element?

level: juniorimportance: must knowfreq 66%
basics
~20 s

Only what every type supports: hold it, pass it on, return it. With no limit written, the placeholder is implicitly pinned at the widest type available, so no pay-component operation such as reading an amount is callable on it.

open as a page

Why does a language that discards type arguments reject a run-time test asking whether a value is a stack of text edits?

level: juniorimportance: must knowfreq 62%
basics
~20 s

A run-time test can only read what the value still carries, and the discarded argument is not there. Every stack of edits shares one run-time shape, so the test cannot be decided, and the compiler rejects it instead of guessing.

open as a page

A settings loader is handed the expected type as an argument alongside the key — what does it do with that argument?

level: juniorimportance: must knowfreq 55%
basics
~20 s

The type argument is the evidence the run time no longer carries: the loader uses it to choose how to convert the stored text and to check the converted value before returning it, so a mismatch fails at the read.

open as a page

After compilation on a platform that discards type arguments, what does a stored container value still record about its argument?

level: juniorimportance: must knowfreq 65%
basics
~20 s

Nothing you can ask the value for. The argument is spent during compilation, and what runs is an ordinary container over the erased element shape. Only a declaration, never the object it points at, may keep a written description of it.

open as a page

A connection type carries a message-type placeholder and a standalone helper carries its own - how long is each fixed?

level: juniorimportance: must knowfreq 62%
basics
~20 s

A placeholder introduced on the type is chosen once when an instance is created and every member of that instance shares it. A placeholder introduced on one operation is chosen afresh for each call and is scoped to that call.

open as a page