mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Add utilities for contains? and contains-key?
This is significantly clearer than using (not (nil? (index-of col val))) Most major programming languages offer some sort of contains function (Python, Java, C, Rust). The only exception I know of is C.
This commit is contained in:
		| @@ -120,6 +120,9 @@ | |||||||
| (defn indexed? "Check if x is an array or tuple." [x] | (defn indexed? "Check if x is an array or tuple." [x] | ||||||
|   (def t (type x)) |   (def t (type x)) | ||||||
|   (if (= t :array) true (= t :tuple))) |   (if (= t :array) true (= t :tuple))) | ||||||
|  | (defn collection? "Check if x is an array, tuple, table, or struct" [x] | ||||||
|  |   (def t (type x)) | ||||||
|  |   (if (= t :array) true (if (= t :tuple) true (if (= t :table) true (= t :struct))))) | ||||||
| (defn truthy? "Check if x is truthy." [x] (if x true false)) | (defn truthy? "Check if x is truthy." [x] (if x true false)) | ||||||
| (defn true? "Check if x is true." [x] (= x true)) | (defn true? "Check if x is true." [x] (= x true)) | ||||||
| (defn false? "Check if x is false." [x] (= x false)) | (defn false? "Check if x is false." [x] (= x false)) | ||||||
| @@ -1194,6 +1197,86 @@ | |||||||
|   (def kw (keyword prefix (slice alias 1 -2))) |   (def kw (keyword prefix (slice alias 1 -2))) | ||||||
|   ~(def ,alias :dyn ,;more ,kw)) |   ~(def ,alias :dyn ,;more ,kw)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | (defn- collection-type-error [val] | ||||||
|  |   (errorf "Expected a collection (tuple|array|table|struct), but got %t" val)) | ||||||
|  |  | ||||||
|  | (defn contains-value? | ||||||
|  |   ```Checks if a collection contains the specified value. | ||||||
|  |  | ||||||
|  |   Semantically equivalent to `(contains? (values dict) val)`, | ||||||
|  |   but implemented more efficiently. | ||||||
|  |  | ||||||
|  |   Unlike contains-key?, this has worst-case O(n) performance. | ||||||
|  |   Noe that tables or structs (dictionaries) never contain null keys``` | ||||||
|  |   [collection target-val] | ||||||
|  |   # Avoid allocating intermediate array for dictionary | ||||||
|  |   # This works for both dictionaries and sequences | ||||||
|  |   (cond | ||||||
|  |     (indexed? collection) (not (nil? (index-of target-val collection))) | ||||||
|  |     (dictionary? collection) | ||||||
|  |     (do | ||||||
|  |       (var res false) | ||||||
|  |       (var k (next collection nil)) | ||||||
|  |       (unless (or (nil? k) (nil? target-val)) | ||||||
|  |         (while true | ||||||
|  |           (def val (in collection k)) | ||||||
|  |           (cond | ||||||
|  |             # We found a result, this will break the loop | ||||||
|  |             (= val target-val) (do | ||||||
|  |                                  (set res true) | ||||||
|  |                                  (break)) | ||||||
|  |             # Reached end of dictionary | ||||||
|  |             (nil? k) (break)) | ||||||
|  |           (set k (next collection k)))) | ||||||
|  |       res) | ||||||
|  |     (collection-type-error collection))) | ||||||
|  |  | ||||||
|  | (defn contains-key? | ||||||
|  |   ```Checks if a collection contains the specified key. | ||||||
|  |  | ||||||
|  |   Functions the same as contains? for dictionaries (table/structs). | ||||||
|  |   Arrays and tuples are indexed by integer keys, and this function simply | ||||||
|  |   checks if the index is valid. | ||||||
|  |  | ||||||
|  |   If this function succeeds, then a call to `(in collection key)` is guarenteed | ||||||
|  |   to succeed as well. | ||||||
|  |  | ||||||
|  |   For dictionaries, this should be (approximate) O(1) time due to the | ||||||
|  |   guarentees of table/struct. | ||||||
|  |   For arrays and tuples it should likewise be O(1) because it is simply a comparison. | ||||||
|  |  | ||||||
|  |   Note that this intentionally excludes string (and buffer types), for the same reasons | ||||||
|  |   as `contains?` does. | ||||||
|  |  | ||||||
|  |   Noe that tables or structs (dictionaries) never contain null keys``` | ||||||
|  |   [collection key] | ||||||
|  |   (assert (collection? collection) (collection-type-error collection)) | ||||||
|  |   (not (nil? (get collection key)))) | ||||||
|  |  | ||||||
|  | (defn contains? | ||||||
|  |   ```Checks if a collection contains the specified value (or key). | ||||||
|  |  | ||||||
|  |   For tables and structs, this only checks the keys, | ||||||
|  |   and not the values. | ||||||
|  |  | ||||||
|  |   For arrays and tuples this takes O(n) time, | ||||||
|  |   while for tables and structs this takes (average) O(1) time. | ||||||
|  |    | ||||||
|  |   This intentionally throws an error when strings are encountered. Technically, | ||||||
|  |   strings are an iterable type, they will succeed with `next` and `index-of`. | ||||||
|  |   Interpreting a string as an iterable type, one would expect this to check "contains byte". | ||||||
|  |   However, the user would very probably expect "contains substring". | ||||||
|  |   Therefore, we intentionally forbid strings (and other buffer types). | ||||||
|  |    | ||||||
|  |   Note that dictionaries never contain null keys``` | ||||||
|  |   [collection val] | ||||||
|  |   (cond | ||||||
|  |     (indexed? collection) (not (nil? (index-of val collection))) | ||||||
|  |     (dictionary? collection) (not (nil? (get collection val))) | ||||||
|  |     (collection-type-error collection))) | ||||||
|  |  | ||||||
|  |  | ||||||
| (defdyn *defdyn-prefix* ``Optional namespace prefix to add to keywords declared with `defdyn`. | (defdyn *defdyn-prefix* ``Optional namespace prefix to add to keywords declared with `defdyn`. | ||||||
|   Use this to prevent keyword collisions between dynamic bindings.``) |   Use this to prevent keyword collisions between dynamic bindings.``) | ||||||
| (defdyn *out* "Where normal print functions print output to.") | (defdyn *out* "Where normal print functions print output to.") | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Techcable
					Techcable