Skip to content

Commit 34947de

Browse files
committed
Issue justinethier#206 - Support hash-table-ref default values
1 parent ddd6ff3 commit 34947de

File tree

7 files changed

+48
-29
lines changed

7 files changed

+48
-29
lines changed

ChangeLog.markdown

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
v3.19.2
22
--------
33

4+
New Features:
5+
6+
- Allow a `default` thunk to be passed to `hash-table-ref`.
7+
- Added `hash-table-ref/default`.
8+
49
Bug Fixes:
510

611
- Fixed `rational?` to properly handle floating-point numbers.

hs-src/Language/Scheme/Core.hs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ module Language.Scheme.Core
4343
, updateList
4444
, updateVector
4545
, updateByteVector
46+
, hashTblRef
4647
-- * Error handling
4748
, addToCallHistory
4849
, throwErrorWithCallHistory
@@ -1075,7 +1076,7 @@ nullEnvWithImport :: IO Env
10751076
nullEnvWithImport = nullEnv >>=
10761077
(flip extendEnv [
10771078
((varNamespace, "%import"), EvalFunc evalfuncImport),
1078-
((varNamespace, "hash-table-ref"), IOFunc $ wrapHashTbl hashTblRef)])
1079+
((varNamespace, "hash-table-ref"), EvalFunc hashTblRef)])
10791080

10801081
-- |Load the standard r5rs environment, including libraries
10811082
r5rsEnv :: IO Env
@@ -1426,6 +1427,7 @@ evalFunctions = [ ("apply", evalfuncApply)
14261427
, ("current-environment", evalfuncInteractionEnv)
14271428
, ("interaction-environment", evalfuncInteractionEnv)
14281429
, ("make-environment", evalfuncMakeEnv)
1430+
, ("hash-table-ref", hashTblRef)
14291431

14301432
-- Non-standard extensions
14311433
#ifdef UseFfi
@@ -1452,3 +1454,36 @@ addToCallHistory :: LispVal -> [LispVal] -> [LispVal]
14521454
addToCallHistory f history
14531455
| null history = [f]
14541456
| otherwise = (lastN' 9 history) ++ [f]
1457+
1458+
-- | Retrieve the value from the hashtable for the given key.
1459+
-- An error is thrown if the key is not found.
1460+
--
1461+
-- Note this had to be made an EvalFunc because a thunk
1462+
-- can be passed as an optional argument to be executed
1463+
-- if the key is not found.
1464+
--
1465+
-- Arguments:
1466+
--
1467+
-- * Current continuation
1468+
-- * HashTable to copy
1469+
-- * Object that is the key to query the table for
1470+
--
1471+
-- Returns: Object containing the key's value
1472+
--
1473+
hashTblRef :: [LispVal] -> IOThrowsError LispVal
1474+
hashTblRef [_, (HashTable ht), key] = do
1475+
case Data.Map.lookup key ht of
1476+
Just val -> return val
1477+
Nothing -> throwError $ BadSpecialForm "Hash table does not contain key" key
1478+
hashTblRef [cont, (HashTable ht), key, thunk] = do
1479+
case Data.Map.lookup key ht of
1480+
Just val -> return $ val
1481+
Nothing -> apply cont thunk []
1482+
{- FUTURE: a thunk can optionally be specified, this drives definition of /default
1483+
Nothing -> apply thunk [] -}
1484+
hashTblRef (cont : p@(Pointer _ _) : args) = do
1485+
ht <- derefPtr p
1486+
hashTblRef (cont : ht : args)
1487+
hashTblRef [_, badType] = throwError $ TypeMismatch "hash-table" badType
1488+
hashTblRef badArgList = throwError $ NumArgs (Just 2) (tail badArgList)
1489+

hs-src/Language/Scheme/Environments.hs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ ioPrimitives = [("open-input-file", makePort openFile ReadMode ),
132132

133133
("hash-table?", wrapHashTbl isHashTbl),
134134
("hash-table-exists?",wrapHashTbl hashTblExists),
135-
("hash-table-ref", wrapHashTbl hashTblRef),
136135
("hash-table-size", wrapHashTbl hashTblSize),
137136
("hash-table->alist", wrapHashTbl hashTbl2List),
138137
("hash-table-keys", wrapHashTbl hashTblKeys),

hs-src/Language/Scheme/Primitives.hs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ module Language.Scheme.Primitives (
4444
, byteVectorStr2Utf
4545
-- ** Hash Table
4646
, hashTblExists
47-
, hashTblRef
4847
, hashTblSize
4948
, hashTbl2List
5049
, hashTblKeys
@@ -1217,31 +1216,6 @@ hashTblExists [(HashTable ht), key] = do
12171216
hashTblExists [] = throwError $ NumArgs (Just 2) []
12181217
hashTblExists args@(_ : _) = throwError $ NumArgs (Just 2) args
12191218

1220-
-- | Retrieve the value from the hashtable for the given key.
1221-
-- An error is thrown if the key is not found.
1222-
--
1223-
-- Arguments:
1224-
--
1225-
-- * HashTable to copy
1226-
--
1227-
-- * Object that is the key to query the table for
1228-
--
1229-
-- Returns: Object containing the key's value
1230-
--
1231-
hashTblRef :: [LispVal] -> ThrowsError LispVal
1232-
hashTblRef [(HashTable ht), key] = do
1233-
case Data.Map.lookup key ht of
1234-
Just val -> return val
1235-
Nothing -> throwError $ BadSpecialForm "Hash table does not contain key" key
1236-
hashTblRef [(HashTable ht), key, Func {}] = do
1237-
case Data.Map.lookup key ht of
1238-
Just val -> return $ val
1239-
Nothing -> throwError $ NotImplemented "thunk"
1240-
{- FUTURE: a thunk can optionally be specified, this drives definition of /default
1241-
Nothing -> apply thunk [] -}
1242-
hashTblRef [badType] = throwError $ TypeMismatch "hash-table" badType
1243-
hashTblRef badArgList = throwError $ NumArgs (Just 2) badArgList
1244-
12451219
-- | Return the number of key/value associations in the hashtable
12461220
--
12471221
-- Arguments:

lib/core.scm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,9 @@
404404
(exit-fail))
405405

406406
;; Hashtable derived forms
407+
(define (hash-table-ref/default ht key default)
408+
(hash-table-ref ht key (lambda () default)))
409+
407410
(define hash-table-walk
408411
(lambda (ht proc)
409412
(map

lib/srfi/69.sld

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
;hash-table-equivalence-function
77
;hash-table-hash-function
88
hash-table-ref
9-
;hash-table-ref/default
9+
hash-table-ref/default
1010
;hash-table-set!
1111
;TODO: should implement this: hash-table-delete!
1212
hash-table-exists?

tests/t-hashtable.scm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
(hash-table-merge! ht test-ht2)
5757
(assert/equal (hash-table-ref ht "test") "testing")
5858

59+
;; Test default values
60+
(assert/equal (hash-table-ref/default (make-hash-table) 2 #f) #f)
61+
5962
(define ht (make-hash-table))
6063
(hash-table-set! ht 1 1)
6164
(hash-table-set! ht 2 2)

0 commit comments

Comments
 (0)