From bd76eddb74c91b879371b9fe8a44622fc6f41967 Mon Sep 17 00:00:00 2001 From: Yogthos Date: Sat, 6 Jun 2026 21:54:07 -0400 Subject: [PATCH] phm: preserve nil-valued keys in get/keys/vals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit phm-get returned the default for a key present with a nil value; fix it to presence-check the bucket so a nil value reads back as nil, not the default. core-keys/core-vals went through phm-to-struct, which drops nil-valued keys — read phm-entries directly instead so those keys survive. Isolated phm correctness only; no map-representation change. Battery holds at 3919, conformance 218/218 in all three modes. The earlier -8 came from assoc's struct->phm promotion, not these accessors. --- src/jolt/core.janet | 5 +++-- src/jolt/phm.janet | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/jolt/core.janet b/src/jolt/core.janet index 884a744..6d759a7 100644 --- a/src/jolt/core.janet +++ b/src/jolt/core.janet @@ -655,10 +655,11 @@ (do (var result @{}) (each m maps (each k (if (phm? m) (keys (phm-to-struct m)) (keys m)) (let [existing (result k)] (put result k (if (nil? existing) (m k) (f existing (m k))))))) (table/to-struct result)))) (defn core-keys [m] - (if (phm? m) (tuple ;(keys (phm-to-struct m))) (tuple ;(keys m)))) + # phm-entries (not phm-to-struct) so keys mapped to nil values are not dropped. + (if (phm? m) (tuple ;(map |(in $ 0) (phm-entries m))) (tuple ;(keys m)))) (defn core-vals [m] - (if (phm? m) (do (def s (phm-to-struct m)) (tuple ;(map |(s $) (keys s)))) (tuple ;(map |(m $) (keys m))))) + (if (phm? m) (tuple ;(map |(in $ 1) (phm-entries m))) (tuple ;(map |(m $) (keys m))))) (defn core-select-keys [m ks] (var result @{}) diff --git a/src/jolt/phm.janet b/src/jolt/phm.janet index a4a24bd..646b297 100644 --- a/src/jolt/phm.janet +++ b/src/jolt/phm.janet @@ -72,7 +72,11 @@ (defn phm-get [m k &opt default] (default default nil) (let [bucket (get (m :buckets) (phm-hash-key k))] - (if bucket (let [v (phm-bucket-find bucket k)] (if (nil? v) default v)) default))) + # presence-check, not nil-of-value: a key mapped to nil is still present, + # so return nil (not the default) when the key exists with a nil value. + (if (and bucket (phm-bucket-contains? bucket k)) + (phm-bucket-find bucket k) + default))) (defn phm-assoc [m k v] (let [cnt (m :cnt) idx (phm-hash-key k)