1 The [manual chapter on objects](https://ucode-lang.org/manual/) covers the 2 value type, key handling and every builtin in detail. The examples below 3 collect recipes for frequently needed operations that are not part of the 4 core library. 5 6 ## Merging 7 8 Spread expressions merge objects shallowly, later keys winning: 9 10 ```ucode 11 let defaults = { theme: "light", fontSize: 12, notifications: true }; 12 let user = { theme: "dark" }; 13 14 let merged = { ...defaults, ...user }; 15 16 print(merged, "\n"); 17 // { "theme": "dark", "fontSize": 12, "notifications": true } 18 ``` 19 20 For nested objects a recursive version is needed; note the forward 21 declaration, as ucode does not hoist function declarations: 22 23 ```ucode 24 function deepMergeArray; 25 26 function deepMerge(target, ...sources) { 27 for (let source in sources) { 28 if (type(source) != "object") 29 continue; 30 31 for (let key in keys(source)) { 32 if (type(source[key]) == "object" && type(target[key]) == "object") 33 target[key] = deepMerge({ ...target[key] }, source[key]); 34 else if (type(source[key]) == "array" && type(target[key]) == "array") 35 target[key] = deepMergeArray(target[key], source[key]); 36 else 37 target[key] = source[key]; 38 } 39 } 40 41 return target; 42 } 43 44 function deepMergeArray(target, source) { 45 for (let i = 0; i < length(source); i++) { 46 if (type(source[i]) == "object" && type(target[i]) == "object") 47 target[i] = deepMerge({ ...target[i] }, source[i]); 48 else if (type(source[i]) == "array" && type(target[i]) == "array") 49 target[i] = deepMergeArray(target[i], source[i]); 50 else 51 target[i] = source[i]; 52 } 53 54 return target; 55 } 56 57 let profile = { 58 name: "Alice", 59 preferences: { theme: "light", sidebar: { visible: true, width: 250 } } 60 }; 61 62 let updates = { preferences: { theme: "dark", sidebar: { width: 300 } } }; 63 64 deepMerge({}, profile, updates); 65 /* 66 { 67 "name": "Alice", 68 "preferences": { 69 "theme": "dark", 70 "sidebar": { "visible": true, "width": 300 } 71 } 72 } 73 */ 74 ``` 75 76 ## Filtering and mapping 77 78 ```ucode 79 function filterObject(obj, filterFn) { 80 let result = {}; 81 82 for (let key in keys(obj)) 83 if (filterFn(key, obj[key])) 84 result[key] = obj[key]; 85 86 return result; 87 } 88 89 let mixed = { a: 1, b: "string", c: 3, d: true, e: 4.5 }; 90 91 filterObject(mixed, (key, value) => 92 type(value) == "int" || type(value) == "double"); 93 // { "a": 1, "c": 3, "e": 4.5 } 94 ``` 95 96 ```ucode 97 function mapObject(obj, mapFn) { 98 let result = {}; 99 100 for (let key in keys(obj)) 101 result[key] = mapFn(key, obj[key]); 102 103 return result; 104 } 105 106 mapObject({ apple: 1.25, banana: 0.75, cherry: 2.50 }, 107 (fruit, price) => price * 0.8); 108 // { "apple": 1, "banana": 0.6, "cherry": 2 } 109 ``` 110 111 ## Caches and lookup tables 112 113 Objects make natural memoization caches, captured by closure: 114 115 ```ucode 116 let fibonacci = (function () { 117 let cache = {}; 118 119 return function fib(n) { 120 if (exists(cache, n)) 121 return cache[n]; 122 123 let result = (n <= 1) ? n : fib(n - 1) + fib(n - 2); 124 cache[n] = result; 125 return result; 126 }; 127 })(); 128 129 fibonacci(40); // 102334155 130 ``` 131 132 Lookup tables replace chains of conditionals, with `??` supplying the 133 fallback: 134 135 ```ucode 136 let statusMessages = { "200": "OK", "404": "Not Found", "500": "Server Error" }; 137 138 let getStatus = (code) => statusMessages[code] ?? "Unknown"; 139 140 getStatus(404); // "Not Found" 141 getStatus(999); // "Unknown" 142 ``` 143 144 ## Deep cloning 145 146 A deep clone re-uses the array and object halves from 147 [the arrays page](tutorial-02-arrays.html); the object half, adapted to start 148 from an object: 149 150 ```ucode 151 function deepCloneArray; 152 153 function deepClone(obj) { 154 if (type(obj) != "object") 155 return obj; 156 157 let clone = {}; 158 159 for (let key in keys(obj)) { 160 if (type(obj[key]) == "object") 161 clone[key] = deepClone(obj[key]); 162 else if (type(obj[key]) == "array") 163 clone[key] = deepCloneArray(obj[key]); 164 else 165 clone[key] = obj[key]; 166 } 167 168 return clone; 169 } 170 ``` 171 172 ## Comparing by value 173 174 Equality operators test reference identity; structural comparison is a 175 recipe, again forward-declared to break the mutual recursion: 176 177 ```ucode 178 function arrayEquals; 179 180 function objectEquals(obj1, obj2) { 181 if (type(obj1) != "object" || type(obj2) != "object") 182 return obj1 === obj2; 183 184 let keys1 = keys(obj1); 185 let keys2 = keys(obj2); 186 187 if (length(keys1) != length(keys2)) 188 return false; 189 190 for (let key in keys1) { 191 if (!exists(obj2, key)) 192 return false; 193 194 if (type(obj1[key]) == "object" && type(obj2[key]) == "object") { 195 if (!objectEquals(obj1[key], obj2[key])) 196 return false; 197 } else if (type(obj1[key]) == "array" && type(obj2[key]) == "array") { 198 if (!arrayEquals(obj1[key], obj2[key])) 199 return false; 200 } else if (obj1[key] !== obj2[key]) { 201 return false; 202 } 203 } 204 205 return true; 206 } 207 208 function arrayEquals(arr1, arr2) { 209 if (length(arr1) != length(arr2)) 210 return false; 211 212 for (let i = 0; i < length(arr1); i++) { 213 if (type(arr1[i]) == "object" && type(arr2[i]) == "object") { 214 if (!objectEquals(arr1[i], arr2[i])) 215 return false; 216 } else if (type(arr1[i]) == "array" && type(arr2[i]) == "array") { 217 if (!arrayEquals(arr1[i], arr2[i])) 218 return false; 219 } else if (arr1[i] !== arr2[i]) { 220 return false; 221 } 222 } 223 224 return true; 225 } 226 ``` 227 228 ## Iterating and sorting 229 230 The two-variable `for ... in` form destructures key and value: 231 232 ```ucode 233 let inventory = { apples: 50, oranges: 25, bananas: 30 }; 234 235 for (let fruit, quantity in inventory) 236 printf("We have %d %s in stock\n", quantity, fruit); 237 ``` 238 239 Objects keep their keys in insertion order, and `sort()` reorders them in 240 place; the compare function receives both keys and both values: 241 242 ```ucode 243 let stock = { apples: 45, bananas: 25, oranges: 30, grapes: 60 }; 244 245 sort(stock, (k1, k2, v1, v2) => v2 - v1); 246 247 for (let fruit, quantity in stock) 248 printf("%s: %d\n", fruit, quantity); 249 // grapes: 60 250 // apples: 45 251 // oranges: 30 252 // bananas: 25 253 ```
This page was automatically generated by LXR 0.3.1. • OpenWrt