-
-
Notifications
You must be signed in to change notification settings - Fork 0
Why Generics for Is_Some_And?
|
Note
|
Question: Why does |
The implementation uses a generic formal subprogram:
generic
with function Pred (X : T) return Boolean;
function Is_Some_And (O : Option) return Boolean;In some languages (or non-SPARK Ada), you might expect:
-- NOT what we do:
function Is_Some_And
(O : Option;
Pred : access function (X : T) return Boolean) return Boolean;Access-to-subprogram types are prohibited in SPARK. The library is SPARK_Mode ⇒ On, so we cannot use function pointers:
-- NOT SPARK-compatible
type Predicate is access function (X : T) return Boolean;
-- SPARK-compatible
generic
with function Pred (X : T) return Boolean;
function Is_Some_And (O : Option) return Boolean;With a generic formal, the compiler knows the exact predicate at instantiation time:
function Is_Positive (N : Integer) return Boolean is (N > 0);
function Positive_Check is new Is_Some_And (Pred => Is_Positive);
-- Compiler can inline Is_Positive directly into Positive_CheckWith access-to-subprogram, there’s an indirect call at runtime.
Generic instantiation resolves at compile time - zero indirection, zero function pointer overhead. Critical for embedded/safety-critical systems.
| Concern | Access-to-Subprogram | Generic Formal |
|---|---|---|
SPARK |
Prohibited |
Full support |
Inlining |
Indirect call |
Direct/inlined |
Proof |
Unknown target |
Known at compile time |
Overhead |
Runtime indirection |
Zero |
Syntax |
Slightly simpler |
One-time instantiation |
The generic approach is the idiomatic Ada way for SPARK-compatible higher-order functions.