Repository navigation
Context in gleam #5206
Replies: 4 comments
How this differs from implicit argumentsAt first glance, this proposal may resemble implicit arguments, but the overlap is mostly superficial. What implicit arguments areIn language design terms, implicit arguments are:
Examples include:
Key properties:
Where the ideas overlapThere is genuine overlap in motivation:
These similarities explain why the idea can be misclassified as implicit arguments. Where this proposal fundamentally differs1. Context is not a parameter — it is a primary abstractionImplicit arguments are still arguments. This proposal treats context as a first-class language construct, not as a hidden parameter list. Functions do not receive context. This shifts the mental model from:
to:
2. Context composition and narrowing are language operationsImplicit arguments provide no notion of context algebra. This proposal introduces:
A function requiring This is not parameter passing — it is structural compatibility between environments. 3. Flat accessibility, not navigational accessWith implicit arguments, values are still accessed through identifiers tied to bindings: logger.info(...)
config.timeoutThis proposal models context as a flat lexical environment, where required properties become directly accessible: The context behaves like a locally injected scope, not an object or parameter bundle. 4. Context is both an environment and a valueImplicit arguments are not first-class values. Here, a context can be:
Both implicit and explicit forms are equivalent and interoperable. This duality does not exist in traditional implicit argument systems. 5. Universal applicability beyond functionsImplicit arguments apply only to function calls. This proposal uses the same mechanism uniformly for:
It is not a convenience feature — it is an organizing principle. SummaryA precise distinction would be:
Or more directly:
|
Testability as a first-class propertyOne practical consequence of treating context as a language abstraction is that testability emerges naturally, without additional patterns or frameworks. Context initialization defines the execution environmentIn this model, behavior is constant, while context varies. The same function can be executed in different environments simply by initializing a different context:
No mocking framework or dependency injection container is required. No global state, no hidden wiringTraditional approaches often rely on:
With explicit contexts:
A function cannot accidentally access production resources in a test unless the context explicitly provides them. Testing by substitution, not interceptionTesting becomes a matter of context substitution, not call interception. For example:
The function itself remains unchanged. This avoids:
Minimal contexts improve test focusBecause functions declare minimal context requirements, tests only need to construct the subset that is actually used. A function that requires
This leads to:
Deterministic execution by constructionSince side effects are expressed exclusively through context:
can all be controlled at the boundary. Determinism is achieved by context design, not by convention. SummaryContext-based programming does not add testability as a feature —
This applies uniformly across:
|
Core Principles of Context-Oriented Programming1. Context as the Primary AbstractionPrograms are structured around contexts, not classes or modules. A context represents a structured environment of data and capabilities in which functions execute. 2. Requirements Instead of Explicit DependenciesFunctions declare what they require from their environment, not how it is passed. A function specifies the minimal set of data and capabilities it needs. 3. Automatic Lexical Context PropagationContexts are propagated automatically through lexical scope. If a required context is available in the surrounding environment, it is implicitly bound. 4. Structural Compatibility and Minimal VisibilityContext compatibility is structural, and visibility is minimal by default. A function can operate in any context that structurally satisfies its requirements. 5. Explicit Effects via ContextAll side effects are enabled explicitly through context. IO, logging, persistence, time, randomness, and external interactions are not implicit. One-sentence summary (FP-style)
Relationship to existing paradigms
|
|
Hello. This is a very large amount of generated context, and from skimming it I can see many inaccuracies. It is not possible to handle requests like these, it would take too much time. I'm going to close this. Please feel to make a new issue, but you must not generate your posts, and you must be concise, otherwise it will be closed too. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Problem: Expressing and Propagating Execution Context in Gleam Applications
Hello!
I’d like to discuss a recurring problem I’ve encountered while building real-world Gleam applications (bots, backend services, integrations), and to get feedback on whether this is something that should remain a library-level concern or could benefit from language-level support.
Background
In non-trivial Gleam applications, functions often need access to execution context such as:
A common pattern is to represent this as a record and pass it explicitly.
Problem 1: Overly Wide Contexts in Function Signatures
Many functions only need a small subset of the context, but are forced to accept the entire record.
In this example,
validate/2only depends onlogger, but its signature suggests a dependency on the full application environment.As the context grows, this leads to:
Problem 2: Manually Passing Only Required Values Does Not Scale
An alternative is to pass only the required values:
This improves precision but introduces new issues:
In practice, this quickly becomes cumbersome.
Problem 3: Smaller Context Types Lead to Duplication
Another approach is to define multiple smaller context records:
While this improves precision, it also introduces:
This becomes harder to maintain as the number of contexts grows.
Problem 4: Module-Level Access Hides Dependencies
While Gleam does not have implicit global mutable state, dependencies can still become implicit when accessed via modules or closures.
Here,
process/1appears pure from its signature, but performs logging internally.The dependency exists, but is not visible to the type system or the caller.
This makes:
Problem 5: Business Logic Also Depends on Context
This is not limited to infrastructure.
Business rules often depend on situational data:
Example:
Over time, such functions accumulate flags and parameters that are not part of the domain model itself, but still influence behavior.
Embedding these concerns into domain types or widening signatures does not scale well.
Problem 6: Composing Independent Concerns Becomes Difficult
In practice, applications often interact with multiple independent systems:
These concerns are orthogonal, but current patterns tend to collapse them into a single “environment” record or scatter them across modules.
This makes it hard to:
Summary of the Problem
In current Gleam applications, developers must choose between:
There is currently no way to:
Desired Properties of a Solution
A potential solution should:
Open Question
Is this class of problems something that Gleam intentionally leaves to library-level patterns, or could it benefit from a language-level abstraction for expressing and propagating execution context?
Possible Direction: Treating Context as a First-Class Language Abstraction
Based on the problems described above, one possible direction is to treat execution context as a first-class language concept, rather than modeling it indirectly via records, modules, or argument plumbing.
This section outlines a possible approach, focusing on expressiveness and clarity, not on final syntax or implementation details.
Core Idea
A context represents a structured environment of data and capabilities that is:
Functions declare what context they need, rather than how it is passed.
Example 1: Infrastructure Context (Logging)
Key properties:
Example 2: Business Logic Context (Policy)
Here:
Orderremains unchanged,Example 3: Same Function, Different Behavior
The function:
Example 4: Independent Data Sources (Vertical Concerns)
Database and cache are:
Example 5: External Integration (HTTP Client)
This dependency:
Example 6: Cross-Cutting Concerns (Metrics + Logging)
Cross-cutting concerns:
Example 7: Composition Without a God Context
There is:
AppContext,Each function sees only what it requires.
Example 8: Same Logic, Different Environments
Background Job
CLI Tool
The same domain logic:
Example 9: Context Assembly at the Boundary
Contexts are created explicitly at system boundaries:
This keeps:
Why This Is Different from Existing Patterns
Compared to current approaches, this model:
Contexts act as a structural layer between types and functions.
Summary
This approach allows:
All reactions